/*++ Copyright (c) 1998-1999 Microsoft Corporation Module Name: MSPaddr.h Abstract: Declaration of the CMSPAddress --*/ #ifndef __MSPADDR_H_ #pragma option push -b -a8 -pc -A- /*P_O_Push*/ #define __MSPADDR_H_ typedef struct { LIST_ENTRY Link; // The link node. See ntrtl.h for detail. MSP_EVENT_INFO MSPEventInfo; // The event code. } MSPEVENTITEM, *PMSPEVENTITEM; typedef HRESULT (*PFNCREATETERM) ( IN CComPtr pMoniker, IN MSP_HANDLE htAddress, OUT ITTerminal **pTerm ); typedef struct { DWORD dwMediaType; const CLSID * clsidClassManager; PFNCREATETERM pfnCreateTerm; } STATIC_TERMINAL_TYPE; /*++ Class Description: Represents an MSP address. --*/ class ATL_NO_VTABLE CMSPAddress : public CComObjectRootEx, public ITMSPAddress, public IDispatchImpl { public: // No need for free thread marshaling, because the MSP address object is // always aggregated by the TAPI3 address object. BEGIN_COM_MAP( CMSPAddress ) COM_INTERFACE_ENTRY( ITMSPAddress ) COM_INTERFACE_ENTRY( IDispatch ) COM_INTERFACE_ENTRY( ITTerminalSupport ) END_COM_MAP() // The DERIVED class should DECLARE_AGGREGATABLE(className) DECLARE_GET_CONTROLLING_UNKNOWN() DECLARE_VQI() CMSPAddress(); virtual ~CMSPAddress(); virtual ULONG MSPAddressAddRef(void) = 0; virtual ULONG MSPAddressRelease(void) = 0; // ITMSPAddress methods, called by TAPI. STDMETHOD (Initialize) ( IN MSP_HANDLE htEvent ); STDMETHOD (Shutdown) (); STDMETHOD (CreateMSPCall) ( IN MSP_HANDLE htCall, IN DWORD dwReserved, IN DWORD dwMediaType, IN IUnknown * pOuterUnknown, OUT IUnknown ** ppMSPCall ) = 0; STDMETHOD (ShutdownMSPCall) ( IN IUnknown * pMSPCall ) = 0; STDMETHOD (ReceiveTSPData) ( IN IUnknown * pMSPCall, IN LPBYTE pBuffer, IN DWORD dwBufferSize ); STDMETHOD (GetEvent) ( IN OUT DWORD * pdwSize, OUT BYTE * pBuffer ); // ITTerminalSupport methods, called by TAPI and/or the app. STDMETHOD (get_StaticTerminals) ( OUT VARIANT * pVariant ); STDMETHOD (EnumerateStaticTerminals) ( OUT IEnumTerminal ** ppTerminalEnumerator ); STDMETHOD (get_DynamicTerminalClasses) ( OUT VARIANT * pVariant ); STDMETHOD (EnumerateDynamicTerminalClasses) ( OUT IEnumTerminalClass ** ppTerminalClassEnumerator ); STDMETHOD (CreateTerminal) ( IN BSTR pTerminalClass, IN long lMediaType, IN TERMINAL_DIRECTION Direction, OUT ITTerminal ** ppTerminal ); STDMETHOD (GetDefaultStaticTerminal) ( IN long lMediaType, IN TERMINAL_DIRECTION Direction, OUT ITTerminal ** ppTerminal ); protected: // ITTerminalSupport helper methods virtual HRESULT GetStaticTerminals ( IN OUT DWORD * pdwNumTerminals, OUT ITTerminal ** ppTerminals ); virtual HRESULT GetDynamicTerminalClasses ( IN OUT DWORD * pdwNumClasses, OUT IID * pTerminalClasses ); public: // methods used by the MSPCall object. // // Check to see if the mediatype is non-zero and is in the mask. // Your MSP can override this if it needs to do special checks on // specific combinations of media types (e.g., can never have more // than one media type on a call, can never have video without // audio, etc.) The default implementation accepts any nonempty // set of media types that is a subset of the set of all supported // media types (specified via the GetCallMediaTypes method). // virtual BOOL IsValidSetOfMediaTypes(DWORD dwMediaType, DWORD dwMask); // Note: the eventItem must be allocated by malloc or new // (when the event is processed, it is deleted). virtual HRESULT PostEvent( IN MSPEVENTITEM * EventItem ); // method used by template function virtual DWORD GetCallMediaTypes(void) = 0; protected: // Private helper function (protected so derived class can call it) virtual HRESULT UpdateTerminalList(void); virtual HRESULT ReceiveTSPAddressData( IN PBYTE pBuffer, IN DWORD dwSize ); protected: // The handle to TAPI's event, which is used to notify TAPI that the MSP // wants to send data to it. HANDLE m_htEvent; // List of events. LIST_ENTRY m_EventList; // The lock that protects the data related to event handling with TAPI. CMSPCritSection m_EventDataLock; // The pointer to the terminal manager object. ITTerminalManager * m_pITTerminalManager; // The list of static terminals that can be used on the address. CMSPArray m_Terminals; BOOL m_fTerminalsUpToDate; // The lock that protects the data members for terminal operations. CMSPCritSection m_TerminalDataLock; private: static const STATIC_TERMINAL_TYPE m_saTerminalTypes[]; static const DWORD m_sdwTerminalTypesCount; }; template HRESULT CreateMSPCallHelper( IN CMSPAddress * pCMSPAddress, IN MSP_HANDLE htCall, IN DWORD dwReserved, IN DWORD dwMediaType, IN IUnknown * pOuterUnknown, OUT IUnknown ** ppMSPCall, OUT T ** ppCMSPCall ) { LOG((MSP_TRACE, "CreateMSPCallHelper - enter")); HRESULT hr; T * pMSPCall; IUnknown *pUnknown = NULL; // // Check parameters. // if ( IsBadReadPtr(pCMSPAddress, sizeof(CMSPAddress) ) ) { LOG((MSP_ERROR, "CreateMSPCallHelper - " "bad address pointer - exit E_POINTER")); return E_POINTER; } if ( IsBadReadPtr(pOuterUnknown, sizeof(IUnknown) ) ) { LOG((MSP_ERROR, "CreateMSPCallHelper - " "bad outer unknown - we require aggregation - exit E_POINTER")); return E_POINTER; } if ( IsBadReadPtr(ppMSPCall, sizeof(IUnknown *) ) ) { LOG((MSP_ERROR, "CreateMSPCallHelper - " "bad iunknown return ptr - exit E_POINTER")); return E_POINTER; } if ( IsBadReadPtr(ppCMSPCall, sizeof(T *) ) ) { LOG((MSP_ERROR, "CreateMSPCallHelper - " "bad class return ptr - exit E_POINTER")); return E_POINTER; } if ( ! pCMSPAddress->IsValidSetOfMediaTypes( dwMediaType, pCMSPAddress->GetCallMediaTypes() ) ) { LOG((MSP_ERROR, "CreateMSPCallHelper - " "unsupported media types - exit TAPI_E_INVALIDMEDIATYPE")); return TAPI_E_INVALIDMEDIATYPE; } // dwReserved is meaningless. // We have no way of checking htCall. // the pOuterUnknown is not NULL. This object is going to be aggregated. CComAggObject * pCall; pCall = new CComAggObject(pOuterUnknown); if (pCall == NULL) { LOG((MSP_ERROR, "CreateMSPCallHelper - " "could not create agg call instance - exit E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // query the interface on the containing object. hr = pCall->QueryInterface(IID_IUnknown, (void **)&pUnknown); if (FAILED(hr)) { LOG((MSP_ERROR, "CreateMSPCallHelper - " "QueryInterface failed: %x", hr)); delete pCall; return hr; } hr = pCall->FinalConstruct(); if (FAILED(hr)) { LOG((MSP_ERROR, "CreateMSPCallHelper - " "FinalConstruct failed: %x.", hr)); pUnknown->Release(); return hr; } // Get a pointer to the real MSPCall object. pMSPCall = dynamic_cast(&(pCall->m_contained)); if (pMSPCall == NULL) { LOG((MSP_ERROR, "CreateMSPCallHelper - " "can not cast to agg object to class pointer - " "exit E_UNEXPECTED")); pUnknown->Release(); return E_UNEXPECTED; } // // initialize the call. // hr = pMSPCall->Init(pCMSPAddress, htCall, dwReserved, dwMediaType); if (FAILED(hr)) { LOG((MSP_ERROR, "CreateMSPCallHelper - " "call init failed: %x", hr)); pUnknown->Release(); return hr; } *ppMSPCall = pUnknown; *ppCMSPCall = pMSPCall; LOG((MSP_TRACE, "CreateMSPCallHelper - exit S_OK")); return hr; } template HRESULT ShutdownMSPCallHelper( IN IUnknown * pUnknown, OUT T ** ppCMSPCall ) { LOG((MSP_TRACE, "ShutdownMSPCallHelper - enter")); if ( IsBadReadPtr(pUnknown, sizeof(IUnknown) ) ) { LOG((MSP_ERROR, "ShutdownMSPCallHelper - " "bad IUnknown pointer - exit E_POINTER")); return E_POINTER; } if ( IsBadWritePtr(ppCMSPCall, sizeof(T *) ) ) { LOG((MSP_ERROR, "ShutdownMSPCallHelper - " "bad return pointer - exit E_POINTER")); return E_POINTER; } T * pMSPCall; CComAggObject * pCall = dynamic_cast *> (pUnknown); if (pCall == NULL) { LOG((MSP_ERROR, "ShutdownMSPCallHelper - " "can't cast unknown to agg object pointer - exit E_UNEXPECTED")); return E_UNEXPECTED; } // // It was aggregated. Get a pointer to the real MSPCall object. // pMSPCall = dynamic_cast (&(pCall->m_contained)); if (pMSPCall == NULL) { LOG((MSP_ERROR, "ShutdownMSPCallHelper - " "can't cast contained unknown to class pointer - " "exit E_UNEXPECTED")); return E_UNEXPECTED; } // // Now we have a call to shut down. Shut it down. // HRESULT hr = pMSPCall->ShutDown(); if (FAILED(hr)) { LOG((MSP_ERROR, "ShutdownMSPCallHelper - " "ShutDownMSPCall failed: %x", hr)); return hr; } *ppCMSPCall = pMSPCall; LOG((MSP_TRACE, "ShutdownMSPCallHelper - exit S_OK")); return S_OK; } #pragma option pop /*P_O_Pop*/ #endif //__MSPADDRESS_H_