// File: icallin.cpp #include "precomp.h" #include #include "cncodes.h" // needed for CN_ #include "icall_in.h" #include "imanager.h" #include "util.h" extern HRESULT OnNotifyCallError(IUnknown *pCallNotify, PVOID pv, REFIID riid); static HRESULT OnNotifyCallAccepted(IUnknown *pCallNotify, PVOID pv, REFIID riid); // Internal code to indicate that there was no security data available in an incoming call. const int CALL_NO_SECURITY_DATA = -1; static const IID * g_apiidCP_Call[] = { {&IID_INmCallNotify}, {&IID_INmCallNotify2} }; CIncomingCall::CIncomingCall( COprahNCUI * pOprahNCUI, BOOL fInvite, CONF_HANDLE hConf, PCWSTR pcwszNodeName, PUSERDATAINFO pUserDataInfoEntries, UINT cUserDataEntries) : CConnectionPointContainer(g_apiidCP_Call, ARRAY_ELEMENTS(g_apiidCP_Call)), m_pOprahNCUI(pOprahNCUI), m_pConnection(NULL), m_fInvite(fInvite), m_hConf(hConf), m_bstrCaller(SysAllocString(pcwszNodeName)), m_State(NM_CALL_INIT), m_dwFlags(0) { DebugEntry(CIncomingCall::CIncomingCall[T120]); ProcessT120UserData(pUserDataInfoEntries, cUserDataEntries); DebugExitVOID(CIncomingCall::CIncomingCall); } CIncomingCall::CIncomingCall(COprahNCUI *pOprahNCUI, IH323Endpoint* pConnection, P_APP_CALL_SETUP_DATA lpvMNMData, DWORD dwFlags) : CConnectionPointContainer(g_apiidCP_Call, ARRAY_ELEMENTS(g_apiidCP_Call)), m_pOprahNCUI(pOprahNCUI), m_pConnection(pConnection), m_fInvite(FALSE), m_hConf(NULL), m_bstrCaller(NULL), m_State(NM_CALL_INIT), m_guidNode(GUID_NULL), m_dwFlags(dwFlags), m_fMemberAdded(FALSE) { DebugEntry(CIncomingCall::CIncomingCall[H323]); HRESULT hr; ASSERT(m_pConnection); m_pConnection->AddRef(); WCHAR wszCaller[MAX_CALLER_NAME]; if (SUCCEEDED(m_pConnection->GetRemoteUserName(wszCaller, MAX_CALLER_NAME))) { m_bstrCaller = SysAllocString(wszCaller); } if ((NULL != lpvMNMData) && (lpvMNMData->dwDataSize > sizeof(DWORD))) { BYTE *pbData = ((BYTE*)lpvMNMData->lpData) + sizeof(DWORD); DWORD cbRemaining = lpvMNMData->dwDataSize - sizeof(DWORD); while ((sizeof(GUID) + sizeof(DWORD)) < cbRemaining) { DWORD cbData = *(DWORD*)(pbData + sizeof(GUID)); DWORD cbRecord = cbData + sizeof(GUID) + sizeof(DWORD); if (cbRemaining < cbRecord) { break; } if (*(GUID *)pbData == g_csguidNodeIdTag) { m_guidNode = *(GUID *)(pbData + sizeof(GUID) + sizeof(DWORD)); } m_UserData.AddUserData((GUID *)pbData, (unsigned short)cbData, pbData + sizeof(GUID) + sizeof(DWORD)); cbRemaining -= cbRecord; pbData += cbRecord; } } DebugExitVOID(CIncomingCall::CIncomingCall); } CIncomingCall::~CIncomingCall() { DebugEntry(CIncomingCall::~CIncomingCall); if(m_pConnection) { m_pConnection->Release(); m_pConnection = NULL; } SysFreeString(m_bstrCaller); DebugExitVOID(CIncomingCall::CIncomingCall); } VOID CIncomingCall::ProcessT120UserData( PUSERDATAINFO pUserDataInfoEntries, UINT cUserDataEntries) { if (cUserDataEntries > 0) { ASSERT(pUserDataInfoEntries); for (UINT u = 0; u < cUserDataEntries; u++) { m_UserData.AddUserData(pUserDataInfoEntries[u].pGUID, (unsigned short)pUserDataInfoEntries[u].cbData, pUserDataInfoEntries[u].pData); } } } BOOL CIncomingCall::MatchAcceptedCaller(PCWSTR pcwszNodeName) { // check to see if this caller matches someone whom we already accepted if ((NULL != m_pConnection) && (NM_CALL_ACCEPTED == m_State) && (GUID_NULL == m_guidNode) && (NULL != m_bstrCaller) && (0 == UnicodeCompare(m_bstrCaller, pcwszNodeName)) ) { return TRUE; } return FALSE; } BOOL CIncomingCall::MatchAcceptedCaller(GUID* pguidNodeId) { // check to see if this caller matches someone whom we already accepted if ((NULL != m_pConnection) && ((NM_CALL_INIT == m_State) || (NM_CALL_ACCEPTED == m_State)) && (GUID_NULL != m_guidNode) && (*pguidNodeId == m_guidNode)) { return TRUE; } return FALSE; } BOOL CIncomingCall::MatchActiveCaller(GUID* pguidNodeId) { // check to see if this caller matches someone whom we already accepted // or is in the process of calling us if ((NULL != m_pConnection) && ((NM_CALL_INIT == m_State) || (NM_CALL_RING == m_State) || (NM_CALL_ACCEPTED == m_State)) && (GUID_NULL != m_guidNode) && (*pguidNodeId == m_guidNode)) { return TRUE; } return FALSE; } void CIncomingCall::Ring() { m_State = NM_CALL_RING; NotifySink((PVOID) m_State, OnNotifyCallStateChanged); } HRESULT CIncomingCall::OnH323Connected() { CConfObject *pco = ::GetConfObject(); if (NULL != pco) { BOOL fAddMember = DidUserAccept(); pco->OnH323Connected(m_pConnection, m_dwFlags, fAddMember, m_guidNode); m_fMemberAdded = fAddMember; } return S_OK; } HRESULT CIncomingCall::OnH323Disconnected() { if (NM_CALL_RING == m_State) { if (m_hConf) { CONF_HANDLE hConf = m_hConf; m_hConf = NULL; // if there is an invite or join pending, kill it if ( m_fInvite ) hConf->InviteResponse(FALSE); else hConf->JoinResponse(FALSE); } } if(m_pConnection) { m_pConnection->Release(); m_pConnection = NULL; } if ((NM_CALL_RING == m_State) || (NM_CALL_INIT == m_State)) { m_State = NM_CALL_CANCELED; NotifySink((PVOID) m_State, OnNotifyCallStateChanged); } return m_hConf ? S_FALSE : S_OK; } VOID CIncomingCall::OnIncomingT120Call( BOOL fInvite, PUSERDATAINFO pUserDataInfoEntries, UINT cUserDataEntries) { m_fInvite = fInvite; ProcessT120UserData(pUserDataInfoEntries, cUserDataEntries); } HRESULT CIncomingCall::OnT120ConferenceEnded() { m_hConf = NULL; if(!m_fMemberAdded && m_pConnection) { // we didn't hand off this connection to the member IH323Endpoint* pConnection = m_pConnection; m_pConnection = NULL; pConnection->Disconnect(); pConnection->Release(); } if (NM_CALL_RING == m_State) { m_State = NM_CALL_CANCELED; NotifySink((PVOID) m_State, OnNotifyCallStateChanged); } return m_pConnection ? S_FALSE : S_OK; } HRESULT CIncomingCall::Terminate(BOOL fReject) { HRESULT hr = E_FAIL; // need to make sure that we are still ringing if ((NM_CALL_ACCEPTED != m_State) && (NM_CALL_REJECTED != m_State) && (NM_CALL_CANCELED != m_State)) { m_State = fReject ? NM_CALL_REJECTED : NM_CALL_CANCELED; TRACE_OUT(("CIncomingCall: Call not accepted - responding")); if (NULL != m_hConf) { CONF_HANDLE hConf = m_hConf; m_hConf = NULL; if (m_fInvite) { hConf->InviteResponse(FALSE); } else { CConfObject *pco = ::GetConfObject(); if ((NULL != pco) && (pco->GetConfHandle() == hConf)) { hConf->JoinResponse(FALSE); } } } if (NULL != m_pConnection) { ConnectStateType state; hr = m_pConnection->GetState(&state); ASSERT(SUCCEEDED(hr)); if(CLS_Alerting == state) { IH323Endpoint* pConn = m_pConnection; m_pConnection = NULL; pConn->AcceptRejectConnection(CRR_REJECT); pConn->Release(); m_pOprahNCUI->ReleaseAV(pConn); } } NotifySink((PVOID) m_State, OnNotifyCallStateChanged); hr = S_OK; } return hr; } STDMETHODIMP_(ULONG) CIncomingCall::AddRef(void) { return RefCount::AddRef(); } STDMETHODIMP_(ULONG) CIncomingCall::Release(void) { return RefCount::Release(); } HRESULT STDMETHODCALLTYPE CIncomingCall::QueryInterface(REFIID riid, PVOID *ppv) { HRESULT hr = S_OK; if ((riid == IID_INmCall) || (riid == IID_IUnknown)) { *ppv = (INmCall *)this; ApiDebugMsg(("CIncomingCall::QueryInterface()")); } else if (riid == IID_IConnectionPointContainer) { *ppv = (IConnectionPointContainer *) this; ApiDebugMsg(("CIncomingCall::QueryInterface(): Returning IConnectionPointContainer.")); } else { hr = E_NOINTERFACE; *ppv = NULL; ApiDebugMsg(("CIncomingCall::QueryInterface(): Called on unknown interface.")); } if (S_OK == hr) { AddRef(); } return hr; } HRESULT CIncomingCall::IsIncoming(void) { return S_OK; } HRESULT CIncomingCall::GetState(NM_CALL_STATE *pState) { HRESULT hr = E_POINTER; if (NULL != pState) { *pState = m_State; hr = S_OK; } return hr; } HRESULT CIncomingCall::GetName(BSTR * pbstrName) { if (NULL == pbstrName) return E_POINTER; *pbstrName = SysAllocString(m_bstrCaller); return (*pbstrName ? S_OK : E_FAIL); } HRESULT CIncomingCall::GetAddr(BSTR * pbstrAddr, NM_ADDR_TYPE *puType) { // for now we just do the same thing as NM2.11 if ((NULL == pbstrAddr) || (NULL == puType)) return E_POINTER; *puType = NM_ADDR_UNKNOWN; *pbstrAddr = SysAllocString(L""); return (*pbstrAddr ? S_OK : E_FAIL); } HRESULT CIncomingCall::GetUserData(REFGUID rguid, BYTE **ppb, ULONG *pcb) { return m_UserData.GetUserData(rguid,ppb,pcb); } HRESULT CIncomingCall::GetConference(INmConference **ppConference) { #ifdef NOTYET *ppConference = NULL; CConfObject *pco = ::GetConfObject(); if (NULL != pco) { if (pco->GetConfHandle() == m_hConf) { *ppConference = pco; return S_OK; } return E_UNEXPECTED; } #endif return S_FALSE; } HRESULT CIncomingCall::Accept(void) { HRESULT hr = E_FAIL; // need to make sure that we are still ringing if (NM_CALL_RING == m_State) { m_pOprahNCUI->OnIncomingCallAccepted(); CConfObject *pco = ::GetConfObject(); ASSERT(pco); if ((NULL != m_hConf) && ( NULL != pco ) && (pco->GetConfHandle() == m_hConf)) { if (m_fInvite) { hr = m_hConf->InviteResponse(TRUE); } else if (pco->GetConfHandle() == m_hConf) { hr = m_hConf->JoinResponse(TRUE); } } else if (NULL != m_pConnection) { ConnectStateType state; HRESULT hrTemp = m_pConnection->GetState(&state); ASSERT(SUCCEEDED(hrTemp)); if(CLS_Alerting == state) { hr = m_pConnection->AcceptRejectConnection(CRR_ACCEPT); } } if (S_OK == hr) { // notify all call observers that the call was accepted m_State = NM_CALL_ACCEPTED; NotifySink((INmConference *) pco, OnNotifyCallAccepted); } else { // call went away before it was accepted m_State = NM_CALL_CANCELED; NotifySink((PVOID)CN_RC_CONFERENCE_ENDED_BEFORE_ACCEPTED, OnNotifyCallError); if(m_pOprahNCUI) { m_pOprahNCUI->OnH323Disconnected(m_pConnection); } } // notify all call observers of the state change NotifySink((PVOID) m_State, OnNotifyCallStateChanged); } else { hr = ((NM_CALL_ACCEPTED == m_State) ? S_OK : E_FAIL); } return hr; } HRESULT CIncomingCall::Reject(void) { return Terminate(TRUE); } HRESULT CIncomingCall::Cancel(void) { return Terminate(FALSE); } /* O N N O T I F Y C A L L A C C E P T E D */ /*------------------------------------------------------------------------- %%Function: OnNotifyCallAccepted -------------------------------------------------------------------------*/ HRESULT OnNotifyCallAccepted(IUnknown *pCallNotify, PVOID pv, REFIID riid) { ASSERT(NULL != pCallNotify); ((INmCallNotify*)pCallNotify)->Accepted((INmConference *) pv); return S_OK; } CIncomingCallManager::CIncomingCallManager() { } CIncomingCallManager::~CIncomingCallManager() { // Empty the call list: while (!m_CallList.IsEmpty()) { CIncomingCall* pCall = (CIncomingCall*) m_CallList.RemoveHead(); // Shouldn't have any NULL entries: ASSERT(pCall); pCall->Release(); } } CREQ_RESPONSETYPE CIncomingCallManager::OnIncomingH323Call( COprahNCUI *pManager, IH323Endpoint* pConnection, P_APP_CALL_SETUP_DATA lpvMNMData) { CREQ_RESPONSETYPE resp; /////////////////////////////////////////////////// // first we determine the capabilities the caller /////////////////////////////////////////////////// BOOL fRequestAutoAccept = FALSE; // don't assume anything about security BOOL fT120SecureCall = FALSE; BOOL fT120NonSecureCall = FALSE; // assume that the caller can do an invite or a join BOOL fT120Invite = TRUE; BOOL fT120Join = TRUE; // assume that the caller wants a/v BOOL fRequestAV = TRUE; // assume that the caller is not NM2.X BOOL fCallerNM2x = FALSE; PCC_VENDORINFO pLocalVendorInfo; PCC_VENDORINFO pRemoteVendorInfo; if (S_OK == pConnection->GetVersionInfo(&pLocalVendorInfo, &pRemoteVendorInfo)) { H323VERSION version = GetH323Version(pRemoteVendorInfo); switch (version) { case H323_NetMeeting20: case H323_NetMeeting21: case H323_NetMeeting211: fCallerNM2x = TRUE; break; default: break; } } if ((NULL != lpvMNMData) && (lpvMNMData->dwDataSize >= sizeof(DWORD))) { DWORD dwUserData = *((LPDWORD)lpvMNMData->lpData); if (fCallerNM2x) { fRequestAutoAccept = (H323UDF_ALREADY_IN_T120_CALL == dwUserData); fT120SecureCall = FALSE; fT120NonSecureCall = TRUE; fT120Invite = TRUE; fT120Join = TRUE; fRequestAV = TRUE; } else if (0 != dwUserData) { fT120SecureCall = (H323UDF_SECURE & dwUserData); fT120NonSecureCall = !fT120SecureCall; fT120Invite = (H323UDF_INVITE & dwUserData); fT120Join = (H323UDF_JOIN & dwUserData); fRequestAV = ((H323UDF_AUDIO | H323UDF_VIDEO) & dwUserData); } } //////////////////////////////////////////////// // next we determine the state of us the callee //////////////////////////////////////////////// DWORD dwFlags = CRPCF_DATA; BOOL fAcceptSecure = TRUE; BOOL fAcceptNonSecure = TRUE; CConfObject *pco = ::GetConfObject(); if( NULL == pco ) { ERROR_OUT(( "CConfObject not found" )); resp = CRR_REJECT; goto REJECT_CALL; } BOOL fInActiveConference = pco->IsConferenceActive(); if (fInActiveConference) { // // If we've reached our limit of attendees, reject it. Also reject // it if incoming calls are prevented by settings. // if (pco->GetNumMembers() >= pco->GetConfMaxParticipants()) { ASSERT(pco->GetNumMembers() == pco->GetConfMaxParticipants()); WARNING_OUT(("Rejecting incoming H.323 call, reached limit setting of %d", pco->GetConfMaxParticipants())); resp = CRR_REJECT; goto REJECT_CALL; } if ((pco->IsHosting() != S_OK) && !(pco->GetConfAttendeePermissions() & NM_PERMIT_INCOMINGCALLS)) { WARNING_OUT(("Rejecting incoming H.323 call, not permitted by meeting setting")); resp = CRR_REJECT; goto REJECT_CALL; } // // We're in a conference, the security settings are whatever those // of the conference are. The user prefs are just for establishing // the first call. // if (pco->IsConfObjSecure()) { fAcceptNonSecure = FALSE; } else { fAcceptSecure = FALSE; } } else { // we are not in a conference so use the prefered settings RegEntry reConf(POLICIES_KEY, HKEY_CURRENT_USER); switch (reConf.GetNumber(REGVAL_POL_SECURITY, DEFAULT_POL_SECURITY)) { case DISABLED_POL_SECURITY: fAcceptSecure = FALSE; break; case REQUIRED_POL_SECURITY: fAcceptNonSecure = FALSE; break; default: { RegEntry rePref(CONFERENCING_KEY, HKEY_CURRENT_USER); // Is incoming required to be secure by preference? if (rePref.GetNumber(REGVAL_SECURITY_INCOMING_REQUIRED, DEFAULT_SECURITY_INCOMING_REQUIRED)) { fAcceptNonSecure = FALSE; } break; } } } ////////////////////////////////////////// // now we weed out non acceptable callers ////////////////////////////////////////// if (fCallerNM2x && !fAcceptNonSecure) { // NetMeeting 2.X cannot speak security return CRR_REJECT; } if (fT120SecureCall || !fAcceptNonSecure) { // // If we insist on security, or the call is secure and we can // handle it, the result is secure. // dwFlags |= CRPCF_SECURE; } else if (fRequestAV && pManager->AcquireAV(pConnection)) { dwFlags |= CRPCF_VIDEO | CRPCF_AUDIO; } if (fCallerNM2x && (0 == ((CRPCF_VIDEO | CRPCF_AUDIO) & dwFlags))) { // a/v is not available // if leading with H323, caller will try again with T120 // else their done resp = CRR_BUSY; } else if (fRequestAutoAccept) { // Auto accept this call if it came from NetMeeting 2.X and the caller is telling // us that we are already in a T.120 call with them. This allows audio after data // calls to be accepted and also means that you aren't prompted when someone // switches a/v using the UI's "Send audio and video to..." if (fInActiveConference) { // we most likely have a matching call already but may not be able to find it CIncomingCall *pCall = new CIncomingCall(pManager, pConnection, lpvMNMData, dwFlags); // This transfers the implicit reference of pConnection to the // new CIncomingCall. It will Release(). if (NULL != pCall) { // add call to the list of incoming calls m_CallList.AddTail(pCall); resp = CRR_ACCEPT; } else { resp = CRR_REJECT; } } else { // we're not really in a T120 call like the caller said. reject this call! resp = CRR_REJECT; } } else if (!fT120Join && fInActiveConference) { // need to change this to CRR_IN_CONFERENCE resp = CRR_BUSY; TRACE_OUT(("Can only accept joins; in a conference")); } else if (fT120Join && !fT120Invite && !fInActiveConference) { resp = CRR_REJECT; TRACE_OUT(("Cannot accept H323 Join Request; not in a conference")); } else if (!fRequestAV && !fT120Join && !fT120Invite && !fInActiveConference) { resp = CRR_REJECT; TRACE_OUT(("No av/ or data; reject")); } else if (fT120SecureCall && !fAcceptSecure) { resp = CRR_SECURITY_DENIED; TRACE_OUT(("Can not accept secure H323 Call")); } else if (fT120NonSecureCall && !fAcceptNonSecure) { resp = CRR_SECURITY_DENIED; TRACE_OUT(("Can not accept non secure H323 Call")); } else { CIncomingCall *pCall = new CIncomingCall(pManager, pConnection, lpvMNMData, dwFlags); // This transfers the implicit reference of pConnection to the // new CIncomingCall. It will Release(). if (NULL != pCall) { if (g_guidLocalNodeId != *pCall->GetNodeGuid()) { // Check for multiple calls from the same caller if (!MatchActiveCaller(pCall->GetNodeGuid())) { // add call to the list of incoming calls m_CallList.AddTail(pCall); pManager->OnIncomingCallCreated(pCall); // Don't ring on data only calls. // Wait for T120 call to come in. if (pCall->IsDataOnly()) { resp = CRR_ACCEPT; } else { pCall->Ring(); resp = CRR_ASYNC; } } else { // we're already in call with this person delete pCall; resp = CRR_REJECT; } } else { // we somehow called ourself delete pCall; resp = CRR_REJECT; } } else { resp = CRR_REJECT; } } REJECT_CALL: if ((resp != CRR_ACCEPT) && (resp != CRR_ASYNC)) { // make sure we are not holding on to AV pManager->ReleaseAV(pConnection); } return resp; } VOID CIncomingCallManager::OnH323Connected(IH323Endpoint* lpConnection) { POSITION pos = m_CallList.GetHeadPosition(); POSITION posItem; while (posItem = pos) { CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos); if ((NULL != pCall) && (lpConnection == pCall->GetH323Connection())) { pCall->OnH323Connected(); break; } } } VOID CIncomingCallManager::OnH323Disconnected(IH323Endpoint * lpConnection) { POSITION pos = m_CallList.GetHeadPosition(); POSITION posItem; while (posItem = pos) { CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos); if ((NULL != pCall) && (lpConnection == pCall->GetH323Connection())) { if (S_OK == pCall->OnH323Disconnected()) { m_CallList.RemoveAt(posItem); pCall->Release(); } break; } } } VOID CIncomingCallManager::OnT120ConferenceEnded(CONF_HANDLE hConference) { POSITION pos = m_CallList.GetHeadPosition(); POSITION posItem; while (posItem = pos) { CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos); if ((NULL != pCall) && (hConference == pCall->GetConfHandle())) { if (S_OK == pCall->OnT120ConferenceEnded()) { m_CallList.RemoveAt(posItem); pCall->Release(); } } } } HRESULT CIncomingCallManager::OnIncomingT120Call( COprahNCUI *pManager, BOOL fInvite, CONF_HANDLE hConf, PCWSTR pcwszNodeName, PUSERDATAINFO pUserDataInfoEntries, UINT cUserDataEntries, BOOL fSecure) { HRESULT hr = S_OK; // need to scan through all accepted calls passing the T120 params // if someone returns S_OK, we accept the call CIncomingCall *pMatchedCall = NULL; GUID* pguidNodeID = GetGuidFromT120UserData(pUserDataInfoEntries, cUserDataEntries); if (pguidNodeID) { pMatchedCall = MatchAcceptedCaller(pguidNodeID); } else { pMatchedCall = MatchAcceptedCaller(pcwszNodeName); } if (pMatchedCall) { pMatchedCall->SetConfHandle(hConf); // we should always ring the client when the call is secure // or when we haven't rang already if (!pMatchedCall->DidUserAccept()) { pMatchedCall->OnIncomingT120Call(fInvite, pUserDataInfoEntries, cUserDataEntries); pMatchedCall->Ring(); } else { if (fInvite) { hr = hConf->InviteResponse(TRUE); } else { hr = hConf->JoinResponse(TRUE); } } pMatchedCall->Release(); } else { CIncomingCall *pCall = new CIncomingCall(pManager, fInvite, hConf, pcwszNodeName, pUserDataInfoEntries, cUserDataEntries); if (NULL != pCall) { // currently we don't add T120 calls to the call list pManager->OnIncomingCallCreated(pCall); pCall->Ring(); // we're not holding on to the call so release it pCall->Release(); } else { // unable to accept call if (fInvite) { hr = hConf->InviteResponse(FALSE); } else { hConf->JoinResponse(FALSE); } hr = E_OUTOFMEMORY; } } return hr; } CIncomingCall* CIncomingCallManager::MatchAcceptedCaller(PCWSTR pcwszNodeName) { // we won't auto accept anyone who is already in the roster CNmMember* pMember = PDataMemberFromName(pcwszNodeName); if (NULL != pMember) { return FALSE; } POSITION pos = m_CallList.GetHeadPosition(); while (pos) { CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos); if ((NULL != pCall) && pCall->MatchAcceptedCaller(pcwszNodeName)) { TRACE_OUT(("Matched accepted caller")); pCall->AddRef(); return pCall; } } return NULL; } CIncomingCall* CIncomingCallManager::MatchAcceptedCaller(GUID* pguidNodeId) { if (GUID_NULL == *pguidNodeId) { return FALSE; } // we wont auto accept anyone who is already in the roster CNmMember* pMember = PMemberFromNodeGuid(*pguidNodeId); if ((NULL != pMember) && pMember->FHasData()) { return FALSE; } POSITION pos = m_CallList.GetHeadPosition(); while (pos) { CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos); if ((NULL != pCall) && pCall->MatchAcceptedCaller(pguidNodeId)) { TRACE_OUT(("Matched accepted caller")); pCall->AddRef(); return pCall; } } return NULL; } CIncomingCall* CIncomingCallManager::MatchActiveCaller(GUID* pguidNodeId) { if (GUID_NULL == *pguidNodeId) { return FALSE; } POSITION pos = m_CallList.GetHeadPosition(); while (pos) { CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos); if ((NULL != pCall) && pCall->MatchActiveCaller(pguidNodeId)) { TRACE_OUT(("Matched active caller")); pCall->AddRef(); return pCall; } } return NULL; } GUID* CIncomingCallManager::GetGuidFromT120UserData( PUSERDATAINFO pUserDataInfoEntries, UINT cUserDataEntries) { if (cUserDataEntries > 0) { ASSERT(pUserDataInfoEntries); for (UINT u = 0; u < cUserDataEntries; u++) { if ((*pUserDataInfoEntries[u].pGUID == g_csguidNodeIdTag) && (pUserDataInfoEntries[u].cbData == sizeof(GUID))) { return (GUID*)pUserDataInfoEntries[u].pData; } } } return NULL; } VOID CIncomingCallManager::CancelCalls() { DebugEntry(CIncomingCallManager::CancelCalls); POSITION pos = m_CallList.GetHeadPosition(); POSITION posItem; while (posItem = pos) { CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos); if (NULL != pCall) { if (SUCCEEDED(pCall->Terminate(FALSE))) { m_CallList.RemoveAt(posItem); pCall->Release(); } } } DebugExitVOID(CIncomingCallManager::CancelCalls); }