// SrvcCall.cpp // Code to implement the INmCallNotify interface for the remote control service #include "precomp.h" #include "srvcutil.h" #include "srvccall.h" CSrvcCall::CSrvcCall(INmCall * pNmCall) : m_pCall (pNmCall), m_pszName (NULL), m_pszAddr (NULL), m_addrType (NM_ADDR_UNKNOWN), m_fSelectedConference (FALSE), m_pos (NULL), m_cRef (1), m_dwCookie (0) { HRESULT hr; TRACE_OUT(("CSrvcCall: Created %08X (INmCall=%08X)", this, pNmCall)); ASSERT(NULL != m_pCall); m_pCall->AddRef(); // Get the display name BSTR bstr; hr = m_pCall->GetName(&bstr); if (SUCCEEDED(hr)) { hr = BSTR_to_LPTSTR(&m_pszName, bstr); SysFreeString(bstr); } if (FEmptySz(m_pszName)) { // Default to "another person" if no name available in the call data m_pszName = TEXT("Somebody"); } hr = m_pCall->GetAddr(&bstr, &m_addrType); if (SUCCEEDED(hr)) { hr = BSTR_to_LPTSTR(&m_pszAddr, bstr); SysFreeString(bstr); } // These should never change m_fIncoming = (m_pCall->IsIncoming() == S_OK); m_dwTick = ::GetTickCount(); Update(); NmAdvise(m_pCall, this, IID_INmCallNotify, &m_dwCookie); } VOID CSrvcCall::RemoveCall(void) { NmUnadvise(m_pCall, IID_INmCallNotify, m_dwCookie); } CSrvcCall::~CSrvcCall() { delete m_pszName; delete m_pszAddr; ASSERT(NULL != m_pCall); m_pCall->Release(); } // IUnknown methods STDMETHODIMP_(ULONG) CSrvcCall::AddRef(void) { return ++m_cRef; } STDMETHODIMP_(ULONG) CSrvcCall::Release(void) { ASSERT(m_cRef > 0); if (m_cRef > 0) { m_cRef--; } ULONG cRef = m_cRef; if (0 == cRef) { delete this; } return cRef; } STDMETHODIMP CSrvcCall::QueryInterface(REFIID riid, PVOID *ppv) { HRESULT hr = S_OK; if ((riid == IID_INmCallNotify) || (riid == IID_IUnknown)) { *ppv = (INmCallNotify *)this; // ApiDebugMsg(("CCall::QueryInterface()")); } else { hr = E_NOINTERFACE; *ppv = NULL; // ApiDebugMsg(("CCall::QueryInterface(): Called on unknown interface.")); } if (S_OK == hr) { AddRef(); } return hr; } // INmCallNotify methods STDMETHODIMP CSrvcCall::NmUI(CONFN uNotify) { return S_OK; } STDMETHODIMP CSrvcCall::StateChanged(NM_CALL_STATE uState) { // REVIEW: This check should be done outside of this routine if (uState == m_State) { // Don't bother the UI when nothing changes! return S_OK; } Update(); return S_OK; } STDMETHODIMP CSrvcCall::Failed(ULONG uError) { return S_OK; } STDMETHODIMP CSrvcCall::Accepted(INmConference *pConference) { return S_OK; } // INmCallNotify3 methods STDMETHODIMP CSrvcCall::CallError(UINT cns) { return S_OK; } STDMETHODIMP CSrvcCall::VersionConflict(HRESULT Status, BOOL *pfContinue) { return S_OK; } STDMETHODIMP CSrvcCall::RemoteConference(BOOL fMCU, BSTR *pwszConfNames, BSTR *pbstrConfToJoin) { return S_OK; } STDMETHODIMP CSrvcCall::RemotePassword(BSTR bstrConference, BSTR *pbstrPassword, BYTE *pb, DWORD cb, BOOL fIsService) { return S_OK; } /* U P D A T E */ /*------------------------------------------------------------------------- %%Function: Update Update the cached information about the call -------------------------------------------------------------------------*/ VOID CSrvcCall::Update(void) { m_pCall->GetState(&m_State); // TRACE_OUT(("CCall: New State=%0d for call=%08X", m_State, this)); switch (m_State) { case NM_CALL_ACCEPTED: case NM_CALL_REJECTED: case NM_CALL_CANCELED: RemoveCall(); Release(); break; case NM_CALL_RING: m_pCall->Accept(); break; default: ERROR_OUT(("CCall::Update: Unknown state %08X", m_State)); case NM_CALL_INVALID: case NM_CALL_INIT: case NM_CALL_SEARCH: case NM_CALL_WAIT: break; } }