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.

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