|
|
// File: ichnldat.cpp
//
// INmChannelData
//
#include "precomp.h"
#include <confguid.h>
static const IID * g_apiidCP[] = { {&IID_INmChannelDataNotify} };
#define CopyStruct(pDest, pSrc) CopyMemory(pDest, pSrc, sizeof(*(pDest)))
#define MAX_NM_PEER 256 // Maximum number of NetMeeting Peer applications/users
#ifdef DEBUG /* T.120 Debug utilities */
LPCTSTR GetGccErrorString(GCCError uErr); LPCTSTR GetMcsErrorString(MCSError uErr); LPCTSTR GetGccResultString(UINT uErr); LPCTSTR GetMcsResultString(UINT uErr); #else
#define GetGccErrorString(uErr) ""
#define GetMcsErrorString(uErr) ""
#define GetGccResultString(uErr) ""
#define GetMcsResultString(uErr) ""
#endif /* DEBUG */
// code from nm\ui\conf\cuserdta.cpp:
static unsigned char H221IDGUID[5] = {H221GUIDKEY0, H221GUIDKEY1, H221GUIDKEY2, H221GUIDKEY3, H221GUIDKEY4};
extern VOID CreateH221AppKeyFromGuid(LPBYTE lpb, GUID * pguid);
/* S E T A P P K E Y */ /*----------------------------------------------------------------------------
%%Function: SetAppKey
Set the two pieces of an OctetString (the length and the data.) Note that the length always includes the terminating null character. ----------------------------------------------------------------------------*/ VOID SetAppKey(LPOSTR pOct, LPBYTE lpb) { pOct->length = cbKeyApp; pOct->value = lpb; }
/* C R E A T E A P P K E Y */ /*----------------------------------------------------------------------------
%%Function: CreateAppKey
Given a guid and a userid, create the appropriate application key.
The key is formated as: 0xB5 0x00 0x53 0x4C - Microsoft Object Identifier 0x01 - guid identifier <binary guid> - guid data <dword node id> - user node id ----------------------------------------------------------------------------*/ VOID CreateAppKey(LPBYTE lpb, GUID * pguid, DWORD dwUserId) { CreateH221AppKeyFromGuid(lpb, pguid); CopyMemory(lpb + cbKeyApp - sizeof(DWORD), &dwUserId, sizeof(DWORD));
#ifdef DEBUG
TCHAR szGuid[LENGTH_SZGUID_FORMATTED]; GuidToSz(pguid, szGuid); TRACE_OUT(("CreateAppKey: %s %08X", szGuid, dwUserId)); #endif
}
/* P M E M B E R F R O M D W U S E R I D */ /*-------------------------------------------------------------------------
%%Function: PMemberFromDwUserId
-------------------------------------------------------------------------*/ CNmMember * PMemberFromDwUserId(DWORD dwUserId, COBLIST *pList) { if (NULL != pList) { POSITION posCurr; POSITION pos = pList->GetHeadPosition(); while (NULL != pos) { posCurr = pos; CNmMember * pMember = (CNmMember *) pList->GetNext(pos); if (dwUserId == pMember->GetGCCID()) { pMember->AddRef(); return pMember; } } } return NULL; }
/* A D D N O D E */ /*-------------------------------------------------------------------------
%%Function: AddNode
Add a node to a list. Initializes the ObList, if necessary. Returns the position in the list or NULL if there was a problem. -------------------------------------------------------------------------*/ POSITION AddNode(PVOID pv, COBLIST ** ppList) { ASSERT(NULL != ppList); if (NULL == *ppList) { *ppList = new COBLIST(); if (NULL == *ppList) return NULL; }
return (*ppList)->AddTail(pv); }
/* R E M O V E N O D E */ /*-------------------------------------------------------------------------
%%Function: RemoveNode
Remove a node from a list. Sets pPos to NULL -------------------------------------------------------------------------*/ PVOID RemoveNodePos(POSITION * pPos, COBLIST *pList) { if ((NULL == pList) || (NULL == pPos)) return NULL;
PVOID pv = pList->RemoveAt(*pPos); *pPos = NULL; return pv; }
/* R E M O V E N O D E */ /*-------------------------------------------------------------------------
%%Function: RemoveNode
-------------------------------------------------------------------------*/ VOID RemoveNode(PVOID pv, COBLIST * pList) { ASSERT(NULL != pv);
if (NULL != pList) { POSITION pos = pList->GetPosition(pv); RemoveNodePos(&pos, pList); } }
VOID CNmChannelData::InitCT120Channel(DWORD dwUserId) { m_dwUserId = dwUserId; m_gcc_conference_id = 0; m_gcc_pIAppSap = NULL; m_mcs_channel_id = 0; m_pmcs_sap = NULL; m_gcc_node_id = 0; m_scs = SCS_UNINITIALIZED;
m_pGuid = PGuid(); ASSERT((NULL != m_pGuid) && (GUID_NULL != *m_pGuid));
CreateAppKey(m_keyApp, m_pGuid, 0); CreateAppKey(m_keyChannel, m_pGuid, dwUserId);
// initialize other gcc & mcs stuff
GCCObjectKey FAR * pObjKey; ClearStruct(&m_gcc_session_key); pObjKey = &(m_gcc_session_key.application_protocol_key); pObjKey->key_type = GCC_H221_NONSTANDARD_KEY; SetAppKey(&(pObjKey->h221_non_standard_id), m_keyApp); ASSERT(0 == m_gcc_session_key.session_id);
ClearStruct(&m_gcc_registry_item); ClearStruct(&m_gcc_registry_key); CopyStruct(&m_gcc_registry_key.session_key, &m_gcc_session_key); SetAppKey(&m_gcc_registry_key.resource_id, m_keyApp);
ClearStruct(&m_registry_item_Private); ClearStruct(&m_registry_key_Private); CopyStruct(&m_registry_key_Private.session_key, &m_gcc_session_key); SetAppKey(&m_registry_key_Private.resource_id, m_keyChannel);
UpdateScState(SCS_UNINITIALIZED, 0); }
/* C L O S E C H A N N E L */ /*----------------------------------------------------------------------------
%%Function: CloseChannel
Close the channel.
Note there are no confirm messages expected for any of the GCC/MCS calls. ----------------------------------------------------------------------------*/ VOID CNmChannelData::CloseChannel(void) { GCCError gccError = GCC_NO_ERROR; MCSError mcsError = MCS_NO_ERROR;
if (SCS_UNINITIALIZED == m_scs) { WARNING_OUT(("in CT120Channel::CloseChannel, m_scs is SCS_UNINITIALIZED, is this OK?")); return; }
TRACE_OUT(("CT120Channel::CloseChannel %08X (userHandle=%p)", m_mcs_channel_id, m_pmcs_sap));
m_scs = SCS_TERMINATING;
if (0 != m_mcs_channel_id) { ASSERT (m_pmcs_sap); mcsError = m_pmcs_sap->ChannelLeave(m_mcs_channel_id); TRACE_OUT(("CT120Channel::CloseChannel: ChannelLeave %s", GetMcsErrorString(mcsError))); m_mcs_channel_id = 0; }
if (NULL != m_pmcs_sap) { mcsError = m_pmcs_sap->ReleaseInterface(); TRACE_OUT(("CT120Channel::CloseChannel: MCS ReleaseInterface %s", GetMcsErrorString(mcsError))); m_pmcs_sap = NULL; }
if (NULL != m_gcc_pIAppSap) { m_gcc_pIAppSap->RegistryDeleteEntry(m_gcc_conference_id, &m_registry_key_Private); // ignore the above result
m_gcc_pIAppSap->ReleaseInterface(); TRACE_OUT(("CT120Channel::CloseChannel: GCCDeleteSap %s", GetGccErrorString(gccError))); m_gcc_pIAppSap = NULL; }
m_scs = SCS_UNINITIALIZED; m_gcc_conference_id = 0;
// make sure no one is around
UpdateRoster(NULL, 0, FALSE, TRUE /* fRemove */);; }
/* U P D A T E S C S T A T E */ /*----------------------------------------------------------------------------
%%Function: UpdateScState
The system progresses from one state to another by making an GCC (or MCS) call that is guarenteed to produce a notification that calls this function. The calling process is released by UnBlockThread. ----------------------------------------------------------------------------*/ VOID CNmChannelData::UpdateScState(SCSTATE scs, DWORD dwErr) { DBGENTRY(CNmChannelData::UpdateScState) if (m_scs != scs) { WARNING_OUT(("UpdateScState - invalid state transition (%d - %d)", m_scs, scs)); dwErr = INVALID_T120_ERROR; // We should never get here
}
if (0 == dwErr) { switch (m_scs) { case SCS_UNINITIALIZED: dwErr = DoCreateSap(); break; case SCS_CREATESAP: dwErr = DoAttach(); break; case SCS_ATTACH: dwErr = DoEnroll(); break; case SCS_ENROLL: dwErr = DoJoinPrivate(); break; case SCS_JOIN_PRIVATE: dwErr = DoRegRetrieve(); break; case SCS_REGRETRIEVE_NEW: dwErr = DoJoinNew(); break; case SCS_REGRETRIEVE_EXISTS: dwErr = DoJoinOld(); break; case SCS_JOIN_NEW: dwErr = DoRegChannel(); break; case SCS_REGCHANNEL: case SCS_JOIN_OLD: dwErr = DoRegPrivate(); break; case SCS_REGPRIVATE: TRACE_OUT((">>>>>>>>>>>UpdateScState: Complete")); m_scs = SCS_CONNECTED; NotifyChannelConnected(); break; case SCS_CONNECTED: case SCS_REGRETRIEVE: // we should never be called when we're in these states
// so, treat it as an error and fall thru to the default case
default: dwErr = INVALID_T120_ERROR; // We should never get here
break; } }
TRACE_OUT(("UpdateScState: New state (%d) channelId=%04X", m_scs, GetMcsChannelId()));
if (0 != dwErr) { WARNING_OUT(("UpdateScState: Err=%d", dwErr)); CloseConnection(); }
DBGEXIT(CNmChannelData::UpdateScState) }
DWORD CNmChannelData::DoCreateSap(void) { ASSERT(SCS_UNINITIALIZED == m_scs); m_scs = SCS_CREATESAP;
GCCError gccError = GCC_CreateAppSap(&m_gcc_pIAppSap, this, NmGccMsgHandler); TRACE_OUT(("GCCCreateSap err=%s", GetGccErrorString(gccError))); return (DWORD) gccError; }
DWORD CNmChannelData::DoAttach(void) { ASSERT(SCS_CREATESAP == m_scs); m_scs = SCS_ATTACH;
MCSError mcsError = MCS_AttachRequest(&m_pmcs_sap, (DomainSelector) &m_gcc_conference_id, sizeof(m_gcc_conference_id), NmMcsMsgHandler, this, ATTACHMENT_DISCONNECT_IN_DATA_LOSS | ATTACHMENT_MCS_FREES_DATA_IND_BUFFER); // This generates an async MCS_ATTACH_USER_CONFIRM
TRACE_OUT(("MCS_AttachRequest err=%s", GetMcsErrorString(mcsError))); return (DWORD) mcsError; }
DWORD CNmChannelData::DoEnroll(void) { ASSERT(SCS_ATTACH == m_scs || SCS_JOIN_STATIC_CHANNEL); m_scs = SCS_ENROLL;
GCCEnrollRequest er; GCCRequestTag nReqTag;
if(m_pGCCER) { m_pGCCER->pSessionKey = &m_gcc_session_key; m_pGCCER->nUserID = m_mcs_sender_id;
} else { // fill in enroll request structure
::ZeroMemory(&er, sizeof(er)); er.pSessionKey = &m_gcc_session_key; er.fEnrollActively = TRUE; er.nUserID = m_mcs_sender_id; // er.fConductingCapabable = FALSE;
er.nStartupChannelType = MCS_DYNAMIC_MULTICAST_CHANNEL; // er.cNonCollapsedCaps = 0;
// er.apNonCollapsedCaps = NULL;
// er.cCollapsedCaps = 0;
// er.apCollapsedCaps = NULL;
er.fEnroll = TRUE; }
GCCError gccError = m_gcc_pIAppSap->AppEnroll(m_gcc_conference_id, m_pGCCER != NULL ? m_pGCCER : &er, &nReqTag);
TRACE_OUT(("GCCApplicationEnrollRequest err=%s", GetGccErrorString(gccError)));
if (GCC_NO_ERROR != gccError) { ERROR_OUT(("DoEnroll failed - WHY?")); }
return (DWORD) gccError; }
// Join the PRIVATE data channel (m_mcs_sender_id)
DWORD CNmChannelData::DoJoinPrivate(void) { ASSERT(SCS_ENROLL == m_scs || SCS_ATTACH == m_scs); m_scs = SCS_JOIN_PRIVATE;
MCSError mcsError = m_pmcs_sap->ChannelJoin(m_mcs_sender_id); // This generates an async MCS_CHANNEL_JOIN_CONFIRM
TRACE_OUT(("MCSChannelJoinRequest (private) %04X, err=%s", m_mcs_sender_id, GetMcsErrorString(mcsError))); return (DWORD) mcsError; }
DWORD CNmChannelData::DoRegRetrieve(void) { ASSERT(SCS_JOIN_PRIVATE == m_scs); m_scs = SCS_REGRETRIEVE;
GCCError gccError = m_gcc_pIAppSap->RegistryRetrieveEntry( m_gcc_conference_id, &m_gcc_registry_key); // This generates an async GCC_RETRIEVE_ENTRY_CONFIRM
TRACE_OUT(("GCCRegistryRetrieveEntryRequest err=%s", GetGccErrorString(gccError))); return (DWORD) gccError; }
// Register the PUBLIC channel
DWORD CNmChannelData::DoRegChannel(void) { ASSERT(SCS_JOIN_NEW == m_scs); m_scs = SCS_REGCHANNEL;
GCCError gccError = m_gcc_pIAppSap->RegisterChannel( m_gcc_conference_id, &m_gcc_registry_key, m_mcs_channel_id); // This generates an async GCC_REGISTER_CHANNEL_CONFIRM
TRACE_OUT(("GCCRegisterChannelRequest err=%s", GetGccErrorString(gccError))); return (DWORD) gccError; }
DWORD CNmChannelData::DoJoinStatic(ChannelID staticChannel) { m_scs = SCS_JOIN_STATIC_CHANNEL; MCSError mcsError = m_pmcs_sap->ChannelJoin(staticChannel); // This generates an async MCS_CHANNEL_JOIN_CONFIRM
TRACE_OUT(("MCSChannelJoinRequest %04X, err=%s", staticChannel, GetMcsErrorString(mcsError))); return (DWORD) mcsError; }
DWORD CNmChannelData::DoJoin(SCSTATE scs) { m_scs = scs;
MCSError mcsError = m_pmcs_sap->ChannelJoin(m_mcs_channel_id); // This generates an async MCS_CHANNEL_JOIN_CONFIRM
TRACE_OUT(("MCSChannelJoinRequest %04X, err=%s", m_mcs_channel_id, GetMcsErrorString(mcsError))); return (DWORD) mcsError; }
DWORD CNmChannelData::DoJoinNew(void) { ASSERT(0 == m_mcs_channel_id); ASSERT(SCS_REGRETRIEVE_NEW == m_scs); return DoJoin(SCS_JOIN_NEW); }
DWORD CNmChannelData::DoJoinOld(void) { ASSERT(0 != m_mcs_channel_id); ASSERT(SCS_REGRETRIEVE_EXISTS == m_scs); return DoJoin(SCS_JOIN_OLD); }
// Register the PRIVATE data channel. (m_mcs_sender_id)
DWORD CNmChannelData::DoRegPrivate(void) { ASSERT(0 != m_mcs_sender_id); ASSERT((SCS_REGCHANNEL == m_scs) || (SCS_JOIN_OLD == m_scs)); m_scs = SCS_REGPRIVATE;
TRACE_OUT(("DoRegPrivate: channelId %04X as private for %08X", m_mcs_sender_id, m_dwUserId));
GCCError gccError = m_gcc_pIAppSap->RegisterChannel( m_gcc_conference_id, &m_registry_key_Private, m_mcs_sender_id); // This generates an async GCC_REGISTER_CHANNEL_CONFIRM
TRACE_OUT(("GCCRegisterChannelRequest err=%s", GetGccErrorString(gccError))); return (DWORD) gccError; }
// deal with a GCC_RETRIEVE_ENTRY_CONFIRM notification
VOID CNmChannelData::ProcessEntryConfirm(GCCAppSapMsg * pMsg) { if (pMsg->RegistryConfirm.pRegKey->resource_id.length >= m_gcc_registry_key.resource_id.length && 0 != memcmp(m_gcc_registry_key.resource_id.value, pMsg->RegistryConfirm.pRegKey->resource_id.value, m_gcc_registry_key.resource_id.length)) { OnEntryConfirmRemote(pMsg); } else { OnEntryConfirmLocal(pMsg); } }
// deal with a GCC_REGISTRY_HANDLE_CONFIRM notification
VOID CNmChannelData::ProcessHandleConfirm(GCCAppSapMsg * pMsg) { ASSERT(NULL != pMsg); NotifySink(&pMsg->RegAllocHandleConfirm, OnAllocateHandleConfirm); }
VOID CNmChannelData::OnEntryConfirmRemote(GCCAppSapMsg * pMsg) { DWORD dwUserId; ASSERT(cbKeyApp == pMsg->RegistryConfirm.pRegKey->resource_id.length); CopyMemory(&dwUserId, pMsg->RegistryConfirm.pRegKey->resource_id.value + cbKeyApp - sizeof(DWORD), sizeof(DWORD));
TRACE_OUT(("GCC_RETRIEVE_ENTRY_CONFIRM: user private channelId = %04X for userId=%04X result=%s", pMsg->RegistryConfirm.pRegItem->channel_id, dwUserId, GetGccResultString(pMsg->RegistryConfirm.nResult)));
if (GCC_RESULT_SUCCESSFUL == pMsg->RegistryConfirm.nResult) { UpdateMemberChannelId(dwUserId, pMsg->RegistryConfirm.pRegItem->channel_id); } else { CNmMemberId * pMemberId = GetMemberId(dwUserId); if (NULL != pMemberId) { UINT cCount = pMemberId->GetCheckIdCount(); if (0 == cCount) { TRACE_OUT(("CT120Channel: No more ChannelId requests %08X", dwUserId)); } else { cCount--; TRACE_OUT(("CT120Channel: Request Count for %08X = %0d", dwUserId, cCount)); pMemberId->SetCheckIdCount(cCount);
// BUGBUG: T.120 should notify us when this information is available
RequestChannelId(dwUserId); } } } }
VOID CNmChannelData::OnEntryConfirmLocal(GCCAppSapMsg * pMsg) { TRACE_OUT(("GCC_RETRIEVE_ENTRY_CONFIRM: public channelId = %04X result=%s", pMsg->RegistryConfirm.pRegItem->channel_id, GetGccResultString(pMsg->RegistryConfirm.nResult)));
// Processing initial request for guid channel information
ASSERT(sizeof(m_gcc_registry_item) == sizeof(*(pMsg->RegistryConfirm.pRegItem))); CopyMemory(&m_gcc_registry_item, pMsg->RegistryConfirm.pRegItem, sizeof(m_gcc_registry_item)); if (GCC_RESULT_SUCCESSFUL == pMsg->RegistryConfirm.nResult) {
m_mcs_channel_id = m_gcc_registry_item.channel_id; ASSERT(SCS_REGRETRIEVE == m_scs); m_scs = SCS_REGRETRIEVE_EXISTS; UpdateScState(SCS_REGRETRIEVE_EXISTS, 0); } else if (GCC_RESULT_ENTRY_DOES_NOT_EXIST == pMsg->RegistryConfirm.nResult) { TRACE_OUT((" channel does not exist - proceeding to new state")); ASSERT(0 == m_mcs_channel_id); ASSERT(SCS_REGRETRIEVE == m_scs); m_scs = SCS_REGRETRIEVE_NEW; UpdateScState(SCS_REGRETRIEVE_NEW, 0); } }
// deal with a GCC_APP_ROSTER_REPORT_INDICATION
BOOL CNmChannelData::UpdateRoster(GCCAppSapMsg * pMsg) { UINT iRoster; GCCApplicationRoster * lpAppRoster; int iRecord; GCCApplicationRecord * lpAppRecord; DWORD dwUserId; UCID rgPeerTemp[MAX_NM_PEER]; int cPeer; int i; BOOL fAdd = FALSE; BOOL fRemove = FALSE; BOOL fLocal = FALSE;
TRACE_OUT(("CT120Channel::UpdateRoster: conf=%d, roster count=%d", pMsg->AppRosterReportInd.nConfID, pMsg->AppRosterReportInd.cRosters));
ZeroMemory(rgPeerTemp, sizeof(rgPeerTemp));
/* Create rgPeerTemp[], cPeer */ cPeer = 0; for (iRoster = 0; iRoster < pMsg->AppRosterReportInd.cRosters; iRoster++) { lpAppRoster = pMsg->AppRosterReportInd.apAppRosters[iRoster]; if (lpAppRoster->session_key.session_id != m_gcc_session_key.session_id) continue; // Must pay attention to these flags to avoid GCC weirdness
if (lpAppRoster->nodes_were_added) fAdd = TRUE; if (lpAppRoster->nodes_were_removed) fRemove = TRUE;
for (iRecord = 0; iRecord < lpAppRoster->number_of_records; iRecord++) { lpAppRecord = lpAppRoster->application_record_list[iRecord]; TRACE_OUT(("Node=%X, Entity=%X, AppId=%X", lpAppRecord->node_id, lpAppRecord->entity_id, lpAppRecord->application_user_id));
// Search for the node in the list
dwUserId = lpAppRecord->node_id; //
// Check for local node
//
fLocal |= (dwUserId == m_dwUserIdLocal); for (i = 0; i < cPeer; i++) { if (dwUserId == rgPeerTemp[i].dwUserId) break; } if (i >= cPeer) { if (cPeer >= MAX_NM_PEER) continue; // over our limit!
// Add the node to our new list
rgPeerTemp[cPeer++].dwUserId = dwUserId; }
// Make sure we know the sender_id's
if (MCS_DYNAMIC_PRIVATE_CHANNEL == lpAppRecord->startup_channel_type) { rgPeerTemp[i].sender_id_private = lpAppRecord->application_user_id; } else { rgPeerTemp[i].sender_id_public = lpAppRecord->application_user_id; } }
break; // out of for (iRoster) loop
}
UpdateRoster(rgPeerTemp, cPeer, fAdd, fRemove);
return (fAdd && fLocal); }
/* H R S E N D D A T A */ /*----------------------------------------------------------------------------
%%Function: HrSendData
Send data on a specific channel ----------------------------------------------------------------------------*/ HRESULT CNmChannelData::HrSendData(ChannelID channel_id, DWORD dwUserId, LPVOID lpv, DWORD cb, ULONG dwFlags) { TRACE_OUT(("CT120Channel::HrSendData: %d bytes", cb));
PDUPriority priority; SendDataFlags allocation = APP_ALLOCATION; DataRequestType requestType;
if(dwFlags & DATA_TOP_PRIORITY) { priority = TOP_PRIORITY; } else if (dwFlags & DATA_HIGH_PRIORITY) { priority = HIGH_PRIORITY; } else if (dwFlags & DATA_MEDIUM_PRIORITY) { priority = MEDIUM_PRIORITY; } else { priority = LOW_PRIORITY; }
if (dwFlags & DATA_UNIFORM_SEND) { requestType = UNIFORM_SEND_DATA; } else { requestType = NORMAL_SEND_DATA; }
if ((0 == m_mcs_channel_id) || (NULL == m_pmcs_sap) || (0 == channel_id)) { WARNING_OUT(("*** Attempted to send data on invalid channel")); return E_INVALIDARG; }
MCSError mcsError = m_pmcs_sap->SendData(requestType, channel_id, priority, (unsigned char *)lpv, cb, allocation);
if (0 != mcsError) { TRACE_OUT(("SendData err=%s", GetMcsErrorString(mcsError))); // Usually MCS_TRANSMIT_BUFFER_FULL
return E_OUTOFMEMORY; }
{ // Inform the app the data has been sent
NMN_DATA_XFER nmnData; nmnData.pMember = NULL; nmnData.pb = (LPBYTE) lpv; nmnData.cb = cb; nmnData.dwFlags = 0;
if (0 == dwUserId) { // send out notification with NULL member (BROADCAST)
NotifySink(&nmnData, OnNmDataSent); } else { nmnData.pMember = (INmMember *) PMemberFromDwUserId(dwUserId, GetMemberList()); if (nmnData.pMember) { NotifySink(&nmnData, OnNmDataSent); nmnData.pMember->Release(); } } }
TRACE_OUT(("SendData completed successfully")); return S_OK; }
// Ask GCC for the private channel id.
VOID CNmChannelData::RequestChannelId(DWORD dwUserId) { BYTE keyChannel[cbKeyApp]; GCCRegistryKey registry_key;
TRACE_OUT(("Requesting channel id for %08X", dwUserId));
CopyStruct(®istry_key.session_key, &m_gcc_session_key); CreateAppKey(keyChannel, m_pGuid, dwUserId); SetAppKey(®istry_key.resource_id, keyChannel);
GCCError gccError = m_gcc_pIAppSap->RegistryRetrieveEntry( m_gcc_conference_id, ®istry_key); // This generates an async GCC_RETRIEVE_ENTRY_CONFIRM
if (0 != gccError) { WARNING_OUT(("RequestChannelId - problem with GCCRegistryRectreiveEntryRequest")); } }
VOID CNmChannelData::NotifyChannelConnected(void) { DBGENTRY(CNmChannelData::NotifyChannelConnected); if (S_OK != IsActive()) { CConfObject * pConference = PConference(); if (NULL != pConference) { m_fActive = TRUE;
TRACE_OUT(("The channel is now officially active")); } else { WARNING_OUT(("PConference is NULL!"));
} } DBGEXIT(CNmChannelData::NotifyChannelConnected); }
/* N M G C C M S G H A N D L E R */ /*-------------------------------------------------------------------------
%%Function: NmGccMsgHandler
-------------------------------------------------------------------------*/ void CALLBACK NmGccMsgHandler(GCCAppSapMsg * pMsg) { TRACE_OUT(("NmGccMsgHandler: [%d]", pMsg->eMsgType));
CNmChannelData * psc = (CNmChannelData *) (pMsg->pAppData); ASSERT(NULL != psc); psc->AddRef();
switch (pMsg->eMsgType) { case GCC_PERMIT_TO_ENROLL_INDICATION: TRACE_OUT((" m_conference_id = %X", pMsg->AppPermissionToEnrollInd.nConfID)); TRACE_OUT((" permission = %X", pMsg->AppPermissionToEnrollInd.fPermissionGranted)); if ((SCS_CONNECTED == psc->m_scs) && (0 == pMsg->AppPermissionToEnrollInd.fPermissionGranted)) { psc->CloseConnection(); break; }
if (SCS_CREATESAP != psc->m_scs) { TRACE_OUT((" ignoring Enroll Indication")); break; } psc->m_gcc_conference_id = pMsg->AppPermissionToEnrollInd.nConfID; psc->UpdateScState(SCS_CREATESAP, !pMsg->AppPermissionToEnrollInd.fPermissionGranted); break;
case GCC_ENROLL_CONFIRM: TRACE_OUT((" result = %s", GetGccResultString(pMsg->AppEnrollConfirm.nResult)));
if (GCC_RESULT_SUCCESSFUL == pMsg->AppEnrollConfirm.nResult) { TRACE_OUT((" m_conference_id = %X", pMsg->AppEnrollConfirm.nConfID)); TRACE_OUT((" entity_id = %X", pMsg->AppEnrollConfirm.eidMyself)); TRACE_OUT((" node_id = %X", pMsg->AppEnrollConfirm.nidMyself)); psc->m_gcc_node_id = pMsg->AppEnrollConfirm.nidMyself; } break;
case GCC_APP_ROSTER_REPORT_INDICATION: if(psc->UpdateRoster(pMsg) && psc->m_scs == SCS_ENROLL) { psc->UpdateScState(SCS_ENROLL, GCC_RESULT_SUCCESSFUL); } break;
case GCC_REGISTER_CHANNEL_CONFIRM: TRACE_OUT(("GCC_REGISTER_CHANNEL_CONFIRM: channel id = %04X result = %s", pMsg->RegistryConfirm.pRegItem->channel_id, GetGccResultString(pMsg->RegistryConfirm.nResult))); if (GCC_RESULT_SUCCESSFUL == pMsg->RegistryConfirm.nResult) { if (psc->GetMcsChannelId() == pMsg->RegistryConfirm.pRegItem->channel_id) { ASSERT((0 == psc->m_gcc_registry_item.item_type) || (GCC_REGISTRY_NONE == psc->m_gcc_registry_item.item_type));
ASSERT(sizeof(psc->m_gcc_registry_item) == sizeof(*(pMsg->RegistryConfirm.pRegItem))); CopyMemory(&psc->m_gcc_registry_item, pMsg->RegistryConfirm.pRegItem, sizeof(psc->m_gcc_registry_item)); } else { ASSERT(psc->SenderChannelId() == pMsg->RegistryConfirm.pRegItem->channel_id); ASSERT(0 == psc->m_registry_item_Private.item_type);
ASSERT(sizeof(psc->m_registry_item_Private) == sizeof(*(pMsg->RegistryConfirm.pRegItem))); CopyMemory(&psc->m_registry_item_Private, pMsg->RegistryConfirm.pRegItem, sizeof(psc->m_registry_item_Private)); } } ASSERT((SCS_REGCHANNEL == psc->m_scs) || (SCS_REGPRIVATE == psc->m_scs)); psc->UpdateScState(psc->m_scs, pMsg->RegistryConfirm.nResult); break;
case GCC_RETRIEVE_ENTRY_CONFIRM: psc->ProcessEntryConfirm(pMsg); break;
case GCC_ALLOCATE_HANDLE_CONFIRM: psc->ProcessHandleConfirm(pMsg); break;
default: break; }
psc->Release(); }
/* N M M C S M S G H A N D L E R */ /*-------------------------------------------------------------------------
%%Function: NmMcsMsgHandler
-------------------------------------------------------------------------*/ void CALLBACK NmMcsMsgHandler(unsigned int uMsg, LPARAM lParam, PVOID pv) { CNmChannelData * psc = (CNmChannelData *) pv; ASSERT(NULL != psc); // TRACE_OUT(("[%s]", GetMcsMsgString(uMsg)));
psc->AddRef();
switch (uMsg) { case MCS_ATTACH_USER_CONFIRM: { TRACE_OUT(("MCS_ATTACH_USER_CONFIRM channelId=%04X result=%s", LOWORD(lParam), GetMcsResultString(HIWORD(lParam)))); if (RESULT_SUCCESSFUL == HIWORD(lParam)) { TRACE_OUT((" Local m_mcs_sender_id = %04X", LOWORD(lParam))); psc->m_mcs_sender_id = LOWORD(lParam); } psc->UpdateScState(SCS_ATTACH, (DWORD) HIWORD(lParam)); break; }
case MCS_CHANNEL_JOIN_CONFIRM: { TRACE_OUT(("MCS_CHANNEL_JOIN_CONFIRM channelId=%04X result=%s", LOWORD(lParam), GetMcsResultString(HIWORD(lParam)))); if (RESULT_SUCCESSFUL == HIWORD(lParam)) { if (psc->m_mcs_sender_id == LOWORD(lParam)) { ASSERT(SCS_JOIN_PRIVATE == psc->m_scs); } else { ASSERT((0 == psc->m_mcs_channel_id) || (psc->m_mcs_channel_id == LOWORD(lParam)));
psc->m_mcs_channel_id = LOWORD(lParam); } } ASSERT((SCS_JOIN_NEW == psc->m_scs) || (SCS_JOIN_OLD == psc->m_scs) || (SCS_JOIN_PRIVATE == psc->m_scs) || (SCS_CONNECTED == psc->m_scs)|| (SCS_JOIN_STATIC_CHANNEL == psc->m_scs));
psc->UpdateScState(psc->m_scs, (DWORD) HIWORD(lParam)); break; }
case MCS_UNIFORM_SEND_DATA_INDICATION: case MCS_SEND_DATA_INDICATION: // lParam == SendData *
{ SendData * pSendData = (SendData *) lParam; ASSERT(NULL != pSendData); CNmMember * pMember = psc->PMemberFromSenderId(pSendData->initiator);
if (NULL != pMember) { if (uMsg == MCS_UNIFORM_SEND_DATA_INDICATION) { //
// Skip UNIFORM notifications that came from us
//
ULONG memberID; pMember->GetID(&memberID);
if (memberID == psc->m_gcc_node_id) { // We sent this, skip it.
goto RelMember; } }
ASSERT (pSendData->segmentation == (SEGMENTATION_BEGIN | SEGMENTATION_END)); NMN_DATA_XFER nmnData; nmnData.pMember =(INmMember *) pMember; nmnData.pb = pSendData->user_data.value; nmnData.cb = pSendData->user_data.length; nmnData.dwFlags = (ULONG) (NM_DF_SEGMENT_BEGIN | NM_DF_SEGMENT_END) | ((psc->GetMcsChannelId() == pSendData->channel_id) ? NM_DF_BROADCAST : NM_DF_PRIVATE);
psc->NotifySink((PVOID) &nmnData, OnNmDataReceived);
RelMember: pMember->Release(); } break; } default: break; }
psc->Release(); }
//
// CNmMemberId
//
CNmMemberId::CNmMemberId(CNmMember *pMember, UCID * pucid) : m_channelId(pucid->channelId), m_sender_id_public(pucid->sender_id_public), m_sender_id_private(pucid->sender_id_private), m_cCheckId(0), m_pMember(pMember) { }
VOID CNmMemberId::UpdateRosterInfo(UCID * pucid) { if (0 == m_channelId) m_channelId = pucid->channelId; if (0 == m_sender_id_private) m_sender_id_private = pucid->sender_id_private; if (0 == m_sender_id_public) m_sender_id_public = pucid->sender_id_public; }
//
// CNmChannelData
//
CNmChannelData::CNmChannelData(CConfObject * pConference, REFGUID rguid) : CConnectionPointContainer(g_apiidCP, ARRAY_ELEMENTS(g_apiidCP)), m_pConference(pConference), m_fClosed(TRUE), m_fActive(FALSE), m_cMember(0), m_pListMemberId(NULL), m_pListMember(NULL), m_pGCCER(NULL) { m_guid = rguid; ASSERT(GUID_NULL != rguid);
m_dwUserIdLocal = pConference->GetDwUserIdLocal(); ASSERT(INVALID_GCCID != m_dwUserIdLocal);
TRACE_OUT(("Obj: %08X created CNmChannelData", this)); }
CNmChannelData::~CNmChannelData(void) { DBGENTRY(CNmChannelData::~CNmChannelData);
// This will keep us from being deleted again...
++m_ulcRef;
CloseConnection();
FreeMemberIdList(&m_pListMemberId); delete m_pListMember;
TRACE_OUT(("Obj: %08X destroyed CNmChannelData", this));
DBGEXIT(CNmChannelData::~CNmChannelData); }
/* A D D M E M B E R */ /*-------------------------------------------------------------------------
%%Function: AddMember
-------------------------------------------------------------------------*/ VOID CNmChannelData::AddMember(CNmMember * pMember) { TRACE_OUT(("CNmChannelData::AddMember [%ls] id=%08X", pMember->GetName(), pMember->GetGCCID()));
m_cMember++; pMember->AddRef(); AddNode(pMember, &m_pListMember); }
/* R E M O V E M E M B E R */ /*-------------------------------------------------------------------------
%%Function: RemoveMember
-------------------------------------------------------------------------*/ VOID CNmChannelData::RemoveMember(CNmMember * pMember) { TRACE_OUT(("CNmChannelData::RemoveMember [%ls] id=%08X", pMember->GetName(), pMember->GetGCCID()));
m_cMember--; ASSERT(m_cMember >= 0); RemoveNode(pMember, m_pListMember);
pMember->Release(); // Release AFTER notifying everyone
}
/* O P E N C O N N E C T I O N */ /*-------------------------------------------------------------------------
%%Function: OpenConnection
Open a T.120 data connection (init both public and private channels) -------------------------------------------------------------------------*/ HRESULT CNmChannelData::OpenConnection(void) { TRACE_OUT(("CNmChannelData::OpenConection()"));
if (!m_fClosed) return E_FAIL; // already open
m_fClosed = FALSE; // need to call CloseConnection after this
InitCT120Channel(m_dwUserIdLocal); return S_OK; }
/* C L O S E C O N N E C T I O N */ /*-------------------------------------------------------------------------
%%Function: CloseConnection
Close the data channel - this matches what is done in OpenConnection -------------------------------------------------------------------------*/ HRESULT CNmChannelData::CloseConnection(void) { DBGENTRY(CNmChannelData::CloseConnection);
HRESULT hr = S_OK;
if (!m_fClosed) { m_fClosed = TRUE;
// Close any open T.120 channels
CloseChannel();
if (0 != m_cMember) { // force roster update with no peers
TRACE_OUT(("CloseConnection: %d members left", m_cMember)); UpdateRoster(NULL, 0, FALSE, TRUE /* fRemove */); ASSERT(IsEmpty()); }
CConfObject * pConference = PConference(); if (NULL != pConference) { m_fActive = FALSE; } }
DBGEXIT_HR(CNmChannelData::CloseConnection, hr); return hr; }
/* U P D A T E P E E R */ /*-------------------------------------------------------------------------
%%Function: UpdatePeer
-------------------------------------------------------------------------*/ VOID CNmChannelData::UpdatePeer(CNmMember * pMember, UCID *pucid, BOOL fAdd) { #ifdef DEBUG
TRACE_OUT(("UpdatePeer (%08X) fAdd=%d fLocal=%d", pMember, fAdd, pMember->FLocal())); if (NULL != pucid) { TRACE_OUT((" channelId=(%04X) dwUserId=%08X", pucid->channelId, pucid->dwUserId)); } #endif /* DEBUG */
if (fAdd) { CNmMemberId *pMemberId = new CNmMemberId(pMember, pucid); if (NULL != pMemberId) { AddNode(pMemberId, &m_pListMemberId); AddMember(pMember); } } else { CNmMemberId *pMemberId = GetMemberId(pMember); if (NULL != pMemberId) { RemoveNode(pMemberId, m_pListMemberId); delete pMemberId; RemoveMember(pMember); } } }
/* U P D A T E R O S T E R */ /*-------------------------------------------------------------------------
%%Function: UpdateRoster
Update the local peer list based on the new roster data -------------------------------------------------------------------------*/ VOID CNmChannelData::UpdateRoster(UCID * rgPeer, int cPeer, BOOL fAdd, BOOL fRemove) { int iPeer; DWORD dwUserId; CNmMember * pMember; COBLIST * pList;
TRACE_OUT(("CNmChannelData::UpdateRoster: %d peers, fAdd=%d, fRemove=%d", cPeer, fAdd, fRemove));
if (NULL != m_pListMemberId) { for (POSITION pos = m_pListMemberId->GetHeadPosition(); NULL != pos; ) { BOOL fFound = FALSE; CNmMemberId *pMemberId = (CNmMemberId *) m_pListMemberId->GetNext(pos); ASSERT(NULL != pMemberId); pMember = pMemberId->GetMember(); ASSERT(NULL != pMember); dwUserId = pMember->GetGCCID();
if (0 != dwUserId) { for (iPeer = 0; iPeer < cPeer; iPeer++) { if (dwUserId == rgPeer[iPeer].dwUserId) { fFound = TRUE; // remove from the new list
// so that the peer will not be added below
rgPeer[iPeer].dwUserId = 0;
// no change, but make sure we know sender_ids
pMemberId->UpdateRosterInfo(&rgPeer[iPeer]);
// try to find channel id, if necessary
if ((0 == pMemberId->GetChannelId()) && (0 == pMemberId->GetCheckIdCount()) && !pMember->FLocal()) { pMemberId->SetCheckIdCount(MAX_CHECKID_COUNT); RequestChannelId(dwUserId); } break; } } }
if (!fFound && fRemove) { pMember->AddRef();
// Unable to find old peer in new list - delete it
UpdatePeer(pMember, NULL, FALSE /* fAdd */ );
pMember->Release(); } } }
if (!fAdd) return;
// Use the conference list to find member data
pList = PConference()->GetMemberList(); /* Add new peers */ for (iPeer = 0; iPeer < cPeer; iPeer++) { dwUserId = rgPeer[iPeer].dwUserId; if (0 == dwUserId) continue;
// PMemberFromDwUserId returns AddRef'd member
pMember = PMemberFromDwUserId(dwUserId, pList);
if (NULL == pMember) { WARNING_OUT(("UpdateRoster: Member not found! dwUserId=%08X", dwUserId)); } else { UpdatePeer(pMember, &rgPeer[iPeer], TRUE /* fAdd */); pMember->Release(); } } }
/* U P D A T E M E M B E R C H A N N E L I D */ /*-------------------------------------------------------------------------
%%Function: UpdateMemberChannelId
-------------------------------------------------------------------------*/ VOID CNmChannelData::UpdateMemberChannelId(DWORD dwUserId, ChannelID channelId) { // PMemberFromDwUserId returns AddRef'd member
CNmMember * pMember = PMemberFromDwUserId(dwUserId, PConference()->GetMemberList()); TRACE_OUT(("Member (%08X) private channelId=(%04X)", pMember, channelId)); if (NULL != pMember) { UCID ucid; ClearStruct(&ucid); ucid.channelId = channelId; UpdateRosterInfo(pMember, &ucid); pMember->Release(); } }
/* G E T M E M B E R I D */ /*-------------------------------------------------------------------------
%%Function: GetMemberId
-------------------------------------------------------------------------*/ CNmMemberId * CNmChannelData::GetMemberId(CNmMember *pMember) { if (NULL != m_pListMemberId) { POSITION pos = m_pListMemberId->GetHeadPosition(); while (NULL != pos) { CNmMemberId *pMemberId = (CNmMemberId *) m_pListMemberId->GetNext(pos); ASSERT(NULL != pMemberId); if (pMemberId->GetMember() == pMember) { return pMemberId; } } } return NULL; }
/* G E T M E M B E R I D */ /*-------------------------------------------------------------------------
%%Function: GetMemberId
-------------------------------------------------------------------------*/ CNmMemberId * CNmChannelData::GetMemberId(DWORD dwUserId) { if (NULL != m_pListMemberId) { POSITION pos = m_pListMemberId->GetHeadPosition(); while (NULL != pos) { CNmMemberId *pMemberId = (CNmMemberId *) m_pListMemberId->GetNext(pos); ASSERT(NULL != pMemberId); CNmMember *pMember = pMemberId->GetMember(); ASSERT(NULL != pMember); if (pMember->GetGCCID() == dwUserId) { return pMemberId; } } } return NULL; }
/* U P D A T E R O S T E R I N F O */ /*-------------------------------------------------------------------------
%%Function: UpdateRosterInfo
-------------------------------------------------------------------------*/ VOID CNmChannelData::UpdateRosterInfo(CNmMember *pMember, UCID * pucid) { CNmMemberId *pMemberId = GetMemberId(pMember); if (NULL != pMemberId) { pMemberId->UpdateRosterInfo(pucid); } }
/* G E T C H A N N E L I D */ /*-------------------------------------------------------------------------
%%Function: GetChannelId
-------------------------------------------------------------------------*/ ChannelID CNmChannelData::GetChannelId(CNmMember *pMember) { CNmMemberId *pMemberId = GetMemberId(pMember); if (NULL != pMemberId) { return pMemberId->GetChannelId(); } return 0; }
/* P M E M B E R F R O M S E N D E R I D */ /*-------------------------------------------------------------------------
%%Function: PMemberFromSenderId
-------------------------------------------------------------------------*/ CNmMember * CNmChannelData::PMemberFromSenderId(UserID id) { if (NULL != m_pListMemberId) { POSITION pos = m_pListMemberId->GetHeadPosition(); while (NULL != pos) { CNmMemberId * pMemberId = (CNmMemberId *) m_pListMemberId->GetNext(pos); ASSERT(NULL != pMemberId); if (pMemberId->FSenderId(id)) { CNmMember* pMember = pMemberId->GetMember(); ASSERT(NULL != pMember); pMember->AddRef(); return pMember; } } } return NULL; }
///////////////////////////
// CNmChannelData:IUknown
ULONG STDMETHODCALLTYPE CNmChannelData::AddRef(void) { TRACE_OUT(("CNmChannelData::AddRef this = 0x%X", this)); return RefCount::AddRef(); }
ULONG STDMETHODCALLTYPE CNmChannelData::Release(void) { TRACE_OUT(("CNmChannelData::Release this = 0x%X", this)); return RefCount::Release(); }
HRESULT STDMETHODCALLTYPE CNmChannelData::QueryInterface(REFIID riid, PVOID *ppv) { HRESULT hr = S_OK;
if ((riid == IID_IUnknown) || (riid == IID_INmChannelData)) { *ppv = (INmChannelData *)this; TRACE_OUT(("CNmChannel::QueryInterface(): Returning INmChannelData.")); } else if (riid == IID_IConnectionPointContainer) { *ppv = (IConnectionPointContainer *) this; TRACE_OUT(("CNmChannel::QueryInterface(): Returning IConnectionPointContainer.")); }
else { hr = E_NOINTERFACE; *ppv = NULL; TRACE_OUT(("CNmChannel::QueryInterface(): Called on unknown interface.")); }
if (S_OK == hr) { AddRef(); }
return hr; }
HRESULT STDMETHODCALLTYPE CNmChannelData::GetGuid(GUID *pGuid) { if (NULL == pGuid) return E_POINTER;
*pGuid = m_guid; return S_OK; }
HRESULT STDMETHODCALLTYPE CNmChannelData::SendData(INmMember *pMember, ULONG cb, LPBYTE pv, ULONG uOptions) { HRESULT hr;
if (!m_fActive) { // No active Channels, yet
return E_FAIL; }
if ((NULL == pv) || (0 == cb)) { return S_FALSE; } if (IsBadReadPtr(pv, cb)) { return E_POINTER; }
CNmMember * pDest = (CNmMember *) pMember; COBLIST * pList = GetMemberList(); if (NULL == pMember) { hr = HrSendData(GetMcsChannelId(), 0, pv, cb, uOptions); } else if ((NULL == pList) || (NULL == pList->Lookup(pDest)) ) { // Destination is not in list
hr = E_INVALIDARG; } else { ChannelID channel_id = GetChannelId(pDest); if (0 == channel_id) { WARNING_OUT(("Unable to find user destination channel?"));
CNmMemberId *pMemberId = GetMemberId(pDest); if (NULL == pMemberId) { hr = E_UNEXPECTED; } else { channel_id = pMemberId->SenderId(); hr = (0 == channel_id) ? E_FAIL : S_OK; } } if (SUCCEEDED(hr)) { hr = HrSendData(channel_id, pDest->GetGCCID(), pv, cb, uOptions); } }
return hr; }
HRESULT STDMETHODCALLTYPE CNmChannelData::RegistryAllocateHandle(ULONG numberOfHandlesRequested) { if (!m_fActive) { // No active Channels, yet
return E_FAIL; }
if(numberOfHandlesRequested == 0) { return E_INVALIDARG; }
//
// Request handles from gcc
//
GCCError gccError = m_gcc_pIAppSap->RegistryAllocateHandle(m_gcc_conference_id, numberOfHandlesRequested); if(gccError == GCC_NO_ERROR) { return S_OK; } else { return E_FAIL; } }
HRESULT STDMETHODCALLTYPE CNmChannelData::IsActive(void) { return m_fActive ? S_OK : S_FALSE; }
HRESULT STDMETHODCALLTYPE CNmChannelData::SetActive(BOOL fActive) { TRACE_OUT(("CNmChannelData::SetActive(%d)", fActive));
NM_CONFERENCE_STATE state; // Must be in a non-idle conference
CConfObject * pConference = PConference(); pConference->GetState(&state); if ((NULL == pConference) || state == NM_CONFERENCE_IDLE) return E_FAIL;
if (fActive) { if (S_OK == IsActive()) return S_OK; return OpenConnection(); } else { if (S_FALSE == IsActive()) return S_OK; return CloseConnection(); } }
HRESULT STDMETHODCALLTYPE CNmChannelData::GetConference(INmConference **ppConference) { return ::GetConference(ppConference); }
HRESULT STDMETHODCALLTYPE CNmChannelData::EnumMember(IEnumNmMember **ppEnum) { HRESULT hr = E_POINTER; if (NULL != ppEnum) { *ppEnum = new CEnumNmMember( GetMemberList(), m_cMember);
hr = (NULL != *ppEnum)? S_OK : E_OUTOFMEMORY; } return hr; }
HRESULT STDMETHODCALLTYPE CNmChannelData::GetMemberCount(ULONG *puCount) { HRESULT hr = E_POINTER;
if (NULL != puCount) { *puCount = m_cMember; hr = S_OK; } return hr; }
///////////////////////////////////////////////////////////////////////////
// Utility Functions
HRESULT OnNmDataSent(IUnknown *pChannelDataNotify, void *pv, REFIID riid) { NMN_DATA_XFER * pData = (NMN_DATA_XFER *) pv;
if (IID_INmChannelDataNotify.Data1 == riid.Data1) { ((INmChannelDataNotify*)pChannelDataNotify)->DataSent( pData->pMember, pData->cb, pData->pb); } return S_OK; }
HRESULT OnNmDataReceived(IUnknown *pChannelDataNotify, void *pv, REFIID riid) { NMN_DATA_XFER * pData = (NMN_DATA_XFER *) pv;
if (IID_INmChannelDataNotify.Data1 == riid.Data1) { ((INmChannelDataNotify*)pChannelDataNotify)->DataReceived( pData->pMember, pData->cb, pData->pb, pData->dwFlags); } return S_OK; }
HRESULT OnAllocateHandleConfirm(IUnknown *pChannelDataNotify, void *pv, REFIID riid) {
if(IID_INmChannelDataNotify.Data1 == riid.Data1) { GCCRegAllocateHandleConfirm *pConfirm = (GCCRegAllocateHandleConfirm *)pv;
((INmChannelDataNotify*)pChannelDataNotify)->AllocateHandleConfirm(pConfirm->nFirstHandle, pConfirm->cHandles); } return S_OK; }
///////////////////////////////////////////////////////////////////////////
// Utility Functions
/* F R E E M E M B E R ID L I S T */ /*-------------------------------------------------------------------------
%%Function: FreeMemberIdList
-------------------------------------------------------------------------*/ VOID FreeMemberIdList(COBLIST ** ppList) { DBGENTRY(FreeMemberIdList);
ASSERT(NULL != ppList); if (NULL != *ppList) { while (!(*ppList)->IsEmpty()) { CNmMemberId * pMemberId = (CNmMemberId *) (*ppList)->RemoveHead(); delete pMemberId; } delete *ppList; *ppList = NULL; } }
///////////////////////////////////////////////////////////////////////////
//
// GCC / MCS Errors
#ifdef DEBUG
LPCTSTR _FormatSzErr(LPTSTR psz, UINT uErr) { static char szErr[MAX_PATH]; wsprintf(szErr, "%s 0x%08X (%d)", psz, uErr, uErr); return szErr; }
#define STRING_CASE(val) case val: pcsz = #val; break
LPCTSTR GetGccErrorString(GCCError uErr) { LPCTSTR pcsz;
switch (uErr) { STRING_CASE(GCC_NO_ERROR); STRING_CASE(GCC_RESULT_ENTRY_DOES_NOT_EXIST); STRING_CASE(GCC_NOT_INITIALIZED); STRING_CASE(GCC_ALREADY_INITIALIZED); STRING_CASE(GCC_ALLOCATION_FAILURE); STRING_CASE(GCC_NO_SUCH_APPLICATION); STRING_CASE(GCC_INVALID_CONFERENCE);
default: pcsz = _FormatSzErr("GccError", uErr); break; }
return pcsz; }
LPCTSTR GetMcsErrorString(MCSError uErr) { LPCTSTR pcsz;
switch (uErr) { STRING_CASE(MCS_NO_ERROR); STRING_CASE(MCS_USER_NOT_ATTACHED); STRING_CASE(MCS_NO_SUCH_USER); STRING_CASE(MCS_TRANSMIT_BUFFER_FULL); STRING_CASE(MCS_NO_SUCH_CONNECTION);
default: pcsz = _FormatSzErr("McsError", uErr); break; }
return pcsz; }
LPCTSTR GetGccResultString(UINT uErr) { LPCTSTR pcsz;
switch (uErr) { STRING_CASE(GCC_RESULT_ENTRY_DOES_NOT_EXIST); default: pcsz = _FormatSzErr("GccResult", uErr); break; }
return pcsz; }
LPCTSTR GetMcsResultString(UINT uErr) { return _FormatSzErr("McsResult", uErr); } #endif /* DEBUG (T.120 Error routines) */
|