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.

799 lines
21 KiB

  1. // ChatCtl.cpp : Implementation of DLL Exports.
  2. // Note: Proxy/Stub Information
  3. // To build a separate proxy/stub DLL,
  4. // run nmake -f ChatCtlps.mk in the project directory.
  5. #include "precomp.h"
  6. #include "NmCtl1.h"
  7. #include "Comboboxex.h"
  8. #include <confguid.h>
  9. BYTE szStr[MAX_PATH];
  10. GCCRequestTag GccTag;
  11. extern CChatObj *g_pChatObj;
  12. extern CNmChatCtl *g_pChatWindow;
  13. extern HANDLE g_hWorkThread;
  14. GUID guidNM2Chat = { 0x340f3a60, 0x7067, 0x11d0, { 0xa0, 0x41, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0 } };
  15. #define cbKeyApp (4 + 1 + sizeof(GUID) + sizeof(DWORD))
  16. static unsigned char H221IDGUID[5] = {H221GUIDKEY0,
  17. H221GUIDKEY1,
  18. H221GUIDKEY2,
  19. H221GUIDKEY3,
  20. H221GUIDKEY4};
  21. static BYTE s_keyApp[cbKeyApp];
  22. // Create an H.221 application key with a guid
  23. VOID CreateH221AppKeyFromGuid(LPBYTE lpb, GUID * pguid)
  24. {
  25. CopyMemory(lpb, H221IDGUID, sizeof(H221IDGUID));
  26. CopyMemory(lpb + sizeof(H221IDGUID), pguid, sizeof(GUID));
  27. }
  28. /* S E T A P P K E Y */
  29. /*----------------------------------------------------------------------------
  30. %%Function: SetAppKey
  31. Set the two pieces of an OctetString (the length and the data.)
  32. Note that the length always includes the terminating null character.
  33. ----------------------------------------------------------------------------*/
  34. VOID SetAppKey(LPOSTR pOct, LPBYTE lpb)
  35. {
  36. pOct->length = cbKeyApp;
  37. pOct->value = lpb;
  38. }
  39. /* C R E A T E A P P K E Y */
  40. /*----------------------------------------------------------------------------
  41. %%Function: CreateAppKey
  42. Given a guid and a userid, create the appropriate application key.
  43. The key is formated as:
  44. 0xB5 0x00 0x53 0x4C - Microsoft Object Identifier
  45. 0x01 - guid identifier
  46. <binary guid> - guid data
  47. <dword node id> - user node id
  48. ----------------------------------------------------------------------------*/
  49. VOID CreateAppKey(LPBYTE lpb, GUID * pguid, DWORD dwUserId)
  50. {
  51. CreateH221AppKeyFromGuid(lpb, pguid);
  52. CopyMemory(lpb + cbKeyApp - sizeof(DWORD), &dwUserId, sizeof(DWORD));
  53. }
  54. #define NODE_ID_ONLY 0x01
  55. #define SEND_ID_ONLY 0x02
  56. #define PRIVATE_SEND_ID_ONLY 0x04
  57. #define WHISPER_ID_ONLY 0x08
  58. #define ALL_IDS 0x10
  59. /*
  60. ** Return the array index of the first duplicate copy
  61. */
  62. int IsAlreadyInArray(MEMBER_CHANNEL_ID *aArray, MEMBER_CHANNEL_ID *pMember, int nSize, int nFlag)
  63. {
  64. int i;
  65. for (i = 0; i < nSize; i++)
  66. {
  67. if (NODE_ID_ONLY == nFlag)
  68. {
  69. if (aArray[i].nNodeId == pMember->nNodeId)
  70. break;
  71. }
  72. else if (SEND_ID_ONLY == nFlag)
  73. {
  74. if (aArray[i].nSendId == pMember->nSendId)
  75. break;
  76. }
  77. else if (PRIVATE_SEND_ID_ONLY == nFlag)
  78. {
  79. if (aArray[i].nPrivateSendId == pMember->nPrivateSendId)
  80. break;
  81. }
  82. else if (WHISPER_ID_ONLY)
  83. {
  84. if (aArray[i].nWhisperId == pMember->nWhisperId)
  85. break;
  86. }
  87. else if (ALL_IDS == nFlag)
  88. {
  89. if ((aArray[i].nNodeId == pMember->nNodeId)&&
  90. (aArray[i].nSendId == pMember->nSendId)&&
  91. (aArray[i].nPrivateSendId == pMember->nPrivateSendId)&&
  92. (aArray[i].nWhisperId == pMember->nWhisperId))
  93. break;
  94. }
  95. }
  96. return (i < nSize)?i:-1;
  97. }
  98. void ChatTimerProc(HWND hWnd, UINT uMsg, UINT_PTR nTimerID, DWORD dwTime)
  99. {
  100. if (g_pChatObj)
  101. {
  102. g_pChatObj->SearchWhisperId();
  103. }
  104. }
  105. #include "NmCtlDbg.h"
  106. HINSTANCE g_hInstance;
  107. /////////////////////////////////////////////////////////////////////////////
  108. // DLL Entry Point
  109. extern "C"
  110. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
  111. {
  112. if (dwReason == DLL_PROCESS_ATTACH)
  113. {
  114. MyInitDebugModule();
  115. DisableThreadLibraryCalls(hInstance);
  116. g_hInstance = hInstance;
  117. DBG_INIT_MEMORY_TRACKING(hInstance);
  118. ::T120_AppletStatus(APPLET_ID_CHAT, APPLET_LIBRARY_LOADED);
  119. }
  120. else if (dwReason == DLL_PROCESS_DETACH)
  121. {
  122. if (NULL != g_hWorkThread)
  123. {
  124. ::CloseHandle(g_hWorkThread);
  125. }
  126. ::T120_AppletStatus(APPLET_ID_CHAT, APPLET_LIBRARY_FREED);
  127. DBG_CHECK_MEMORY_TRACKING(hDllInst);
  128. MyExitDebugModule();
  129. }
  130. return TRUE; // ok
  131. }
  132. //
  133. // T120 Applet Functions
  134. //
  135. void CALLBACK T120AppletCallbackProc
  136. (
  137. T120AppletMsg *pMsg
  138. )
  139. {
  140. CChatObj *pCHATOBJ = (CChatObj *) pMsg->pAppletContext;
  141. if (pCHATOBJ == g_pChatObj)
  142. {
  143. switch (pMsg->eMsgType)
  144. {
  145. case GCC_PERMIT_TO_ENROLL_INDICATION:
  146. pCHATOBJ->OnPermitToEnroll(pMsg->PermitToEnrollInd.nConfID,
  147. pMsg->PermitToEnrollInd.fPermissionGranted);
  148. break;
  149. case T120_JOIN_SESSION_CONFIRM:
  150. default:
  151. break;
  152. }
  153. }
  154. }
  155. void CALLBACK T120SessionCallbackProc
  156. (
  157. T120AppletSessionMsg *pMsg
  158. )
  159. {
  160. if(g_pChatObj == NULL)
  161. {
  162. return;
  163. }
  164. CChatObj *pSession = (CChatObj *) pMsg->pSessionContext;
  165. ASSERT(pMsg->pAppletContext == pMsg->pSessionContext);
  166. if (pSession == g_pChatObj)
  167. {
  168. ASSERT(pMsg->nConfID == pSession->GetConfID());
  169. switch (pMsg->eMsgType)
  170. {
  171. case MCS_UNIFORM_SEND_DATA_INDICATION:
  172. //
  173. // Check if we are receiving a indication from owrself
  174. //
  175. if(pMsg->SendDataInd.initiator == GET_USER_ID_FROM_MEMBER_ID(g_pChatObj->m_MyMemberID))
  176. {
  177. return;
  178. }
  179. case MCS_SEND_DATA_INDICATION:
  180. MCSSendDataIndication(
  181. pMsg->SendDataInd.user_data.length,
  182. pMsg->SendDataInd.user_data.value,
  183. pMsg->SendDataInd.channel_id,
  184. pMsg->SendDataInd.initiator);
  185. break;
  186. case MCS_TRANSMIT_BUFFER_AVAILABLE_INDICATION:
  187. // m_fWaitingForBufferAvailable = FALSE;
  188. break;
  189. case GCC_APP_ROSTER_REPORT_INDICATION:
  190. pSession->OnRosterIndication((ULONG) pMsg->AppRosterReportInd.cRosters, pMsg->AppRosterReportInd.apAppRosters);
  191. break;
  192. case T120_JOIN_SESSION_CONFIRM:
  193. pSession->OnJoinSessionConfirm(&pMsg->JoinSessionConfirm);
  194. break;
  195. case GCC_RETRIEVE_ENTRY_CONFIRM:
  196. // Asynchronous Registry Retrieve Confirm message
  197. pSession->OnRegistryEntryConfirm(&pMsg->RegistryConfirm);
  198. break;
  199. default:
  200. break;
  201. }
  202. }
  203. }
  204. CChatObj::CChatObj() :
  205. m_pApplet(NULL),
  206. m_aMembers(&g_aMembers[0]),
  207. m_nTimerID(0)
  208. {
  209. DBGENTRY(CChatObj::CChatObj);
  210. // Construct GCCAppProtEntityList
  211. ::ZeroMemory(&m_ChatProtocolEnt, sizeof(m_ChatProtocolEnt));
  212. m_ChatProtocolEnt.must_be_invoked = TRUE;
  213. m_ChatProtocolEnt.number_of_expected_capabilities = 0;
  214. m_ChatProtocolEnt.expected_capabilities_list = NULL;
  215. m_ChatProtocolEnt.startup_channel_type = MCS_DYNAMIC_MULTICAST_CHANNEL;
  216. // construct the applet key
  217. m_ChatProtocolEnt.session_key.application_protocol_key.key_type = APPLET_H221_NONSTD_KEY;
  218. SetAppKey(&m_ChatProtocolEnt.session_key.application_protocol_key.h221_non_standard_id, szStr);
  219. ::CreateH221AppKeyFromGuid(szStr, (GUID *)&guidNM2Chat );
  220. // ape list
  221. m_pChatProtocolEnt = &m_ChatProtocolEnt;
  222. m_AppProtoEntList.cApes = 1;
  223. m_AppProtoEntList.apApes = &m_pChatProtocolEnt;
  224. // broadcast
  225. ::ZeroMemory(&m_NodeList, sizeof(m_NodeList));
  226. // Cleanup per-conference T.120 info
  227. CleanupPerConf();
  228. // set the global pointer
  229. g_pChatObj = this;
  230. // T.120 Applet
  231. T120Error rc = ::T120_CreateAppletSAP(&m_pApplet);
  232. if (T120_NO_ERROR != rc)
  233. {
  234. ERROR_OUT(("CChatObj::CChatObj: cannot create applet SAP"));
  235. return;
  236. }
  237. ASSERT(NULL != m_pApplet);
  238. m_pApplet->Advise(T120AppletCallbackProc, this);
  239. DBGEXIT(CChatObj::CChatObj);
  240. }
  241. CChatObj::~CChatObj()
  242. {
  243. DBGENTRY(CChatObj::~CChatObj);
  244. ASSERT(NULL == m_pAppletSession);
  245. ASSERT(NULL == m_pApplet);
  246. delete g_pChatWindow;
  247. DBGEXIT(CChatObj::~CChatObj);
  248. }
  249. void CChatObj::LeaveT120(void)
  250. {
  251. // no more T.120
  252. if (NULL != m_pAppletSession)
  253. {
  254. m_pAppletSession->ReleaseInterface();
  255. CleanupPerConf();
  256. }
  257. if (NULL != m_pApplet)
  258. {
  259. m_pApplet->ReleaseInterface();
  260. m_pApplet = NULL;
  261. }
  262. }
  263. void CChatObj::OnPermitToEnroll
  264. (
  265. T120ConfID nConfID,
  266. BOOL fPermissionGranted
  267. )
  268. {
  269. if (fPermissionGranted)
  270. {
  271. // We are not in a conference, right?
  272. ASSERT(NULL == m_pAppletSession);
  273. // Create an applet session
  274. T120Error rc = m_pApplet->CreateSession(&m_pAppletSession, nConfID);
  275. if (T120_NO_ERROR == rc)
  276. {
  277. ASSERT(NULL != m_pAppletSession);
  278. m_pAppletSession->Advise(T120SessionCallbackProc, this, this);
  279. // Build join-sesion request
  280. ::ZeroMemory(&m_JoinSessionReq, sizeof(m_JoinSessionReq));
  281. m_JoinSessionReq.dwAttachmentFlags = ATTACHMENT_DISCONNECT_IN_DATA_LOSS | ATTACHMENT_MCS_FREES_DATA_IND_BUFFER;
  282. // Non standard key
  283. CreateAppKey(s_keyApp, &guidNM2Chat, 0);
  284. GCCObjectKey FAR * pObjKey;
  285. pObjKey = &m_JoinSessionReq.SessionKey.application_protocol_key;
  286. pObjKey->key_type = GCC_H221_NONSTANDARD_KEY;
  287. SetAppKey(&(pObjKey->h221_non_standard_id), s_keyApp);
  288. m_JoinSessionReq.SessionKey.session_id = m_sidMyself;
  289. m_JoinSessionReq.fConductingCapable = FALSE;
  290. m_JoinSessionReq.nStartupChannelType =MCS_DYNAMIC_MULTICAST_CHANNEL;
  291. //
  292. // Retrieve registry key
  293. //
  294. ::ZeroMemory(&m_resourceRequest, sizeof(m_resourceRequest));
  295. m_resourceRequest.eCommand = APPLET_JOIN_DYNAMIC_CHANNEL;
  296. m_resourceRequest.RegKey.session_key = m_JoinSessionReq.SessionKey;
  297. SetAppKey(&m_resourceRequest.RegKey.resource_id, s_keyApp);
  298. m_JoinSessionReq.cResourceReqs = 1;
  299. m_JoinSessionReq.aResourceReqs = &m_resourceRequest;
  300. // Join now
  301. rc = m_pAppletSession->Join(&m_JoinSessionReq);
  302. if (T120_NO_ERROR == rc)
  303. {
  304. m_nConfID = nConfID;
  305. }
  306. else
  307. {
  308. WARNING_OUT(("CChatObj::OnPermitToEnroll: cannot join conf=%u, rc=%u", nConfID, rc));
  309. }
  310. }
  311. }
  312. else
  313. {
  314. if (NULL != m_pAppletSession)
  315. {
  316. T120RegistryRequest Req;
  317. ::ZeroMemory(&Req, sizeof(Req));
  318. Req.eCommand = APPLET_DELETE_ENTRY;
  319. Req.pRegistryKey = &m_resourceRequest.RegKey;
  320. m_pAppletSession->RegistryRequest(&Req);
  321. m_pAppletSession->ReleaseInterface();
  322. CleanupPerConf();
  323. }
  324. }
  325. }
  326. void CChatObj::OnJoinSessionConfirm
  327. (
  328. T120JoinSessionConfirm *pConfirm
  329. )
  330. {
  331. if (NULL != m_pAppletSession)
  332. {
  333. ASSERT(m_pAppletSession == pConfirm->pIAppletSession);
  334. if (T120_RESULT_SUCCESSFUL == pConfirm->eResult)
  335. {
  336. m_uidMyself = pConfirm->uidMyself;
  337. m_sidMyself = pConfirm->sidMyself;
  338. m_eidMyself = pConfirm->eidMyself;
  339. m_nidMyself = pConfirm->nidMyself;
  340. // get the broadcast channel
  341. m_broadcastChannel = pConfirm->aResourceReqs[0].nChannelID;
  342. // create member ID
  343. m_MyMemberID = MAKE_MEMBER_ID(m_nidMyself, m_uidMyself);
  344. // we are now in the conference
  345. m_fInConference = TRUE;
  346. if(g_pChatWindow)
  347. {
  348. g_pChatWindow->_UpdateContainerCaption();
  349. g_pChatWindow->_AddEveryoneInChat();
  350. }
  351. // Invoke applet on other nodes (for interop with NM 2.x)
  352. InvokeApplet();
  353. // Register channel with GCC (for interop with NM 2.x)
  354. T120RegistryRequest Req;
  355. GCCRegistryKey registry_key;
  356. BYTE SessionKey[cbKeyApp];
  357. BYTE ResourceKey[cbKeyApp];
  358. ::ZeroMemory(&Req, sizeof(Req));
  359. Req.eCommand = APPLET_REGISTER_CHANNEL;
  360. ::CopyMemory(&registry_key.session_key,
  361. &m_resourceRequest.RegKey.session_key, sizeof(GCCSessionKey));
  362. CreateAppKey(SessionKey, &guidNM2Chat, 0);
  363. CreateAppKey(ResourceKey, &guidNM2Chat, m_nidMyself);
  364. SetAppKey(&registry_key.session_key.application_protocol_key.h221_non_standard_id, SessionKey);
  365. SetAppKey(&registry_key.resource_id, ResourceKey);
  366. Req.pRegistryKey = &registry_key;
  367. Req.nChannelID = m_uidMyself;
  368. m_pAppletSession->RegistryRequest(&Req);
  369. }
  370. else
  371. {
  372. WARNING_OUT(("CChatObj::OnJoinSessionConfirm: failed to join conference, result=%u. error=%u", pConfirm->eResult, pConfirm->eError));
  373. m_pAppletSession->ReleaseInterface();
  374. CleanupPerConf();
  375. }
  376. }
  377. }
  378. void CChatObj::InvokeApplet(void)
  379. {
  380. m_ChatProtocolEnt.session_key.session_id = m_sidMyself;
  381. if (m_pAppletSession)
  382. {
  383. m_pAppletSession->InvokeApplet(&m_AppProtoEntList, &m_NodeList, &GccTag);
  384. }
  385. }
  386. void CChatObj::OnRosterIndication
  387. (
  388. ULONG cRosters,
  389. GCCAppRoster *apRosters[]
  390. )
  391. {
  392. if (IsInConference())
  393. {
  394. BOOL fAdded = FALSE;
  395. BOOL fRemoved = FALSE;
  396. ULONG cOtherMembers = 0;
  397. ULONG i, j, k;
  398. // Caculate how many members in this session
  399. for (i = 0; i < cRosters; i++)
  400. {
  401. GCCAppRoster *pRoster = apRosters[i];
  402. // bail out if this roster is not for this session
  403. if (pRoster->session_key.session_id != m_sidMyself)
  404. {
  405. continue;
  406. }
  407. // node added or removed?
  408. fAdded |= pRoster->nodes_were_added;
  409. fRemoved |= pRoster->nodes_were_removed;
  410. // parse the roster records
  411. for (j = 0; j < pRoster->number_of_records; j++)
  412. {
  413. GCCAppRecord *pRecord = pRoster->application_record_list[j];
  414. // Because the flag is_enrolled_actively is not set correctly in
  415. // NM 2.11, we don't bother to check it.
  416. // MEMBER_ID nMemberID = MAKE_MEMBER_ID(pRecord->node_id, pRecord->application_user_id);
  417. if (pRecord->node_id != m_nidMyself)
  418. {
  419. cOtherMembers++;
  420. }
  421. } // for
  422. } // for
  423. // If there are changes, we then do the update
  424. if (fAdded || fRemoved || cOtherMembers != g_pChatWindow->m_cOtherMembers)
  425. {
  426. MEMBER_CHANNEL_ID aTempMembers[MAX_MEMBERS]; // scratch copy
  427. // make sure we are able to handle it
  428. if (cOtherMembers >= MAX_MEMBERS)
  429. {
  430. ERROR_OUT(("CChatObj::OnRosterIndication: we hit the max members limit, cOtherMembers=%u, max-members=%u",
  431. cOtherMembers, MAX_MEMBERS));
  432. cOtherMembers = MAX_MEMBERS;
  433. }
  434. // reset the flags for members added and removed
  435. fAdded = FALSE;
  436. fRemoved = FALSE;
  437. // copy the members
  438. ULONG idxTempMember = 0;
  439. for (i = 0; i < cRosters; i++)
  440. {
  441. GCCAppRoster *pRoster = apRosters[i];
  442. // bail out if this roster is not for this session
  443. if (pRoster->session_key.session_id != m_sidMyself)
  444. {
  445. continue;
  446. }
  447. // parse the roster records
  448. for (j = 0; j < pRoster->number_of_records; j++)
  449. {
  450. GCCAppRecord *pRecord = pRoster->application_record_list[j];
  451. // Because of a bug in NM2.11, we don't check flag is_enrolled_actively
  452. // MEMBER_ID nMemberID = MAKE_MEMBER_ID(pRecord->node_id, pRecord->application_user_id);
  453. if (pRecord->node_id != m_nidMyself && idxTempMember < cOtherMembers)
  454. {
  455. aTempMembers[idxTempMember].nNodeId = pRecord->node_id;
  456. aTempMembers[idxTempMember].nSendId = aTempMembers[idxTempMember].nPrivateSendId =
  457. aTempMembers[idxTempMember].nWhisperId = pRecord->application_user_id;
  458. idxTempMember++;
  459. // let's see if it is an 'add' or a 'delete'
  460. for (k = 0; k < g_pChatWindow->m_cOtherMembers; k++)
  461. {
  462. if (m_aMembers[k].nNodeId == pRecord->node_id)
  463. {
  464. ::ZeroMemory(&m_aMembers[k], sizeof(MEMBER_CHANNEL_ID));
  465. break;
  466. }
  467. }
  468. fAdded |= (k >= g_pChatWindow->m_cOtherMembers); // not found, must be new
  469. }
  470. } // for
  471. } // for
  472. // sanity check
  473. ASSERT(idxTempMember == cOtherMembers);
  474. // see if there are ones that are not in the new roster.
  475. // if so, they must be removed.
  476. for (k = 0; k < g_pChatWindow->m_cOtherMembers; k++)
  477. {
  478. if (m_aMembers[k].nNodeId)
  479. {
  480. fRemoved = TRUE;
  481. g_pChatWindow->_RemoveMember(&m_aMembers[k]);
  482. }
  483. }
  484. // now, update the member array
  485. g_pChatWindow->m_cOtherMembers = cOtherMembers;
  486. if ( g_pChatWindow->m_cOtherMembers)
  487. {
  488. ASSERT(sizeof(m_aMembers[0]) == sizeof(aTempMembers[0]));
  489. ::CopyMemory(&m_aMembers[0], &aTempMembers[0], g_pChatWindow->m_cOtherMembers * sizeof(m_aMembers[0]));
  490. // Setup Send Channel Id
  491. int nDuplicates = 0;
  492. for (k = 0; k < g_pChatWindow->m_cOtherMembers; k++)
  493. {
  494. int nIndex = IsAlreadyInArray(m_aMembers, &m_aMembers[k], k, NODE_ID_ONLY);
  495. if (nIndex >= 0)
  496. {
  497. m_aMembers[nIndex].nSendId = m_aMembers[k].nSendId;
  498. nDuplicates++;
  499. m_aMembers[k].nNodeId = 0;
  500. }
  501. }
  502. // Remove all zeroed out regions
  503. if (nDuplicates)
  504. {
  505. k = 0;
  506. while (k < g_pChatWindow->m_cOtherMembers)
  507. {
  508. if (0 == m_aMembers[k].nNodeId)
  509. {
  510. for (i = k + 1; i < g_pChatWindow->m_cOtherMembers; i++)
  511. {
  512. if (m_aMembers[i].nNodeId)
  513. break;
  514. }
  515. if (i < g_pChatWindow->m_cOtherMembers)
  516. {
  517. m_aMembers[k] = m_aMembers[i];
  518. m_aMembers[i].nNodeId = 0;
  519. }
  520. }
  521. k++;
  522. }
  523. }
  524. g_pChatWindow->m_cOtherMembers -= nDuplicates;
  525. // Get the current selection
  526. MEMBER_CHANNEL_ID *pMemberID = (MEMBER_CHANNEL_ID*)g_pChatWindow->_GetSelectedMember();
  527. // Add the members to the list
  528. g_pChatWindow->_DeleteAllListItems();
  529. g_pChatWindow->_AddEveryoneInChat();
  530. for (k = 0; k < g_pChatWindow->m_cOtherMembers; k++)
  531. {
  532. g_pChatWindow->_AddMember(&m_aMembers[k]);
  533. }
  534. // Remove the bogus whisperId for Nm 2.x nodes
  535. BOOL fHasNM2xNode = FALSE;
  536. for (k = 0; k < g_pChatWindow->m_cOtherMembers; k++)
  537. {
  538. if (T120_GetNodeVersion(m_nConfID, m_aMembers[k].nNodeId) < 0x0404)
  539. { // Version 2.x, give it a whisper id of 0
  540. m_aMembers[k].nWhisperId = 0;
  541. fHasNM2xNode = TRUE;
  542. }
  543. }
  544. if ((fHasNM2xNode)&&(!m_nTimerID))
  545. { // time out every 1 sec
  546. m_nTimerID = ::SetTimer(NULL, 0, 1000, ChatTimerProc);
  547. }
  548. //
  549. // Goto the current selection, if it is still there.
  550. //
  551. i = ComboBoxEx_FindMember(g_pChatWindow->GetMemberList(), 0, pMemberID);
  552. if(i == -1 )
  553. {
  554. i = 0;
  555. }
  556. ComboBoxEx_SetCurSel( g_pChatWindow->GetMemberList(), i );
  557. }
  558. g_pChatWindow->_UpdateContainerCaption();
  559. } // if any change
  560. } // if is in conf
  561. }
  562. void CChatObj::OnRegistryEntryConfirm(GCCRegistryConfirm *pRegistryConfirm)
  563. {
  564. BOOL fAllFound = TRUE;
  565. // This is generated by "m_pAppletSession->RegistryRequest(&Req)" above to
  566. // retrieve the channel id number of NM 2.x nodes
  567. if (T120_RESULT_SUCCESSFUL == pRegistryConfirm->nResult)
  568. {
  569. // Update the m_aWhisperIds array.
  570. T120NodeID nNodeId;
  571. ::CopyMemory(&nNodeId, pRegistryConfirm->pRegKey->resource_id.value + cbKeyApp - sizeof(DWORD),
  572. sizeof(T120NodeID));
  573. T120ChannelID nChannelId = pRegistryConfirm->pRegItem->channel_id;
  574. WARNING_OUT(("Receive registry: node id 0x%x, channel id 0x%x.\n",
  575. nNodeId, nChannelId));
  576. for (ULONG k = 0; k < g_pChatWindow->m_cOtherMembers; k++)
  577. {
  578. if (m_aMembers[k].nNodeId == nNodeId)
  579. {
  580. m_aMembers[k].nWhisperId = nChannelId;
  581. }
  582. if (fAllFound && (0 == m_aMembers[k].nWhisperId))
  583. {
  584. fAllFound = FALSE;
  585. WARNING_OUT(("Node 0x%x is still not updated.\n",
  586. m_aMembers[k].nNodeId));
  587. }
  588. }
  589. if (fAllFound)
  590. {
  591. ::KillTimer(NULL, m_nTimerID);
  592. m_nTimerID = 0;
  593. WARNING_OUT(("All updated. Kill timer.\n"));
  594. }
  595. }
  596. }
  597. void CChatObj::CleanupPerConf(void)
  598. {
  599. m_fInConference = FALSE;
  600. m_pAppletSession = NULL;
  601. m_MyMemberID = 0;
  602. m_nConfID = 0; // Conf ID
  603. m_uidMyself = 0; // User ID
  604. m_sidMyself = 0; // Session ID
  605. m_eidMyself = 0; // Entity ID
  606. m_nidMyself = 0; // Node ID
  607. if(g_pChatWindow)
  608. {
  609. g_pChatWindow->m_cOtherMembers = 0;
  610. g_pChatWindow->_UpdateContainerCaption();
  611. g_pChatWindow->_DeleteAllListItems();
  612. }
  613. }
  614. T120Error CChatObj::SendData
  615. (
  616. T120UserID userID,
  617. ULONG cbDataSize,
  618. PBYTE pbData
  619. )
  620. {
  621. T120Error rc;
  622. if (IsInConference())
  623. {
  624. rc = m_pAppletSession->SendData(
  625. NORMAL_SEND_DATA,
  626. userID,
  627. APPLET_LOW_PRIORITY,
  628. pbData,
  629. cbDataSize,
  630. APP_ALLOCATION);
  631. }
  632. else
  633. {
  634. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  635. }
  636. return rc;
  637. }
  638. void CChatObj::SearchWhisperId(void)
  639. {
  640. T120RegistryRequest Req;
  641. GCCRegistryKey registry_key;
  642. BYTE SessionKey[cbKeyApp];
  643. BYTE ResourceKey[cbKeyApp];
  644. if (NULL != m_pAppletSession)
  645. {
  646. // Set up T120RegistryRequest
  647. ZeroMemory(&Req, sizeof(Req));
  648. Req.eCommand = APPLET_RETRIEVE_ENTRY;
  649. ::CopyMemory(&registry_key.session_key,
  650. &m_resourceRequest.RegKey.session_key, sizeof(GCCSessionKey));
  651. CreateAppKey(SessionKey, &guidNM2Chat, 0);
  652. SetAppKey(&registry_key.session_key.application_protocol_key.h221_non_standard_id, SessionKey);
  653. SetAppKey(&registry_key.resource_id, ResourceKey);
  654. Req.pRegistryKey = &registry_key;
  655. for (ULONG i = 0; i < g_pChatWindow->m_cOtherMembers; i++)
  656. {
  657. if (m_aMembers[i].nWhisperId == 0)
  658. {
  659. CreateAppKey(ResourceKey, &guidNM2Chat, m_aMembers[i].nNodeId);
  660. m_pAppletSession->RegistryRequest(&Req);
  661. WARNING_OUT(("Send search registry for node 0x%x.\n", m_aMembers[i].nNodeId));
  662. }
  663. }
  664. }
  665. }
  666. void MCSSendDataIndication(ULONG uSize, LPBYTE pb, T120ChannelID destinationID, T120UserID senderID)
  667. {
  668. if(g_pChatWindow)
  669. {
  670. g_pChatWindow->_DataReceived(uSize, pb, destinationID, senderID);
  671. }
  672. }