#ifndef __MSPADDR_H_
#define __MSPADDR_H_
typedef struct {
LIST_ENTRY Link;
MSP_EVENT_INFO MSPEventInfo;
} MSPEVENTITEM,*PMSPEVENTITEM;
MSPEVENTITEM *AllocateEventItem(SIZE_T nExtraBytes = 0);
WINBOOL FreeEventItem(MSPEVENTITEM *pEventItemToFree);
typedef HRESULT (*PFNCREATETERM)(CComPtr<IMoniker> pMoniker,MSP_HANDLE htAddress,ITTerminal **pTerm);
typedef struct {
DWORD dwMediaType;
const CLSID *clsidClassManager;
PFNCREATETERM pfnCreateTerm;
} STATIC_TERMINAL_TYPE;
class ATL_NO_VTABLE CPlugTerminalClassInfo : public IDispatchImpl<ITPluggableTerminalClassInfo,&IID_ITPluggableTerminalClassInfo,&LIBID_TAPI3Lib>,public CComObjectRootEx<CComMultiThreadModel>,public CMSPObjectSafetyImpl
{
public:
DECLARE_GET_CONTROLLING_UNKNOWN()
virtual HRESULT FinalConstruct(void);
BEGIN_COM_MAP(CPlugTerminalClassInfo)
COM_INTERFACE_ENTRY(ITPluggableTerminalClassInfo)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IObjectSafety)
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal,m_pFTM)
END_COM_MAP()
public:
CPlugTerminalClassInfo() : m_bstrName(NULL),m_bstrCompany(NULL),m_bstrVersion(NULL),m_bstrCLSID(NULL),m_bstrTerminalClass(NULL),m_lMediaType(1),m_Direction(TD_CAPTURE),m_pFTM(NULL)
{
}
~CPlugTerminalClassInfo() {
if(m_bstrName) {
SysFreeString(m_bstrName);
}
if(m_bstrCompany) {
SysFreeString(m_bstrCompany);
}
if(m_bstrVersion) {
SysFreeString(m_bstrVersion);
}
if(m_bstrCLSID) {
SysFreeString(m_bstrCLSID);
}
if(m_bstrTerminalClass) {
SysFreeString(m_bstrTerminalClass);
}
if(m_pFTM) {
m_pFTM->Release();
}
}
public:
STDMETHOD(get_Name)(BSTR *pName);
STDMETHOD(get_Company)(BSTR *pCompany);
STDMETHOD(get_Version)(BSTR *pVersion);
STDMETHOD(get_TerminalClass)(BSTR *pTerminalClass);
STDMETHOD(get_CLSID)(BSTR *pCLSID);
STDMETHOD(get_Direction)(TERMINAL_DIRECTION *pDirection);
STDMETHOD(get_MediaTypes)(__LONG32 *pMediaTypes);
private:
CMSPCritSection m_CritSect;
BSTR m_bstrName;
BSTR m_bstrCompany;
BSTR m_bstrVersion;
BSTR m_bstrTerminalClass;
BSTR m_bstrCLSID;
__LONG32 m_lMediaType;
TERMINAL_DIRECTION m_Direction;
IUnknown *m_pFTM;
private:
STDMETHOD(put_Name)(BSTR bstrName);
STDMETHOD(put_Company)(BSTR bstrCompany);
STDMETHOD(put_Version)(BSTR bstrVersion);
STDMETHOD(put_TerminalClass)(BSTR bstrTerminalClass);
STDMETHOD(put_CLSID)(BSTR bstrCLSID);
STDMETHOD(put_Direction)(TERMINAL_DIRECTION nDirection);
STDMETHOD(put_MediaTypes)(__LONG32 nMediaTypes);
friend class CMSPAddress;
};
class ATL_NO_VTABLE CPlugTerminalSuperclassInfo : public IDispatchImpl<ITPluggableTerminalSuperclassInfo,&IID_ITPluggableTerminalSuperclassInfo,&LIBID_TAPI3Lib>,public CComObjectRootEx<CComMultiThreadModel>,public CMSPObjectSafetyImpl
{
public:
DECLARE_GET_CONTROLLING_UNKNOWN()
virtual HRESULT FinalConstruct(void);
BEGIN_COM_MAP(CPlugTerminalSuperclassInfo)
COM_INTERFACE_ENTRY(ITPluggableTerminalSuperclassInfo)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IObjectSafety)
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal,m_pFTM)
END_COM_MAP()
public:
CPlugTerminalSuperclassInfo() : m_bstrCLSID(NULL),m_bstrName(NULL),m_pFTM(NULL) {
}
~CPlugTerminalSuperclassInfo() {
if(m_bstrName) {
SysFreeString(m_bstrName);
}
if(m_bstrCLSID) {
SysFreeString(m_bstrCLSID);
}
if(m_pFTM) {
m_pFTM->Release();
}
}
public:
STDMETHOD(get_Name)(BSTR *pName);
STDMETHOD(get_CLSID)(BSTR *pCLSID);
private:
CMSPCritSection m_CritSect;
BSTR m_bstrCLSID;
BSTR m_bstrName;
IUnknown *m_pFTM;
private:
STDMETHOD(put_Name)(BSTR bstrName);
STDMETHOD(put_CLSID)(BSTR bstrCLSID);
friend class CMSPAddress;
};
class ATL_NO_VTABLE CMSPAddress : public CComObjectRootEx<CComMultiThreadModelNoCS>,public ITMSPAddress,public IDispatchImpl<ITTerminalSupport2,&IID_ITTerminalSupport2,&LIBID_TAPI3Lib>
{
public:
BEGIN_COM_MAP(CMSPAddress)
COM_INTERFACE_ENTRY(ITMSPAddress)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ITTerminalSupport)
COM_INTERFACE_ENTRY(ITTerminalSupport2)
END_COM_MAP()
DECLARE_GET_CONTROLLING_UNKNOWN()
DECLARE_VQI()
CMSPAddress();
virtual ~CMSPAddress();
virtual ULONG MSPAddressAddRef(void) = 0;
virtual ULONG MSPAddressRelease(void) = 0;
STDMETHOD (Initialize) (MSP_HANDLE htEvent);
STDMETHOD (Shutdown) ();
STDMETHOD (CreateMSPCall) (MSP_HANDLE htCall,DWORD dwReserved,DWORD dwMediaType,IUnknown *pOuterUnknown,IUnknown **ppMSPCall) = 0;
STDMETHOD (ShutdownMSPCall) (IUnknown *pMSPCall) = 0;
STDMETHOD (ReceiveTSPData) (IUnknown *pMSPCall,LPBYTE pBuffer,DWORD dwBufferSize);
STDMETHOD (GetEvent) (DWORD *pdwSize,BYTE *pBuffer);
STDMETHOD (get_StaticTerminals) (VARIANT *pVariant);
STDMETHOD (EnumerateStaticTerminals) (IEnumTerminal **ppTerminalEnumerator);
STDMETHOD (get_DynamicTerminalClasses) (VARIANT *pVariant);
STDMETHOD (EnumerateDynamicTerminalClasses) (IEnumTerminalClass **ppTerminalClassEnumerator);
STDMETHOD (CreateTerminal) (BSTR pTerminalClass,__LONG32 lMediaType,TERMINAL_DIRECTION Direction,ITTerminal **ppTerminal);
STDMETHOD (GetDefaultStaticTerminal) (__LONG32 lMediaType,TERMINAL_DIRECTION Direction,ITTerminal **ppTerminal);
STDMETHOD (get_PluggableSuperclasses)(VARIANT *pVariant);
STDMETHOD (EnumeratePluggableSuperclasses)(IEnumPluggableSuperclassInfo **ppSuperclassEnumerator);
STDMETHOD (get_PluggableTerminalClasses)(BSTR bstrTerminalSuperclass,__LONG32 lMediaType,VARIANT *pVariant);
STDMETHOD (EnumeratePluggableTerminalClasses)(CLSID iidTerminalSuperclass,__LONG32 lMediaType,IEnumPluggableTerminalClassInfo **ppClassEnumerator);
protected:
virtual HRESULT GetStaticTerminals (DWORD *pdwNumTerminals,ITTerminal **ppTerminals);
virtual HRESULT GetDynamicTerminalClasses (DWORD *pdwNumClasses,IID *pTerminalClasses);
public:
virtual WINBOOL IsValidSetOfMediaTypes(DWORD dwMediaType,DWORD dwMask);
virtual HRESULT PostEvent(MSPEVENTITEM *EventItem);
virtual DWORD GetCallMediaTypes(void) = 0;
protected:
virtual HRESULT IsMonikerInTerminalList(IMoniker *pMoniker);
virtual HRESULT UpdateTerminalListForPnp(WINBOOL bDeviceArrival);
virtual HRESULT UpdateTerminalList(void);
virtual HRESULT ReceiveTSPAddressData(PBYTE pBuffer,DWORD dwSize);
public:
virtual HRESULT PnpNotifHandler(WINBOOL bDeviceArrival);
protected:
HANDLE m_htEvent;
LIST_ENTRY m_EventList;
CMSPCritSection m_EventDataLock;
ITTerminalManager *m_pITTerminalManager;
CMSPArray <ITTerminal *> m_Terminals;
WINBOOL m_fTerminalsUpToDate;
CMSPCritSection m_TerminalDataLock;
private:
static const STATIC_TERMINAL_TYPE m_saTerminalTypes[];
static const DWORD m_sdwTerminalTypesCount;
};
template <class T> HRESULT CreateMSPCallHelper(CMSPAddress *pCMSPAddress,MSP_HANDLE htCall,DWORD dwReserved,DWORD dwMediaType,IUnknown *pOuterUnknown,IUnknown **ppMSPCall,T **ppCMSPCall)
{
LOG((MSP_TRACE,"CreateMSPCallHelper - enter"));
HRESULT hr;
T *pMSPCall;
IUnknown *pUnknown = NULL;
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;
}
CComAggObject<T> *pCall;
pCall = new CComAggObject<T>(pOuterUnknown);
if(!pCall) {
LOG((MSP_ERROR,"CreateMSPCallHelper - could not create agg call instance - exit E_OUTOFMEMORY"));
return E_OUTOFMEMORY;
}
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;
}
pMSPCall = dynamic_cast<T *>(&(pCall->m_contained));
if(!pMSPCall) {
LOG((MSP_ERROR,"CreateMSPCallHelper - can not cast to agg object to class pointer - exit E_UNEXPECTED"));
pUnknown->Release();
return E_UNEXPECTED;
}
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 <class T> HRESULT ShutdownMSPCallHelper(IUnknown *pUnknown,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<T> *pCall = dynamic_cast<CComAggObject<T> *> (pUnknown);
if(!pCall) {
LOG((MSP_ERROR,"ShutdownMSPCallHelper - can't cast unknown to agg object pointer - exit E_UNEXPECTED"));
return E_UNEXPECTED;
}
pMSPCall = dynamic_cast<T *> (&(pCall->m_contained));
if(!pMSPCall) {
LOG((MSP_ERROR,"ShutdownMSPCallHelper - can't cast contained unknown to class pointer - exit E_UNEXPECTED"));
return E_UNEXPECTED;
}
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;
}
#endif