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.

1074 lines
25 KiB

  1. // NMWbObj.cpp : Implementation of CNMWbObj
  2. #include "precomp.h"
  3. #include <wbguid.h>
  4. #include "wbcaps.h"
  5. #include "NMWbObj.h"
  6. #include <iappldr.h>
  7. // Local prototypes
  8. void CALLBACK T120AppletCallbackProc(T120AppletMsg *pMsg);
  9. void CALLBACK T120SessionCallbackProc(T120AppletSessionMsg *pMsg);
  10. /////////////////////////////////////////////////////////////////////////////////////////////////////
  11. // CNMWbObj Construction and initialization
  12. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  13. CNMWbObj* g_pNMWBOBJ;
  14. UINT g_numberOfWorkspaces;
  15. UINT g_numberOfObjects;
  16. CWBOBLIST* g_pListOfWorkspaces;
  17. BOOL g_fWaitingForBufferAvailable;
  18. CWBOBLIST* g_pListOfObjectsThatRequestedHandles;
  19. CWBOBLIST* g_pRetrySendList;
  20. CWBOBLIST* g_pTrash;
  21. ULONG g_MyMemberID;
  22. ULONG g_RefresherID;
  23. UINT g_MyIndex;
  24. BOOL g_bSavingFile;
  25. BOOL g_bContentsChanged;
  26. GCCPREALOC g_GCCPreallocHandles[PREALLOC_GCC_BUFFERS];
  27. UINT g_iGCCHandleIndex;
  28. BOOL g_WaitingForGCCHandles;
  29. //
  30. // T.126 protocol related
  31. //
  32. static const ULONG g_T126KeyNodes[] = {0,0,20,126,0,1};
  33. static const T120ChannelID g_aStaticChannels[] = { _SI_CHANNEL_0 };
  34. //
  35. // T.120 capabilities
  36. //
  37. static GCCAppCap *g_CapPtrList[_iT126_MAX_COLLAPSING_CAPABILITIES];
  38. static GCCAppCap g_CapArray[_iT126_MAX_COLLAPSING_CAPABILITIES];
  39. //
  40. // T.120 non-collapsing capabilities
  41. //
  42. #define MY_APP_STR "_MSWB"
  43. #define T126_TEXT_STRING "NM 3 Text"
  44. #define T126_24BIT_STRING "NM 3 24BitMap"
  45. static const OSTR s_AppData[_iT126_LAST_NON_COLLAPSING_CAPABILITIES] =
  46. {
  47. {
  48. sizeof(T126_TEXT_STRING),
  49. (LPBYTE) T126_TEXT_STRING
  50. },
  51. {
  52. sizeof(T126_24BIT_STRING),
  53. (LPBYTE) T126_24BIT_STRING
  54. },
  55. };
  56. static GCCNonCollCap g_NCCapArray[2];
  57. static const GCCNonCollCap *g_NCCapPtrList[2] = { &g_NCCapArray[0], &g_NCCapArray[1] };
  58. //
  59. // Member ID arrays, assuming 64 members
  60. //
  61. #define MAX_MEMBERS 128
  62. static MEMBER_ID g_aMembers[MAX_MEMBERS];
  63. CNMWbObj::CNMWbObj( void ) :
  64. // T.120 applet SAP
  65. m_pApplet(NULL),
  66. m_aMembers(&g_aMembers[0])
  67. {
  68. DBGENTRY(CNMWbObj::CNMWbObj);
  69. DBG_SAVE_FILE_LINE
  70. g_pListOfWorkspaces = new CWBOBLIST();
  71. DBG_SAVE_FILE_LINE
  72. g_pListOfObjectsThatRequestedHandles = new CWBOBLIST();
  73. DBG_SAVE_FILE_LINE
  74. g_pTrash = new CWBOBLIST();
  75. DBG_SAVE_FILE_LINE
  76. g_pRetrySendList = new CWBOBLIST();
  77. g_pListOfWorkspaces->EmptyList();
  78. g_pListOfObjectsThatRequestedHandles->EmptyList();
  79. g_pRetrySendList->EmptyList();
  80. g_pTrash->EmptyList();
  81. g_numberOfWorkspaces = 0;
  82. g_numberOfObjects = 0;
  83. g_MyIndex = 0;
  84. g_bSavingFile = FALSE;
  85. g_bContentsChanged = FALSE;
  86. g_iGCCHandleIndex = 0;
  87. g_fWaitingForBufferAvailable = FALSE;
  88. g_WaitingForGCCHandles = FALSE;
  89. ::ZeroMemory(&g_GCCPreallocHandles, sizeof(g_GCCPreallocHandles));
  90. m_instanceNumber = 0;
  91. m_bConferenceOnlyNetmeetingNodes = TRUE;
  92. g_pNMWBOBJ = this;
  93. // Cleanup per-conference T.120 info
  94. CleanupPerConf();
  95. // T.120 Applet
  96. T120Error rc = ::T120_CreateAppletSAP(&m_pApplet);
  97. if (T120_NO_ERROR != rc)
  98. {
  99. ERROR_OUT(("CNMWbObj::CNMWbObj: cannot create applet SAP"));
  100. return;
  101. }
  102. ASSERT(NULL != m_pApplet);
  103. m_pApplet->Advise(T120AppletCallbackProc, this);
  104. //
  105. // Fill in the capabilities
  106. //
  107. BuildCaps();
  108. //
  109. // Load IMM32 if this is FE
  110. //
  111. ASSERT(!g_hImmLib);
  112. ASSERT(!g_fnImmGetContext);
  113. ASSERT(!g_fnImmNotifyIME);
  114. if (GetSystemMetrics(SM_DBCSENABLED))
  115. {
  116. g_hImmLib = LoadLibrary("imm32.dll");
  117. if (!g_hImmLib)
  118. {
  119. ERROR_OUT(("Failed to load imm32.dll"));
  120. }
  121. else
  122. {
  123. g_fnImmGetContext = (IGC_PROC)GetProcAddress(g_hImmLib, "ImmGetContext");
  124. if (!g_fnImmGetContext)
  125. {
  126. ERROR_OUT(("Failed to get ImmGetContext pointer"));
  127. }
  128. g_fnImmNotifyIME = (INI_PROC)GetProcAddress(g_hImmLib, "ImmNotifyIME");
  129. if (!g_fnImmNotifyIME)
  130. {
  131. ERROR_OUT(("Failed to get ImmNotifyIME pointer"));
  132. }
  133. }
  134. }
  135. DBG_SAVE_FILE_LINE
  136. g_pMain = new WbMainWindow();
  137. if (!g_pMain)
  138. {
  139. ERROR_OUT(("Can't create WbMainWindow"));
  140. }
  141. else
  142. {
  143. //
  144. // OK, now we're ready to create our HWND
  145. //
  146. if (!g_pMain->Open(SW_SHOWDEFAULT))
  147. {
  148. ERROR_OUT(("Can't create WB windows"));
  149. }
  150. }
  151. DBGEXIT(CNMWbObj::CNMWbObj);
  152. }
  153. CNMWbObj::~CNMWbObj( void )
  154. {
  155. DBGENTRY(CNMWbObj::~CNMWbObj);
  156. //
  157. // If i'm the refresher, I have to release the token
  158. // And send an workspace refresh status pdu
  159. //
  160. if(m_bImTheT126Refresher)
  161. {
  162. ::ZeroMemory(&m_tokenRequest, sizeof(m_tokenRequest));
  163. m_tokenRequest.eCommand = APPLET_RELEASE_TOKEN;
  164. m_tokenRequest.nTokenID = _SI_WORKSPACE_REFRESH_TOKEN;
  165. T120Error rc = m_pAppletSession->TokenRequest(&m_tokenRequest);
  166. SendWorkspaceRefreshPDU(FALSE);
  167. }
  168. // no more T.120
  169. if (NULL != m_pAppletSession)
  170. {
  171. m_pAppletSession->ReleaseInterface();
  172. CleanupPerConf();
  173. }
  174. if (NULL != m_pApplet)
  175. {
  176. m_pApplet->ReleaseInterface();
  177. m_pApplet = NULL;
  178. }
  179. if(g_pMain)
  180. {
  181. delete g_pMain;
  182. g_pMain = NULL;
  183. }
  184. //
  185. // Delete all the global lists
  186. //
  187. DeleteAllWorkspaces(FALSE);
  188. g_pListOfWorkspaces->EmptyList();
  189. g_pListOfObjectsThatRequestedHandles->EmptyList();
  190. g_numberOfWorkspaces = 0;
  191. T126Obj* pGraphic;
  192. //
  193. // Burn trash
  194. //
  195. pGraphic = (T126Obj *)g_pTrash->RemoveTail();
  196. while (pGraphic != NULL)
  197. {
  198. delete pGraphic;
  199. pGraphic = (T126Obj *) g_pTrash->RemoveTail();
  200. }
  201. if(g_pTrash)
  202. {
  203. delete g_pTrash;
  204. g_pTrash = NULL;
  205. }
  206. if(g_pListOfWorkspaces)
  207. {
  208. delete g_pListOfWorkspaces;
  209. g_pListOfWorkspaces = NULL;
  210. }
  211. if(g_pListOfObjectsThatRequestedHandles)
  212. {
  213. delete g_pListOfObjectsThatRequestedHandles;
  214. g_pListOfObjectsThatRequestedHandles = NULL;
  215. }
  216. if(g_pRetrySendList)
  217. {
  218. delete g_pRetrySendList;
  219. g_pRetrySendList = NULL;
  220. }
  221. g_fnImmNotifyIME = NULL;
  222. g_fnImmGetContext = NULL;
  223. if (g_hImmLib)
  224. {
  225. FreeLibrary(g_hImmLib);
  226. g_hImmLib = NULL;
  227. }
  228. DBGEXIT(CNMWbObj::~CNMWbObj);
  229. }
  230. void CNMWbObj::BuildCaps(void)
  231. {
  232. // Fill in the caps we support
  233. int i;
  234. for(i=0;i<_iT126_MAX_COLLAPSING_CAPABILITIES;i++)
  235. {
  236. g_CapArray[i].capability_id.capability_id_type = GCC_STANDARD_CAPABILITY;
  237. g_CapArray[i].capability_id.standard_capability = GCCCaps[i].CapValue;
  238. g_CapArray[i].capability_class.eType = GCCCaps[i].Type;
  239. if( GCCCaps[i].CapValue == Soft_Copy_Workspace_Max_Width)
  240. {
  241. GCCCaps[i].MinValue = DRAW_WIDTH + 1;
  242. GCCCaps[i].MaxValue = DRAW_WIDTH - 1;
  243. }
  244. if(GCCCaps[i].CapValue == Soft_Copy_Workspace_Max_Height)
  245. {
  246. GCCCaps[i].MinValue = DRAW_HEIGHT + 1;
  247. GCCCaps[i].MaxValue = DRAW_HEIGHT - 1;
  248. }
  249. if(GCCCaps[i].CapValue == Soft_Copy_Workspace_Max_Planes)
  250. {
  251. GCCCaps[i].MinValue = WB_MAX_WORKSPACES + 1;
  252. GCCCaps[i].MaxValue = WB_MAX_WORKSPACES - 1;
  253. }
  254. if(GCCCaps[i].Type == GCC_UNSIGNED_MINIMUM_CAPABILITY)
  255. {
  256. g_CapArray[i].capability_class.nMinOrMax = GCCCaps[i].MinValue - 1;
  257. }
  258. else if ((GCCCaps[i].Type == GCC_UNSIGNED_MAXIMUM_CAPABILITY))
  259. {
  260. g_CapArray[i].capability_class.nMinOrMax = GCCCaps[i].MaxValue + 1;
  261. }
  262. else
  263. {
  264. g_CapArray[i].capability_class.nMinOrMax = 0;
  265. }
  266. g_CapArray[i].number_of_entities = 0;
  267. g_CapPtrList[i] = &g_CapArray[i];
  268. }
  269. //
  270. // Non-Collapsed Capabilities
  271. //
  272. g_NCCapArray[0].capability_id.capability_id_type = GCC_STANDARD_CAPABILITY;
  273. g_NCCapArray[0].capability_id.standard_capability = _iT126_TEXT_CAPABILITY_ID;
  274. g_NCCapArray[0].application_data = (OSTR *) &s_AppData[0];
  275. //
  276. // How many bits per pixel can we handle?
  277. //
  278. HDC hDC = CreateCompatibleDC(NULL);
  279. if((GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)) >= 24)
  280. {
  281. m_bICanDo24BitBitmaps = TRUE;
  282. g_NCCapArray[1].capability_id.capability_id_type = GCC_STANDARD_CAPABILITY;
  283. g_NCCapArray[1].capability_id.standard_capability = _iT126_24BIT_BITMAP_ID;
  284. g_NCCapArray[1].application_data = (OSTR *) &s_AppData[1];
  285. }
  286. else
  287. {
  288. m_bICanDo24BitBitmaps = FALSE;
  289. }
  290. if (hDC)
  291. {
  292. DeleteDC(hDC);
  293. }
  294. }
  295. //
  296. // T120 Applet Functions
  297. //
  298. void CALLBACK T120AppletCallbackProc
  299. (
  300. T120AppletMsg *pMsg
  301. )
  302. {
  303. CNMWbObj *pWBOBJ = (CNMWbObj *) pMsg->pAppletContext;
  304. if (pWBOBJ == g_pNMWBOBJ)
  305. {
  306. switch (pMsg->eMsgType)
  307. {
  308. case GCC_PERMIT_TO_ENROLL_INDICATION:
  309. pWBOBJ->OnPermitToEnroll(pMsg->PermitToEnrollInd.nConfID,
  310. pMsg->PermitToEnrollInd.fPermissionGranted);
  311. break;
  312. case T120_JOIN_SESSION_CONFIRM:
  313. default:
  314. break;
  315. }
  316. }
  317. }
  318. void CALLBACK T120SessionCallbackProc
  319. (
  320. T120AppletSessionMsg *pMsg
  321. )
  322. {
  323. if(g_pNMWBOBJ == NULL)
  324. {
  325. return;
  326. }
  327. CNMWbObj *pSession = (CNMWbObj *) pMsg->pSessionContext;
  328. ASSERT(pMsg->pAppletContext == pMsg->pSessionContext);
  329. if (pSession == g_pNMWBOBJ)
  330. {
  331. ASSERT(pMsg->nConfID == pSession->GetConfID());
  332. switch (pMsg->eMsgType)
  333. {
  334. case MCS_UNIFORM_SEND_DATA_INDICATION:
  335. //
  336. // Check if we are receiving a indication from owrself
  337. //
  338. if(pMsg->SendDataInd.initiator == GET_USER_ID_FROM_MEMBER_ID(g_MyMemberID))
  339. {
  340. return;
  341. }
  342. case MCS_SEND_DATA_INDICATION:
  343. ::T126_MCSSendDataIndication(
  344. pMsg->SendDataInd.user_data.length,
  345. pMsg->SendDataInd.user_data.value,
  346. pMsg->SendDataInd.initiator,
  347. FALSE);
  348. break;
  349. case MCS_TRANSMIT_BUFFER_AVAILABLE_INDICATION:
  350. g_fWaitingForBufferAvailable = FALSE;
  351. RetrySend();
  352. break;
  353. case GCC_APP_ROSTER_REPORT_INDICATION:
  354. pSession->OnRosterIndication((ULONG) pMsg->AppRosterReportInd.cRosters,
  355. pMsg->AppRosterReportInd.apAppRosters);
  356. break;
  357. case GCC_ALLOCATE_HANDLE_CONFIRM:
  358. pSession->OnAllocateHandleConfirm(&pMsg->RegAllocHandleConfirm);
  359. break;
  360. case T120_JOIN_SESSION_CONFIRM:
  361. pSession->OnJoinSessionConfirm(&pMsg->JoinSessionConfirm);
  362. break;
  363. case MCS_TOKEN_GRAB_CONFIRM:
  364. TRACE_DEBUG(("MCS_TOKEN_GRAB_CONFIRM result = %d",pMsg->TokenConfirm.eResult));
  365. if(pMsg->TokenConfirm.eResult == T120_RESULT_SUCCESSFUL)
  366. {
  367. TRACE_DEBUG((">>> I'm the T126 REFRESHER <<<"));
  368. g_pNMWBOBJ->m_bImTheT126Refresher = TRUE;
  369. //
  370. // Tell everybody I'm the refresher
  371. //
  372. SendWorkspaceRefreshPDU(TRUE);
  373. g_RefresherID = g_MyMemberID;
  374. }
  375. else
  376. {
  377. TRACE_DEBUG((">>> I'm NOT the T126 REFRESHER <<<"));
  378. // if we are not the t126 refresher, we should save the previous work
  379. if (!g_pNMWBOBJ->m_bImTheT126Refresher)
  380. {
  381. if(!g_pNMWBOBJ->IsInConference())
  382. {
  383. if (g_pMain && (g_pMain->QuerySaveRequired(FALSE) == IDYES))
  384. {
  385. g_pMain->OnSave(FALSE);
  386. }
  387. //
  388. // If we were waiting on the save contents <yes> <no> dialog
  389. // and the whole conference and UI are exiting, g_pMain could be NULL
  390. // Or if we are not in a call anymore, we don't need to delete all the local workspaces.
  391. //
  392. if(g_pMain == NULL || !g_pNMWBOBJ->IsInConference())
  393. {
  394. return;
  395. }
  396. ::InvalidateRect(g_pDraw->m_hwnd, NULL, TRUE);
  397. DeleteAllWorkspaces(FALSE);
  398. //
  399. // Fill up the GCC tank
  400. //
  401. TimeToGetGCCHandles(PREALLOC_GCC_HANDLES);
  402. }
  403. // ELSE
  404. // If we got here and we are in a call don't do a thing.
  405. // We just got here because the refresher went away. We tried
  406. // to grab the token and we lost it to a faster node.
  407. //
  408. }
  409. }
  410. break;
  411. default:
  412. break;
  413. }
  414. }
  415. }
  416. void CNMWbObj::OnPermitToEnroll
  417. (
  418. T120ConfID nConfID,
  419. BOOL fPermissionGranted
  420. )
  421. {
  422. if (fPermissionGranted)
  423. {
  424. // We are not in a conference, right?
  425. ASSERT(NULL == m_pAppletSession);
  426. m_bConferenceOnlyNetmeetingNodes = TRUE;
  427. // Create an applet session
  428. T120Error rc = m_pApplet->CreateSession(&m_pAppletSession, nConfID);
  429. if (T120_NO_ERROR == rc)
  430. {
  431. ASSERT(NULL != m_pAppletSession);
  432. m_pAppletSession->Advise(T120SessionCallbackProc, this, this);
  433. // get top provider information
  434. m_bImTheTopProvider = m_pAppletSession->IsThisNodeTopProvider();
  435. // Build join-sesion request
  436. ::ZeroMemory(&m_JoinSessionReq, sizeof(m_JoinSessionReq));
  437. m_JoinSessionReq.dwAttachmentFlags = ATTACHMENT_DISCONNECT_IN_DATA_LOSS | ATTACHMENT_MCS_FREES_DATA_IND_BUFFER;
  438. m_JoinSessionReq.SessionKey.application_protocol_key.key_type = GCC_OBJECT_KEY;
  439. m_JoinSessionReq.SessionKey.application_protocol_key.object_id.long_string = (ULONG *) g_T126KeyNodes;
  440. m_JoinSessionReq.SessionKey.application_protocol_key.object_id.long_string_length = sizeof(g_T126KeyNodes) / sizeof(g_T126KeyNodes[0]);
  441. m_JoinSessionReq.SessionKey.session_id = _SI_CHANNEL_0;
  442. m_JoinSessionReq.fConductingCapable = FALSE;
  443. m_JoinSessionReq.nStartupChannelType =MCS_STATIC_CHANNEL;
  444. m_JoinSessionReq.cNonCollapsedCaps =1 + (m_bICanDo24BitBitmaps ? 1 : 0);
  445. m_JoinSessionReq.apNonCollapsedCaps = (GCCNonCollCap **) g_NCCapPtrList;
  446. m_JoinSessionReq.cCollapsedCaps = sizeof(g_CapPtrList) / sizeof(g_CapPtrList[0]);
  447. ASSERT(_iT126_MAX_COLLAPSING_CAPABILITIES == sizeof(g_CapPtrList) / sizeof(g_CapPtrList[0]));
  448. m_JoinSessionReq.apCollapsedCaps = g_CapPtrList;
  449. m_JoinSessionReq.cStaticChannels = sizeof(g_aStaticChannels) / sizeof(g_aStaticChannels[0]);
  450. m_JoinSessionReq.aStaticChannels = (T120ChannelID *) g_aStaticChannels;
  451. //
  452. // Token to grab
  453. //
  454. ::ZeroMemory(&m_tokenResourceRequest, sizeof(m_tokenResourceRequest));
  455. m_tokenResourceRequest.eCommand = APPLET_GRAB_TOKEN_REQUEST;
  456. // m_tokenRequest.nChannelID = _SI_CHANNEL_0;
  457. m_tokenResourceRequest.nTokenID = _SI_WORKSPACE_REFRESH_TOKEN;
  458. m_tokenResourceRequest.fImmediateNotification = TRUE;
  459. m_JoinSessionReq.cResourceReqs = 1;
  460. m_JoinSessionReq.aResourceReqs = &m_tokenResourceRequest;
  461. // Join now
  462. rc = m_pAppletSession->Join(&m_JoinSessionReq);
  463. if (T120_NO_ERROR == rc)
  464. {
  465. m_nConfID = nConfID;
  466. //
  467. // JOSEF NOW SET THE MAIN WINDOW STATUS
  468. }
  469. else
  470. {
  471. WARNING_OUT(("CNMWbObj::OnPermitToEnroll: cannot join conf=%u, rc=%u", nConfID, rc));
  472. }
  473. }
  474. }
  475. else
  476. {
  477. if (NULL != m_pAppletSession)
  478. {
  479. m_pAppletSession->ReleaseInterface();
  480. CleanupPerConf();
  481. }
  482. }
  483. }
  484. void CNMWbObj::OnJoinSessionConfirm
  485. (
  486. T120JoinSessionConfirm *pConfirm
  487. )
  488. {
  489. if (NULL != m_pAppletSession)
  490. {
  491. ASSERT(m_pAppletSession == pConfirm->pIAppletSession);
  492. if (T120_RESULT_SUCCESSFUL == pConfirm->eResult)
  493. {
  494. m_uidMyself = pConfirm->uidMyself;
  495. m_sidMyself = pConfirm->sidMyself;
  496. m_eidMyself = pConfirm->eidMyself;
  497. m_nidMyself = pConfirm->nidMyself;
  498. // create member ID
  499. g_MyMemberID = MAKE_MEMBER_ID(m_nidMyself, m_uidMyself);
  500. if(g_pDraw && g_pDraw->IsLocked())
  501. {
  502. m_LockerID = g_MyMemberID;
  503. }
  504. // regardless, update the index anyway
  505. g_MyIndex = (m_uidMyself + NUMCOLS) % NUMCLRPANES;
  506. // we are now in the conference
  507. m_fInConference = TRUE;
  508. // allocate handles for all objects
  509. if (m_bImTheT126Refresher)
  510. {
  511. g_RefresherID = g_MyMemberID;
  512. //
  513. // Resend all objects
  514. //
  515. WBPOSITION pos;
  516. WBPOSITION posObj;
  517. WorkspaceObj* pWorkspace;
  518. T126Obj* pObj;
  519. pos = g_pListOfWorkspaces->GetHeadPosition();
  520. while(pos)
  521. {
  522. pWorkspace = (WorkspaceObj*)g_pListOfWorkspaces->GetNext(pos);
  523. g_pListOfObjectsThatRequestedHandles->AddHead(pWorkspace);
  524. posObj = pWorkspace->GetHeadPosition();
  525. while(posObj)
  526. {
  527. pObj = pWorkspace->GetNextObject(posObj);
  528. if(pObj)
  529. {
  530. g_pListOfObjectsThatRequestedHandles->AddHead(pObj);
  531. }
  532. }
  533. }
  534. //
  535. // Delete the fake handles we had
  536. //
  537. g_WaitingForGCCHandles = FALSE;
  538. g_GCCPreallocHandles[0].GccHandleCount = 0;
  539. g_GCCPreallocHandles[1].GccHandleCount = 0;
  540. TimeToGetGCCHandles(g_numberOfObjects + g_numberOfWorkspaces + PREALLOC_GCC_HANDLES);
  541. }
  542. else
  543. {
  544. ::InvalidateRect(g_pDraw->m_hwnd, NULL, TRUE);
  545. DeleteAllWorkspaces(FALSE);
  546. }
  547. }
  548. else
  549. {
  550. WARNING_OUT(("CNMWbObj::OnJoinSessionConfirm: failed to join conference, result=%u. error=%u",
  551. pConfirm->eResult, pConfirm->eError));
  552. ASSERT(GCC_CONFERENCE_NOT_ESTABLISHED == pConfirm->eError);
  553. m_pAppletSession->ReleaseInterface();
  554. CleanupPerConf();
  555. }
  556. }
  557. }
  558. void CNMWbObj::OnAllocateHandleConfirm
  559. (
  560. GCCRegAllocateHandleConfirm *pConfirm
  561. )
  562. {
  563. if (T120_RESULT_SUCCESSFUL == pConfirm->nResult)
  564. {
  565. ::T126_GCCAllocateHandleConfirm(pConfirm->nFirstHandle, pConfirm->cHandles);
  566. }
  567. else
  568. {
  569. ERROR_OUT(("CNMWbObj::OnAllocateHandleConfirm: failed to allocate %u handles, result=%u",
  570. pConfirm->cHandles, pConfirm->nResult));
  571. }
  572. }
  573. void CNMWbObj::OnRosterIndication
  574. (
  575. ULONG cRosters,
  576. GCCAppRoster *apRosters[]
  577. )
  578. {
  579. if (IsInConference())
  580. {
  581. BOOL fAdded = FALSE;
  582. BOOL fRemoved = FALSE;
  583. ULONG cOtherMembers = 0;
  584. ULONG i, j, k;
  585. // Caculate how many members in this session
  586. for (i = 0; i < cRosters; i++)
  587. {
  588. GCCAppRoster *pRoster = apRosters[i];
  589. // bail out if this roster is not for this session
  590. if (pRoster->session_key.session_id != m_sidMyself)
  591. {
  592. continue;
  593. }
  594. // node added or removed?
  595. fAdded |= pRoster->nodes_were_added;
  596. fRemoved |= pRoster->nodes_were_removed;
  597. BOOL conferenceCanDo24BitBitmap = TRUE;
  598. BOOL conferenceCanDoText = TRUE;
  599. // parse the roster records
  600. for (j = 0; j < pRoster->number_of_records; j++)
  601. {
  602. GCCAppRecord *pRecord = pRoster->application_record_list[j];
  603. if (pRecord->is_enrolled_actively)
  604. {
  605. MEMBER_ID nMemberID = MAKE_MEMBER_ID(pRecord->node_id, pRecord->application_user_id);
  606. if (nMemberID != g_MyMemberID)
  607. {
  608. //
  609. // Only count T126 apps
  610. //
  611. if((pRoster->session_key.application_protocol_key.key_type == GCC_OBJECT_KEY &&
  612. pRoster->session_key.application_protocol_key.object_id.long_string_length == sizeof(g_T126KeyNodes) / sizeof(g_T126KeyNodes[0]) &&
  613. !memcmp (pRoster->session_key.application_protocol_key.object_id.long_string, g_T126KeyNodes, sizeof(g_T126KeyNodes))))
  614. {
  615. cOtherMembers++;
  616. m_instanceNumber = pRoster->instance_number;
  617. if(T120_GetNodeVersion(m_nConfID, pRecord->node_id) < 0x404)
  618. {
  619. m_bConferenceOnlyNetmeetingNodes = FALSE;
  620. }
  621. }
  622. }
  623. //
  624. // Can we do 24 color bitmap
  625. //
  626. BOOL nodeCanDo24BitBitmap = FALSE;
  627. BOOL nodeCanDoText = FALSE;
  628. for (k = 0; k < pRecord->number_of_non_collapsed_caps; k++)
  629. {
  630. //
  631. // Check if the node handles 24 bit bitmaps
  632. //
  633. if(pRecord->non_collapsed_caps_list[k]->application_data->length == sizeof(T126_24BIT_STRING))
  634. {
  635. if(!memcmp(pRecord->non_collapsed_caps_list[k]->application_data->value, T126_24BIT_STRING ,sizeof(T126_24BIT_STRING)))
  636. {
  637. nodeCanDo24BitBitmap = TRUE;
  638. }
  639. }
  640. //
  641. // Check if the node handles text
  642. //
  643. if(pRecord->non_collapsed_caps_list[k]->application_data->length == sizeof(T126_TEXT_STRING))
  644. {
  645. if(!memcmp(pRecord->non_collapsed_caps_list[k]->application_data->value, T126_TEXT_STRING ,sizeof(T126_TEXT_STRING)))
  646. {
  647. nodeCanDoText = TRUE;
  648. }
  649. }
  650. }
  651. conferenceCanDo24BitBitmap &= nodeCanDo24BitBitmap;
  652. conferenceCanDoText &= nodeCanDoText;
  653. }
  654. } // for
  655. m_bConferenceCanDo24BitBitmaps = conferenceCanDo24BitBitmap;
  656. m_bConferenceCanDoText = conferenceCanDoText;
  657. } // for
  658. // If there are changes, we then do the update
  659. if (fAdded || fRemoved || cOtherMembers != m_cOtherMembers)
  660. {
  661. MEMBER_ID aTempMembers[MAX_MEMBERS]; // scratch copy
  662. // make sure we are able to handle it
  663. if (cOtherMembers >= MAX_MEMBERS)
  664. {
  665. ERROR_OUT(("CNMWbObj::OnRosterIndication: we hit the max members limit, cOtherMembers=%u, max-members=%u",
  666. cOtherMembers, MAX_MEMBERS));
  667. cOtherMembers = MAX_MEMBERS;
  668. }
  669. // reset the flags for members added and removed
  670. fAdded = FALSE;
  671. fRemoved = FALSE;
  672. // copy the members
  673. ULONG idxTempMember = 0;
  674. for (i = 0; i < cRosters; i++)
  675. {
  676. GCCAppRoster *pRoster = apRosters[i];
  677. // bail out if this roster is not for this session
  678. if (pRoster->session_key.session_id != m_sidMyself)
  679. {
  680. continue;
  681. }
  682. // parse the roster records
  683. for (j = 0; j < pRoster->number_of_records; j++)
  684. {
  685. GCCAppRecord *pRecord = pRoster->application_record_list[j];
  686. if (pRecord->is_enrolled_actively)
  687. {
  688. MEMBER_ID nMemberID = MAKE_MEMBER_ID(pRecord->node_id, pRecord->application_user_id);
  689. if (nMemberID != g_MyMemberID && idxTempMember < cOtherMembers)
  690. {
  691. aTempMembers[idxTempMember++] = nMemberID;
  692. // let's see if it is an 'add' or a 'delete'
  693. for (k = 0; k < m_cOtherMembers; k++)
  694. {
  695. if (m_aMembers[k] == nMemberID)
  696. {
  697. m_aMembers[k] = 0;
  698. break;
  699. }
  700. }
  701. fAdded |= (k >= m_cOtherMembers); // not found, must be new
  702. }
  703. }
  704. } // for
  705. } // for
  706. // sanity check
  707. ASSERT(idxTempMember == cOtherMembers);
  708. // see if there are ones that are not in the new roster.
  709. // if so, they must be removed.
  710. for (k = 0; k < m_cOtherMembers; k++)
  711. {
  712. if (m_aMembers[k])
  713. {
  714. fRemoved = TRUE;
  715. ULONG memberID = GET_USER_ID_FROM_MEMBER_ID(m_aMembers[k]);
  716. TRACE_DEBUG(("OnRosterIndication removing RemotePointer from member =%x", memberID));
  717. RemoveRemotePointer(memberID);
  718. //
  719. // if the refresher went away
  720. //
  721. if(g_RefresherID == memberID)
  722. {
  723. GrabRefresherToken();
  724. }
  725. //
  726. // if node locking went away
  727. //
  728. if(m_LockerID == memberID)
  729. {
  730. TogleLockInAllWorkspaces(FALSE, FALSE); // Not locked, don't send updates
  731. g_pMain->UnlockDrawingArea();
  732. g_pMain->m_TB.PopUp(IDM_LOCK);
  733. g_pMain->UncheckMenuItem(IDM_LOCK);
  734. m_LockerID = 0;
  735. }
  736. }
  737. }
  738. // now, update the member array
  739. m_cOtherMembers = cOtherMembers;
  740. if (m_cOtherMembers)
  741. {
  742. ASSERT(sizeof(m_aMembers[0]) == sizeof(aTempMembers[0]));
  743. ::CopyMemory(&m_aMembers[0], &aTempMembers[0], m_cOtherMembers * sizeof(m_aMembers[0]));
  744. }
  745. // if added, resend all objects
  746. if (fAdded && (m_bImTheT126Refresher))
  747. {
  748. //
  749. // Tell the new node that I'm the refresher
  750. //
  751. SendWorkspaceRefreshPDU(TRUE);
  752. //
  753. // Refresh the new node
  754. //
  755. ResendAllObjects();
  756. //
  757. // if node locking everybody went away
  758. //
  759. if(m_LockerID == g_MyMemberID)
  760. {
  761. TogleLockInAllWorkspaces(TRUE, TRUE); // Locked, send updates
  762. }
  763. //
  764. // Syncronize it
  765. //
  766. if(g_pCurrentWorkspace)
  767. {
  768. g_pCurrentWorkspace->OnObjectEdit();
  769. }
  770. }
  771. // finally, update the caption
  772. if(g_pMain)
  773. {
  774. g_pMain->UpdateWindowTitle();
  775. }
  776. } // if any change
  777. } // if is in conf
  778. }
  779. void CNMWbObj::CleanupPerConf(void)
  780. {
  781. m_fInConference = FALSE;
  782. m_pAppletSession = NULL;
  783. g_MyMemberID = 0;
  784. g_RefresherID = 0;
  785. m_nConfID = 0; // Conf ID
  786. m_uidMyself = 0; // User ID
  787. m_sidMyself = 0; // Session ID
  788. m_eidMyself = 0; // Entity ID
  789. m_nidMyself = 0; // Node ID
  790. m_bImTheTopProvider = FALSE;
  791. m_bImTheT126Refresher = FALSE;
  792. m_bConferenceOnlyNetmeetingNodes = TRUE;
  793. m_cOtherMembers = 0;
  794. if(g_pMain)
  795. {
  796. g_pMain->UpdateWindowTitle();
  797. RemoveRemotePointer(0);
  798. DeleteAllRetryPDUS();
  799. g_pListOfObjectsThatRequestedHandles->EmptyList();
  800. ASSERT(g_pDraw);
  801. //
  802. // If we were locked
  803. //
  804. if(g_pDraw->IsLocked())
  805. {
  806. m_LockerID = g_MyMemberID;
  807. TogleLockInAllWorkspaces(FALSE, FALSE); // Not locked, don't send updates
  808. g_pMain->UnlockDrawingArea();
  809. g_pMain->m_TB.PopUp(IDM_LOCK);
  810. g_pMain->UncheckMenuItem(IDM_LOCK);
  811. }
  812. }
  813. m_LockerID = 0;
  814. }
  815. T120Error CNMWbObj::SendData
  816. (
  817. T120Priority ePriority,
  818. ULONG cbDataSize,
  819. PBYTE pbData
  820. )
  821. {
  822. T120Error rc;
  823. if (IsInConference())
  824. {
  825. rc = m_pAppletSession->SendData(
  826. UNIFORM_SEND_DATA,
  827. _SI_CHANNEL_0,
  828. ePriority,
  829. pbData,
  830. cbDataSize,
  831. APP_ALLOCATION);
  832. }
  833. else
  834. {
  835. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  836. }
  837. return rc;
  838. }
  839. T120Error CNMWbObj::GrabRefresherToken(void)
  840. {
  841. T120Error rc;
  842. if (IsInConference())
  843. {
  844. T120TokenRequest Req;
  845. Req.eCommand = APPLET_GRAB_TOKEN;
  846. Req.nTokenID = _SI_WORKSPACE_REFRESH_TOKEN;
  847. Req.uidGiveTo = m_uidMyself;
  848. Req.eGiveResponse = T120_RESULT_SUCCESSFUL;
  849. rc = m_pAppletSession->TokenRequest(&Req);
  850. if (T120_NO_ERROR != rc)
  851. {
  852. WARNING_OUT(("CNMWbObj::AllocateHandles: TokenRequest"));
  853. }
  854. }
  855. else
  856. {
  857. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  858. }
  859. return rc;
  860. }
  861. T120Error CNMWbObj::AllocateHandles
  862. (
  863. ULONG cHandles
  864. )
  865. {
  866. T120Error rc;
  867. if ( cHandles > 0 && IsInConference())
  868. {
  869. T120RegistryRequest Req;
  870. Req.eCommand = APPLET_ALLOCATE_HANDLE;
  871. Req.pRegistryKey = NULL;
  872. Req.cHandles = cHandles;
  873. rc = m_pAppletSession->RegistryRequest(&Req);
  874. if (T120_NO_ERROR != rc)
  875. {
  876. ERROR_OUT(("CNMWbObj::AllocateHandles: RegistryRequest(cHandles=%u), rc=%u", cHandles, rc));
  877. }
  878. }
  879. else
  880. {
  881. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  882. }
  883. return rc;
  884. }