// NMWbObj.cpp : Implementation of CNMWbObj #include "precomp.h" #include #include "wbcaps.h" #include "NMWbObj.h" #include // Local prototypes void CALLBACK T120AppletCallbackProc(T120AppletMsg *pMsg); void CALLBACK T120SessionCallbackProc(T120AppletSessionMsg *pMsg); ///////////////////////////////////////////////////////////////////////////////////////////////////// // CNMWbObj Construction and initialization /////////////////////////////////////////////////////////////////////////////////////////////////////// CNMWbObj* g_pNMWBOBJ; UINT g_numberOfWorkspaces; UINT g_numberOfObjects; CWBOBLIST* g_pListOfWorkspaces; BOOL g_fWaitingForBufferAvailable; CWBOBLIST* g_pListOfObjectsThatRequestedHandles; CWBOBLIST* g_pRetrySendList; CWBOBLIST* g_pTrash; ULONG g_MyMemberID; ULONG g_RefresherID; UINT g_MyIndex; BOOL g_bSavingFile; BOOL g_bContentsChanged; GCCPREALOC g_GCCPreallocHandles[PREALLOC_GCC_BUFFERS]; UINT g_iGCCHandleIndex; BOOL g_WaitingForGCCHandles; // // T.126 protocol related // static const ULONG g_T126KeyNodes[] = {0,0,20,126,0,1}; static const T120ChannelID g_aStaticChannels[] = { _SI_CHANNEL_0 }; // // T.120 capabilities // static GCCAppCap *g_CapPtrList[_iT126_MAX_COLLAPSING_CAPABILITIES]; static GCCAppCap g_CapArray[_iT126_MAX_COLLAPSING_CAPABILITIES]; // // T.120 non-collapsing capabilities // #define MY_APP_STR "_MSWB" #define T126_TEXT_STRING "NM 3 Text" #define T126_24BIT_STRING "NM 3 24BitMap" static const OSTR s_AppData[_iT126_LAST_NON_COLLAPSING_CAPABILITIES] = { { sizeof(T126_TEXT_STRING), (LPBYTE) T126_TEXT_STRING }, { sizeof(T126_24BIT_STRING), (LPBYTE) T126_24BIT_STRING }, }; static GCCNonCollCap g_NCCapArray[2]; static const GCCNonCollCap *g_NCCapPtrList[2] = { &g_NCCapArray[0], &g_NCCapArray[1] }; // // Member ID arrays, assuming 64 members // #define MAX_MEMBERS 128 static MEMBER_ID g_aMembers[MAX_MEMBERS]; CNMWbObj::CNMWbObj( void ) : // T.120 applet SAP m_pApplet(NULL), m_aMembers(&g_aMembers[0]) { DBGENTRY(CNMWbObj::CNMWbObj); DBG_SAVE_FILE_LINE g_pListOfWorkspaces = new CWBOBLIST(); DBG_SAVE_FILE_LINE g_pListOfObjectsThatRequestedHandles = new CWBOBLIST(); DBG_SAVE_FILE_LINE g_pTrash = new CWBOBLIST(); DBG_SAVE_FILE_LINE g_pRetrySendList = new CWBOBLIST(); g_pListOfWorkspaces->EmptyList(); g_pListOfObjectsThatRequestedHandles->EmptyList(); g_pRetrySendList->EmptyList(); g_pTrash->EmptyList(); g_numberOfWorkspaces = 0; g_numberOfObjects = 0; g_MyIndex = 0; g_bSavingFile = FALSE; g_bContentsChanged = FALSE; g_iGCCHandleIndex = 0; g_fWaitingForBufferAvailable = FALSE; g_WaitingForGCCHandles = FALSE; ::ZeroMemory(&g_GCCPreallocHandles, sizeof(g_GCCPreallocHandles)); m_instanceNumber = 0; m_bConferenceOnlyNetmeetingNodes = TRUE; g_pNMWBOBJ = this; // Cleanup per-conference T.120 info CleanupPerConf(); // T.120 Applet T120Error rc = ::T120_CreateAppletSAP(&m_pApplet); if (T120_NO_ERROR != rc) { ERROR_OUT(("CNMWbObj::CNMWbObj: cannot create applet SAP")); return; } ASSERT(NULL != m_pApplet); m_pApplet->Advise(T120AppletCallbackProc, this); // // Fill in the capabilities // BuildCaps(); // // Load IMM32 if this is FE // ASSERT(!g_hImmLib); ASSERT(!g_fnImmGetContext); ASSERT(!g_fnImmNotifyIME); if (GetSystemMetrics(SM_DBCSENABLED)) { g_hImmLib = LoadLibrary("imm32.dll"); if (!g_hImmLib) { ERROR_OUT(("Failed to load imm32.dll")); } else { g_fnImmGetContext = (IGC_PROC)GetProcAddress(g_hImmLib, "ImmGetContext"); if (!g_fnImmGetContext) { ERROR_OUT(("Failed to get ImmGetContext pointer")); } g_fnImmNotifyIME = (INI_PROC)GetProcAddress(g_hImmLib, "ImmNotifyIME"); if (!g_fnImmNotifyIME) { ERROR_OUT(("Failed to get ImmNotifyIME pointer")); } } } DBG_SAVE_FILE_LINE g_pMain = new WbMainWindow(); if (!g_pMain) { ERROR_OUT(("Can't create WbMainWindow")); } else { // // OK, now we're ready to create our HWND // if (!g_pMain->Open(SW_SHOWDEFAULT)) { ERROR_OUT(("Can't create WB windows")); } } DBGEXIT(CNMWbObj::CNMWbObj); } CNMWbObj::~CNMWbObj( void ) { DBGENTRY(CNMWbObj::~CNMWbObj); // // If i'm the refresher, I have to release the token // And send an workspace refresh status pdu // if(m_bImTheT126Refresher) { ::ZeroMemory(&m_tokenRequest, sizeof(m_tokenRequest)); m_tokenRequest.eCommand = APPLET_RELEASE_TOKEN; m_tokenRequest.nTokenID = _SI_WORKSPACE_REFRESH_TOKEN; T120Error rc = m_pAppletSession->TokenRequest(&m_tokenRequest); SendWorkspaceRefreshPDU(FALSE); } // no more T.120 if (NULL != m_pAppletSession) { m_pAppletSession->ReleaseInterface(); CleanupPerConf(); } if (NULL != m_pApplet) { m_pApplet->ReleaseInterface(); m_pApplet = NULL; } if(g_pMain) { delete g_pMain; g_pMain = NULL; } // // Delete all the global lists // DeleteAllWorkspaces(FALSE); g_pListOfWorkspaces->EmptyList(); g_pListOfObjectsThatRequestedHandles->EmptyList(); g_numberOfWorkspaces = 0; T126Obj* pGraphic; // // Burn trash // pGraphic = (T126Obj *)g_pTrash->RemoveTail(); while (pGraphic != NULL) { delete pGraphic; pGraphic = (T126Obj *) g_pTrash->RemoveTail(); } if(g_pTrash) { delete g_pTrash; g_pTrash = NULL; } if(g_pListOfWorkspaces) { delete g_pListOfWorkspaces; g_pListOfWorkspaces = NULL; } if(g_pListOfObjectsThatRequestedHandles) { delete g_pListOfObjectsThatRequestedHandles; g_pListOfObjectsThatRequestedHandles = NULL; } if(g_pRetrySendList) { delete g_pRetrySendList; g_pRetrySendList = NULL; } g_fnImmNotifyIME = NULL; g_fnImmGetContext = NULL; if (g_hImmLib) { FreeLibrary(g_hImmLib); g_hImmLib = NULL; } DBGEXIT(CNMWbObj::~CNMWbObj); } void CNMWbObj::BuildCaps(void) { // Fill in the caps we support int i; for(i=0;i<_iT126_MAX_COLLAPSING_CAPABILITIES;i++) { g_CapArray[i].capability_id.capability_id_type = GCC_STANDARD_CAPABILITY; g_CapArray[i].capability_id.standard_capability = GCCCaps[i].CapValue; g_CapArray[i].capability_class.eType = GCCCaps[i].Type; if( GCCCaps[i].CapValue == Soft_Copy_Workspace_Max_Width) { GCCCaps[i].MinValue = DRAW_WIDTH + 1; GCCCaps[i].MaxValue = DRAW_WIDTH - 1; } if(GCCCaps[i].CapValue == Soft_Copy_Workspace_Max_Height) { GCCCaps[i].MinValue = DRAW_HEIGHT + 1; GCCCaps[i].MaxValue = DRAW_HEIGHT - 1; } if(GCCCaps[i].CapValue == Soft_Copy_Workspace_Max_Planes) { GCCCaps[i].MinValue = WB_MAX_WORKSPACES + 1; GCCCaps[i].MaxValue = WB_MAX_WORKSPACES - 1; } if(GCCCaps[i].Type == GCC_UNSIGNED_MINIMUM_CAPABILITY) { g_CapArray[i].capability_class.nMinOrMax = GCCCaps[i].MinValue - 1; } else if ((GCCCaps[i].Type == GCC_UNSIGNED_MAXIMUM_CAPABILITY)) { g_CapArray[i].capability_class.nMinOrMax = GCCCaps[i].MaxValue + 1; } else { g_CapArray[i].capability_class.nMinOrMax = 0; } g_CapArray[i].number_of_entities = 0; g_CapPtrList[i] = &g_CapArray[i]; } // // Non-Collapsed Capabilities // g_NCCapArray[0].capability_id.capability_id_type = GCC_STANDARD_CAPABILITY; g_NCCapArray[0].capability_id.standard_capability = _iT126_TEXT_CAPABILITY_ID; g_NCCapArray[0].application_data = (OSTR *) &s_AppData[0]; // // How many bits per pixel can we handle? // HDC hDC = CreateCompatibleDC(NULL); if((GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)) >= 24) { m_bICanDo24BitBitmaps = TRUE; g_NCCapArray[1].capability_id.capability_id_type = GCC_STANDARD_CAPABILITY; g_NCCapArray[1].capability_id.standard_capability = _iT126_24BIT_BITMAP_ID; g_NCCapArray[1].application_data = (OSTR *) &s_AppData[1]; } else { m_bICanDo24BitBitmaps = FALSE; } if (hDC) { DeleteDC(hDC); } } // // T120 Applet Functions // void CALLBACK T120AppletCallbackProc ( T120AppletMsg *pMsg ) { CNMWbObj *pWBOBJ = (CNMWbObj *) pMsg->pAppletContext; if (pWBOBJ == g_pNMWBOBJ) { switch (pMsg->eMsgType) { case GCC_PERMIT_TO_ENROLL_INDICATION: pWBOBJ->OnPermitToEnroll(pMsg->PermitToEnrollInd.nConfID, pMsg->PermitToEnrollInd.fPermissionGranted); break; case T120_JOIN_SESSION_CONFIRM: default: break; } } } void CALLBACK T120SessionCallbackProc ( T120AppletSessionMsg *pMsg ) { if(g_pNMWBOBJ == NULL) { return; } CNMWbObj *pSession = (CNMWbObj *) pMsg->pSessionContext; ASSERT(pMsg->pAppletContext == pMsg->pSessionContext); if (pSession == g_pNMWBOBJ) { ASSERT(pMsg->nConfID == pSession->GetConfID()); switch (pMsg->eMsgType) { case MCS_UNIFORM_SEND_DATA_INDICATION: // // Check if we are receiving a indication from owrself // if(pMsg->SendDataInd.initiator == GET_USER_ID_FROM_MEMBER_ID(g_MyMemberID)) { return; } case MCS_SEND_DATA_INDICATION: ::T126_MCSSendDataIndication( pMsg->SendDataInd.user_data.length, pMsg->SendDataInd.user_data.value, pMsg->SendDataInd.initiator, FALSE); break; case MCS_TRANSMIT_BUFFER_AVAILABLE_INDICATION: g_fWaitingForBufferAvailable = FALSE; RetrySend(); break; case GCC_APP_ROSTER_REPORT_INDICATION: pSession->OnRosterIndication((ULONG) pMsg->AppRosterReportInd.cRosters, pMsg->AppRosterReportInd.apAppRosters); break; case GCC_ALLOCATE_HANDLE_CONFIRM: pSession->OnAllocateHandleConfirm(&pMsg->RegAllocHandleConfirm); break; case T120_JOIN_SESSION_CONFIRM: pSession->OnJoinSessionConfirm(&pMsg->JoinSessionConfirm); break; case MCS_TOKEN_GRAB_CONFIRM: TRACE_DEBUG(("MCS_TOKEN_GRAB_CONFIRM result = %d",pMsg->TokenConfirm.eResult)); if(pMsg->TokenConfirm.eResult == T120_RESULT_SUCCESSFUL) { TRACE_DEBUG((">>> I'm the T126 REFRESHER <<<")); g_pNMWBOBJ->m_bImTheT126Refresher = TRUE; // // Tell everybody I'm the refresher // SendWorkspaceRefreshPDU(TRUE); g_RefresherID = g_MyMemberID; } else { TRACE_DEBUG((">>> I'm NOT the T126 REFRESHER <<<")); // if we are not the t126 refresher, we should save the previous work if (!g_pNMWBOBJ->m_bImTheT126Refresher) { if(!g_pNMWBOBJ->IsInConference()) { if (g_pMain && (g_pMain->QuerySaveRequired(FALSE) == IDYES)) { g_pMain->OnSave(FALSE); } // // If we were waiting on the save contents dialog // and the whole conference and UI are exiting, g_pMain could be NULL // Or if we are not in a call anymore, we don't need to delete all the local workspaces. // if(g_pMain == NULL || !g_pNMWBOBJ->IsInConference()) { return; } ::InvalidateRect(g_pDraw->m_hwnd, NULL, TRUE); DeleteAllWorkspaces(FALSE); // // Fill up the GCC tank // TimeToGetGCCHandles(PREALLOC_GCC_HANDLES); } // ELSE // If we got here and we are in a call don't do a thing. // We just got here because the refresher went away. We tried // to grab the token and we lost it to a faster node. // } } break; default: break; } } } void CNMWbObj::OnPermitToEnroll ( T120ConfID nConfID, BOOL fPermissionGranted ) { if (fPermissionGranted) { // We are not in a conference, right? ASSERT(NULL == m_pAppletSession); m_bConferenceOnlyNetmeetingNodes = TRUE; // Create an applet session T120Error rc = m_pApplet->CreateSession(&m_pAppletSession, nConfID); if (T120_NO_ERROR == rc) { ASSERT(NULL != m_pAppletSession); m_pAppletSession->Advise(T120SessionCallbackProc, this, this); // get top provider information m_bImTheTopProvider = m_pAppletSession->IsThisNodeTopProvider(); // Build join-sesion request ::ZeroMemory(&m_JoinSessionReq, sizeof(m_JoinSessionReq)); m_JoinSessionReq.dwAttachmentFlags = ATTACHMENT_DISCONNECT_IN_DATA_LOSS | ATTACHMENT_MCS_FREES_DATA_IND_BUFFER; m_JoinSessionReq.SessionKey.application_protocol_key.key_type = GCC_OBJECT_KEY; m_JoinSessionReq.SessionKey.application_protocol_key.object_id.long_string = (ULONG *) g_T126KeyNodes; m_JoinSessionReq.SessionKey.application_protocol_key.object_id.long_string_length = sizeof(g_T126KeyNodes) / sizeof(g_T126KeyNodes[0]); m_JoinSessionReq.SessionKey.session_id = _SI_CHANNEL_0; m_JoinSessionReq.fConductingCapable = FALSE; m_JoinSessionReq.nStartupChannelType =MCS_STATIC_CHANNEL; m_JoinSessionReq.cNonCollapsedCaps =1 + (m_bICanDo24BitBitmaps ? 1 : 0); m_JoinSessionReq.apNonCollapsedCaps = (GCCNonCollCap **) g_NCCapPtrList; m_JoinSessionReq.cCollapsedCaps = sizeof(g_CapPtrList) / sizeof(g_CapPtrList[0]); ASSERT(_iT126_MAX_COLLAPSING_CAPABILITIES == sizeof(g_CapPtrList) / sizeof(g_CapPtrList[0])); m_JoinSessionReq.apCollapsedCaps = g_CapPtrList; m_JoinSessionReq.cStaticChannels = sizeof(g_aStaticChannels) / sizeof(g_aStaticChannels[0]); m_JoinSessionReq.aStaticChannels = (T120ChannelID *) g_aStaticChannels; // // Token to grab // ::ZeroMemory(&m_tokenResourceRequest, sizeof(m_tokenResourceRequest)); m_tokenResourceRequest.eCommand = APPLET_GRAB_TOKEN_REQUEST; // m_tokenRequest.nChannelID = _SI_CHANNEL_0; m_tokenResourceRequest.nTokenID = _SI_WORKSPACE_REFRESH_TOKEN; m_tokenResourceRequest.fImmediateNotification = TRUE; m_JoinSessionReq.cResourceReqs = 1; m_JoinSessionReq.aResourceReqs = &m_tokenResourceRequest; // Join now rc = m_pAppletSession->Join(&m_JoinSessionReq); if (T120_NO_ERROR == rc) { m_nConfID = nConfID; // // JOSEF NOW SET THE MAIN WINDOW STATUS } else { WARNING_OUT(("CNMWbObj::OnPermitToEnroll: cannot join conf=%u, rc=%u", nConfID, rc)); } } } else { if (NULL != m_pAppletSession) { m_pAppletSession->ReleaseInterface(); CleanupPerConf(); } } } void CNMWbObj::OnJoinSessionConfirm ( T120JoinSessionConfirm *pConfirm ) { if (NULL != m_pAppletSession) { ASSERT(m_pAppletSession == pConfirm->pIAppletSession); if (T120_RESULT_SUCCESSFUL == pConfirm->eResult) { m_uidMyself = pConfirm->uidMyself; m_sidMyself = pConfirm->sidMyself; m_eidMyself = pConfirm->eidMyself; m_nidMyself = pConfirm->nidMyself; // create member ID g_MyMemberID = MAKE_MEMBER_ID(m_nidMyself, m_uidMyself); if(g_pDraw && g_pDraw->IsLocked()) { m_LockerID = g_MyMemberID; } // regardless, update the index anyway g_MyIndex = (m_uidMyself + NUMCOLS) % NUMCLRPANES; // we are now in the conference m_fInConference = TRUE; // allocate handles for all objects if (m_bImTheT126Refresher) { g_RefresherID = g_MyMemberID; // // Resend all objects // WBPOSITION pos; WBPOSITION posObj; WorkspaceObj* pWorkspace; T126Obj* pObj; pos = g_pListOfWorkspaces->GetHeadPosition(); while(pos) { pWorkspace = (WorkspaceObj*)g_pListOfWorkspaces->GetNext(pos); g_pListOfObjectsThatRequestedHandles->AddHead(pWorkspace); posObj = pWorkspace->GetHeadPosition(); while(posObj) { pObj = pWorkspace->GetNextObject(posObj); if(pObj) { g_pListOfObjectsThatRequestedHandles->AddHead(pObj); } } } // // Delete the fake handles we had // g_WaitingForGCCHandles = FALSE; g_GCCPreallocHandles[0].GccHandleCount = 0; g_GCCPreallocHandles[1].GccHandleCount = 0; TimeToGetGCCHandles(g_numberOfObjects + g_numberOfWorkspaces + PREALLOC_GCC_HANDLES); } else { ::InvalidateRect(g_pDraw->m_hwnd, NULL, TRUE); DeleteAllWorkspaces(FALSE); } } else { WARNING_OUT(("CNMWbObj::OnJoinSessionConfirm: failed to join conference, result=%u. error=%u", pConfirm->eResult, pConfirm->eError)); ASSERT(GCC_CONFERENCE_NOT_ESTABLISHED == pConfirm->eError); m_pAppletSession->ReleaseInterface(); CleanupPerConf(); } } } void CNMWbObj::OnAllocateHandleConfirm ( GCCRegAllocateHandleConfirm *pConfirm ) { if (T120_RESULT_SUCCESSFUL == pConfirm->nResult) { ::T126_GCCAllocateHandleConfirm(pConfirm->nFirstHandle, pConfirm->cHandles); } else { ERROR_OUT(("CNMWbObj::OnAllocateHandleConfirm: failed to allocate %u handles, result=%u", pConfirm->cHandles, pConfirm->nResult)); } } void CNMWbObj::OnRosterIndication ( ULONG cRosters, GCCAppRoster *apRosters[] ) { if (IsInConference()) { BOOL fAdded = FALSE; BOOL fRemoved = FALSE; ULONG cOtherMembers = 0; ULONG i, j, k; // Caculate how many members in this session for (i = 0; i < cRosters; i++) { GCCAppRoster *pRoster = apRosters[i]; // bail out if this roster is not for this session if (pRoster->session_key.session_id != m_sidMyself) { continue; } // node added or removed? fAdded |= pRoster->nodes_were_added; fRemoved |= pRoster->nodes_were_removed; BOOL conferenceCanDo24BitBitmap = TRUE; BOOL conferenceCanDoText = TRUE; // parse the roster records for (j = 0; j < pRoster->number_of_records; j++) { GCCAppRecord *pRecord = pRoster->application_record_list[j]; if (pRecord->is_enrolled_actively) { MEMBER_ID nMemberID = MAKE_MEMBER_ID(pRecord->node_id, pRecord->application_user_id); if (nMemberID != g_MyMemberID) { // // Only count T126 apps // if((pRoster->session_key.application_protocol_key.key_type == GCC_OBJECT_KEY && pRoster->session_key.application_protocol_key.object_id.long_string_length == sizeof(g_T126KeyNodes) / sizeof(g_T126KeyNodes[0]) && !memcmp (pRoster->session_key.application_protocol_key.object_id.long_string, g_T126KeyNodes, sizeof(g_T126KeyNodes)))) { cOtherMembers++; m_instanceNumber = pRoster->instance_number; if(T120_GetNodeVersion(m_nConfID, pRecord->node_id) < 0x404) { m_bConferenceOnlyNetmeetingNodes = FALSE; } } } // // Can we do 24 color bitmap // BOOL nodeCanDo24BitBitmap = FALSE; BOOL nodeCanDoText = FALSE; for (k = 0; k < pRecord->number_of_non_collapsed_caps; k++) { // // Check if the node handles 24 bit bitmaps // if(pRecord->non_collapsed_caps_list[k]->application_data->length == sizeof(T126_24BIT_STRING)) { if(!memcmp(pRecord->non_collapsed_caps_list[k]->application_data->value, T126_24BIT_STRING ,sizeof(T126_24BIT_STRING))) { nodeCanDo24BitBitmap = TRUE; } } // // Check if the node handles text // if(pRecord->non_collapsed_caps_list[k]->application_data->length == sizeof(T126_TEXT_STRING)) { if(!memcmp(pRecord->non_collapsed_caps_list[k]->application_data->value, T126_TEXT_STRING ,sizeof(T126_TEXT_STRING))) { nodeCanDoText = TRUE; } } } conferenceCanDo24BitBitmap &= nodeCanDo24BitBitmap; conferenceCanDoText &= nodeCanDoText; } } // for m_bConferenceCanDo24BitBitmaps = conferenceCanDo24BitBitmap; m_bConferenceCanDoText = conferenceCanDoText; } // for // If there are changes, we then do the update if (fAdded || fRemoved || cOtherMembers != m_cOtherMembers) { MEMBER_ID aTempMembers[MAX_MEMBERS]; // scratch copy // make sure we are able to handle it if (cOtherMembers >= MAX_MEMBERS) { ERROR_OUT(("CNMWbObj::OnRosterIndication: we hit the max members limit, cOtherMembers=%u, max-members=%u", cOtherMembers, MAX_MEMBERS)); cOtherMembers = MAX_MEMBERS; } // reset the flags for members added and removed fAdded = FALSE; fRemoved = FALSE; // copy the members ULONG idxTempMember = 0; for (i = 0; i < cRosters; i++) { GCCAppRoster *pRoster = apRosters[i]; // bail out if this roster is not for this session if (pRoster->session_key.session_id != m_sidMyself) { continue; } // parse the roster records for (j = 0; j < pRoster->number_of_records; j++) { GCCAppRecord *pRecord = pRoster->application_record_list[j]; if (pRecord->is_enrolled_actively) { MEMBER_ID nMemberID = MAKE_MEMBER_ID(pRecord->node_id, pRecord->application_user_id); if (nMemberID != g_MyMemberID && idxTempMember < cOtherMembers) { aTempMembers[idxTempMember++] = nMemberID; // let's see if it is an 'add' or a 'delete' for (k = 0; k < m_cOtherMembers; k++) { if (m_aMembers[k] == nMemberID) { m_aMembers[k] = 0; break; } } fAdded |= (k >= m_cOtherMembers); // not found, must be new } } } // for } // for // sanity check ASSERT(idxTempMember == cOtherMembers); // see if there are ones that are not in the new roster. // if so, they must be removed. for (k = 0; k < m_cOtherMembers; k++) { if (m_aMembers[k]) { fRemoved = TRUE; ULONG memberID = GET_USER_ID_FROM_MEMBER_ID(m_aMembers[k]); TRACE_DEBUG(("OnRosterIndication removing RemotePointer from member =%x", memberID)); RemoveRemotePointer(memberID); // // if the refresher went away // if(g_RefresherID == memberID) { GrabRefresherToken(); } // // if node locking went away // if(m_LockerID == memberID) { TogleLockInAllWorkspaces(FALSE, FALSE); // Not locked, don't send updates g_pMain->UnlockDrawingArea(); g_pMain->m_TB.PopUp(IDM_LOCK); g_pMain->UncheckMenuItem(IDM_LOCK); m_LockerID = 0; } } } // now, update the member array m_cOtherMembers = cOtherMembers; if (m_cOtherMembers) { ASSERT(sizeof(m_aMembers[0]) == sizeof(aTempMembers[0])); ::CopyMemory(&m_aMembers[0], &aTempMembers[0], m_cOtherMembers * sizeof(m_aMembers[0])); } // if added, resend all objects if (fAdded && (m_bImTheT126Refresher)) { // // Tell the new node that I'm the refresher // SendWorkspaceRefreshPDU(TRUE); // // Refresh the new node // ResendAllObjects(); // // if node locking everybody went away // if(m_LockerID == g_MyMemberID) { TogleLockInAllWorkspaces(TRUE, TRUE); // Locked, send updates } // // Syncronize it // if(g_pCurrentWorkspace) { g_pCurrentWorkspace->OnObjectEdit(); } } // finally, update the caption if(g_pMain) { g_pMain->UpdateWindowTitle(); } } // if any change } // if is in conf } void CNMWbObj::CleanupPerConf(void) { m_fInConference = FALSE; m_pAppletSession = NULL; g_MyMemberID = 0; g_RefresherID = 0; m_nConfID = 0; // Conf ID m_uidMyself = 0; // User ID m_sidMyself = 0; // Session ID m_eidMyself = 0; // Entity ID m_nidMyself = 0; // Node ID m_bImTheTopProvider = FALSE; m_bImTheT126Refresher = FALSE; m_bConferenceOnlyNetmeetingNodes = TRUE; m_cOtherMembers = 0; if(g_pMain) { g_pMain->UpdateWindowTitle(); RemoveRemotePointer(0); DeleteAllRetryPDUS(); g_pListOfObjectsThatRequestedHandles->EmptyList(); ASSERT(g_pDraw); // // If we were locked // if(g_pDraw->IsLocked()) { m_LockerID = g_MyMemberID; TogleLockInAllWorkspaces(FALSE, FALSE); // Not locked, don't send updates g_pMain->UnlockDrawingArea(); g_pMain->m_TB.PopUp(IDM_LOCK); g_pMain->UncheckMenuItem(IDM_LOCK); } } m_LockerID = 0; } T120Error CNMWbObj::SendData ( T120Priority ePriority, ULONG cbDataSize, PBYTE pbData ) { T120Error rc; if (IsInConference()) { rc = m_pAppletSession->SendData( UNIFORM_SEND_DATA, _SI_CHANNEL_0, ePriority, pbData, cbDataSize, APP_ALLOCATION); } else { rc = GCC_CONFERENCE_NOT_ESTABLISHED; } return rc; } T120Error CNMWbObj::GrabRefresherToken(void) { T120Error rc; if (IsInConference()) { T120TokenRequest Req; Req.eCommand = APPLET_GRAB_TOKEN; Req.nTokenID = _SI_WORKSPACE_REFRESH_TOKEN; Req.uidGiveTo = m_uidMyself; Req.eGiveResponse = T120_RESULT_SUCCESSFUL; rc = m_pAppletSession->TokenRequest(&Req); if (T120_NO_ERROR != rc) { WARNING_OUT(("CNMWbObj::AllocateHandles: TokenRequest")); } } else { rc = GCC_CONFERENCE_NOT_ESTABLISHED; } return rc; } T120Error CNMWbObj::AllocateHandles ( ULONG cHandles ) { T120Error rc; if ( cHandles > 0 && IsInConference()) { T120RegistryRequest Req; Req.eCommand = APPLET_ALLOCATE_HANDLE; Req.pRegistryKey = NULL; Req.cHandles = cHandles; rc = m_pAppletSession->RegistryRequest(&Req); if (T120_NO_ERROR != rc) { ERROR_OUT(("CNMWbObj::AllocateHandles: RegistryRequest(cHandles=%u), rc=%u", cHandles, rc)); } } else { rc = GCC_CONFERENCE_NOT_ESTABLISHED; } return rc; }