Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

683 lines
16 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. MSPaddr.h
  5. Abstract:
  6. Declaration of the CMSPAddress
  7. --*/
  8. #ifndef __MSPADDR_H_
  9. #define __MSPADDR_H_
  10. typedef struct
  11. {
  12. LIST_ENTRY Link; // The link node. See ntrtl.h for detail.
  13. MSP_EVENT_INFO MSPEventInfo; // The event code.
  14. } MSPEVENTITEM, *PMSPEVENTITEM;
  15. //
  16. // these functions should be used to allocate and deallocate MSPEVENTITEM
  17. // structures. In case of failure, the caller can call GetLastError()
  18. // to get exact cause of the failure.
  19. //
  20. //
  21. // nExtraBytes specifies how many extra (in addition to sizeof(MSPEVENTITEM))
  22. // bytes to allocate.
  23. //
  24. MSPEVENTITEM *AllocateEventItem(SIZE_T nExtraBytes = 0);
  25. BOOL FreeEventItem(MSPEVENTITEM *pEventItemToFree);
  26. typedef HRESULT (*PFNCREATETERM) (
  27. IN CComPtr<IMoniker> pMoniker,
  28. IN MSP_HANDLE htAddress,
  29. OUT ITTerminal **pTerm
  30. );
  31. typedef struct
  32. {
  33. DWORD dwMediaType;
  34. const CLSID * clsidClassManager;
  35. PFNCREATETERM pfnCreateTerm;
  36. } STATIC_TERMINAL_TYPE;
  37. class ATL_NO_VTABLE CPlugTerminalClassInfo :
  38. public IDispatchImpl<ITPluggableTerminalClassInfo, &IID_ITPluggableTerminalClassInfo, &LIBID_TAPI3Lib>,
  39. public CComObjectRootEx<CComMultiThreadModel>,
  40. public CMSPObjectSafetyImpl
  41. {
  42. public:
  43. DECLARE_GET_CONTROLLING_UNKNOWN()
  44. virtual HRESULT FinalConstruct(void);
  45. BEGIN_COM_MAP(CPlugTerminalClassInfo)
  46. COM_INTERFACE_ENTRY(ITPluggableTerminalClassInfo)
  47. COM_INTERFACE_ENTRY(IDispatch)
  48. COM_INTERFACE_ENTRY(IObjectSafety)
  49. COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM)
  50. END_COM_MAP()
  51. public:
  52. CPlugTerminalClassInfo() :
  53. m_bstrName(NULL),
  54. m_bstrCompany(NULL),
  55. m_bstrVersion(NULL),
  56. m_bstrCLSID(NULL),
  57. m_bstrTerminalClass(NULL),
  58. m_lMediaType(1),
  59. m_Direction(TD_CAPTURE),
  60. m_pFTM(NULL)
  61. {
  62. }
  63. ~CPlugTerminalClassInfo()
  64. {
  65. if( m_bstrName )
  66. {
  67. SysFreeString( m_bstrName );
  68. }
  69. if( m_bstrCompany )
  70. {
  71. SysFreeString( m_bstrCompany );
  72. }
  73. if( m_bstrVersion )
  74. {
  75. SysFreeString( m_bstrVersion );
  76. }
  77. if( m_bstrCLSID )
  78. {
  79. SysFreeString( m_bstrCLSID );
  80. }
  81. if( m_bstrTerminalClass )
  82. {
  83. SysFreeString( m_bstrTerminalClass );
  84. }
  85. if( m_pFTM )
  86. {
  87. m_pFTM->Release();
  88. }
  89. }
  90. public:
  91. STDMETHOD(get_Name)(
  92. /*[out, retval]*/ BSTR* pName
  93. );
  94. STDMETHOD(get_Company)(
  95. /*[out, retval]*/ BSTR* pCompany
  96. );
  97. STDMETHOD(get_Version)(
  98. /*[out, retval]*/ BSTR* pVersion
  99. );
  100. STDMETHOD(get_TerminalClass)(
  101. /*[out, retval]*/ BSTR* pTerminalClass
  102. );
  103. STDMETHOD(get_CLSID)(
  104. /*[out, retval]*/ BSTR* pCLSID
  105. );
  106. STDMETHOD(get_Direction)(
  107. /*[out, retval]*/ TERMINAL_DIRECTION* pDirection
  108. );
  109. STDMETHOD(get_MediaTypes)(
  110. /*[out, retval]*/ long* pMediaTypes
  111. );
  112. private:
  113. CMSPCritSection m_CritSect; // Critical Section
  114. BSTR m_bstrName;
  115. BSTR m_bstrCompany;
  116. BSTR m_bstrVersion;
  117. BSTR m_bstrTerminalClass;
  118. BSTR m_bstrCLSID;
  119. long m_lMediaType;
  120. TERMINAL_DIRECTION m_Direction;
  121. IUnknown* m_pFTM; // pointer to the free threaded marshaler
  122. private:
  123. STDMETHOD(put_Name)(
  124. /*[in]*/ BSTR bstrName
  125. );
  126. STDMETHOD(put_Company)(
  127. /*[in]*/ BSTR bstrCompany
  128. );
  129. STDMETHOD(put_Version)(
  130. /*[in]*/ BSTR bstrVersion
  131. );
  132. STDMETHOD(put_TerminalClass)(
  133. /*[in]*/ BSTR bstrTerminalClass
  134. );
  135. STDMETHOD(put_CLSID)(
  136. /*[in]*/ BSTR bstrCLSID
  137. );
  138. STDMETHOD(put_Direction)(
  139. /*[in]*/ TERMINAL_DIRECTION nDirection
  140. );
  141. STDMETHOD(put_MediaTypes)(
  142. /*[in]*/ long nMediaTypes
  143. );
  144. friend class CMSPAddress;
  145. };
  146. class ATL_NO_VTABLE CPlugTerminalSuperclassInfo :
  147. public IDispatchImpl<ITPluggableTerminalSuperclassInfo, &IID_ITPluggableTerminalSuperclassInfo, &LIBID_TAPI3Lib>,
  148. public CComObjectRootEx<CComMultiThreadModel>,
  149. public CMSPObjectSafetyImpl
  150. {
  151. public:
  152. DECLARE_GET_CONTROLLING_UNKNOWN()
  153. virtual HRESULT FinalConstruct(void);
  154. BEGIN_COM_MAP(CPlugTerminalSuperclassInfo)
  155. COM_INTERFACE_ENTRY(ITPluggableTerminalSuperclassInfo)
  156. COM_INTERFACE_ENTRY(IDispatch)
  157. COM_INTERFACE_ENTRY(IObjectSafety)
  158. COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM)
  159. END_COM_MAP()
  160. public:
  161. CPlugTerminalSuperclassInfo() :
  162. m_bstrCLSID(NULL),
  163. m_bstrName(NULL),
  164. m_pFTM(NULL)
  165. {
  166. }
  167. ~CPlugTerminalSuperclassInfo()
  168. {
  169. if( m_bstrName )
  170. {
  171. SysFreeString( m_bstrName );
  172. }
  173. if( m_bstrCLSID )
  174. {
  175. SysFreeString( m_bstrCLSID );
  176. }
  177. if( m_pFTM )
  178. {
  179. m_pFTM->Release();
  180. }
  181. }
  182. public:
  183. STDMETHOD(get_Name)(
  184. /*[out, retval]*/ BSTR* pName
  185. );
  186. STDMETHOD(get_CLSID)(
  187. /*[out, retval]*/ BSTR* pCLSID
  188. );
  189. private:
  190. CMSPCritSection m_CritSect; // Critical Section
  191. BSTR m_bstrCLSID;
  192. BSTR m_bstrName;
  193. IUnknown* m_pFTM; // pointer to the free threaded marshaler
  194. private:
  195. STDMETHOD(put_Name)(
  196. /*[in]*/ BSTR bstrName
  197. );
  198. STDMETHOD(put_CLSID)(
  199. /*[in]*/ BSTR bstrCLSID
  200. );
  201. friend class CMSPAddress;
  202. };
  203. /*++
  204. Class Description:
  205. Represents an MSP address.
  206. --*/
  207. class ATL_NO_VTABLE CMSPAddress :
  208. public CComObjectRootEx<CComMultiThreadModelNoCS>,
  209. public ITMSPAddress,
  210. public IDispatchImpl<ITTerminalSupport2, &IID_ITTerminalSupport2, &LIBID_TAPI3Lib>
  211. {
  212. public:
  213. // No need for free thread marshaling, because the MSP address object is
  214. // always aggregated by the TAPI3 address object.
  215. BEGIN_COM_MAP( CMSPAddress )
  216. COM_INTERFACE_ENTRY( ITMSPAddress )
  217. COM_INTERFACE_ENTRY( IDispatch )
  218. COM_INTERFACE_ENTRY( ITTerminalSupport )
  219. COM_INTERFACE_ENTRY( ITTerminalSupport2 )
  220. END_COM_MAP()
  221. // The DERIVED class should DECLARE_AGGREGATABLE(className)
  222. DECLARE_GET_CONTROLLING_UNKNOWN()
  223. DECLARE_VQI()
  224. CMSPAddress();
  225. virtual ~CMSPAddress();
  226. virtual ULONG MSPAddressAddRef(void) = 0;
  227. virtual ULONG MSPAddressRelease(void) = 0;
  228. // ITMSPAddress methods, called by TAPI.
  229. STDMETHOD (Initialize) (
  230. IN MSP_HANDLE htEvent
  231. );
  232. STDMETHOD (Shutdown) ();
  233. STDMETHOD (CreateMSPCall) (
  234. IN MSP_HANDLE htCall,
  235. IN DWORD dwReserved,
  236. IN DWORD dwMediaType,
  237. IN IUnknown * pOuterUnknown,
  238. OUT IUnknown ** ppMSPCall
  239. ) = 0;
  240. STDMETHOD (ShutdownMSPCall) (
  241. IN IUnknown * pMSPCall
  242. ) = 0;
  243. STDMETHOD (ReceiveTSPData) (
  244. IN IUnknown * pMSPCall,
  245. IN LPBYTE pBuffer,
  246. IN DWORD dwBufferSize
  247. );
  248. STDMETHOD (GetEvent) (
  249. IN OUT DWORD * pdwSize,
  250. OUT BYTE * pBuffer
  251. );
  252. // ITTerminalSupport methods, called by TAPI and/or the app.
  253. STDMETHOD (get_StaticTerminals) (
  254. OUT VARIANT * pVariant
  255. );
  256. STDMETHOD (EnumerateStaticTerminals) (
  257. OUT IEnumTerminal ** ppTerminalEnumerator
  258. );
  259. STDMETHOD (get_DynamicTerminalClasses) (
  260. OUT VARIANT * pVariant
  261. );
  262. STDMETHOD (EnumerateDynamicTerminalClasses) (
  263. OUT IEnumTerminalClass ** ppTerminalClassEnumerator
  264. );
  265. STDMETHOD (CreateTerminal) (
  266. IN BSTR pTerminalClass,
  267. IN long lMediaType,
  268. IN TERMINAL_DIRECTION Direction,
  269. OUT ITTerminal ** ppTerminal
  270. );
  271. STDMETHOD (GetDefaultStaticTerminal) (
  272. IN long lMediaType,
  273. IN TERMINAL_DIRECTION Direction,
  274. OUT ITTerminal ** ppTerminal
  275. );
  276. STDMETHOD (get_PluggableSuperclasses)(
  277. OUT VARIANT * pVariant
  278. );
  279. STDMETHOD (EnumeratePluggableSuperclasses)(
  280. OUT IEnumPluggableSuperclassInfo** ppSuperclassEnumerator
  281. );
  282. STDMETHOD (get_PluggableTerminalClasses)(
  283. IN BSTR bstrTerminalSuperclass,
  284. IN long lMediaType,
  285. OUT VARIANT * pVariant
  286. );
  287. STDMETHOD (EnumeratePluggableTerminalClasses)(
  288. IN CLSID iidTerminalSuperclass,
  289. IN long lMediaType,
  290. OUT IEnumPluggableTerminalClassInfo ** ppClassEnumerator
  291. );
  292. protected:
  293. // ITTerminalSupport helper methods
  294. virtual HRESULT GetStaticTerminals (
  295. IN OUT DWORD * pdwNumTerminals,
  296. OUT ITTerminal ** ppTerminals
  297. );
  298. virtual HRESULT GetDynamicTerminalClasses (
  299. IN OUT DWORD * pdwNumClasses,
  300. OUT IID * pTerminalClasses
  301. );
  302. public:
  303. // methods used by the MSPCall object.
  304. //
  305. // Check to see if the mediatype is non-zero and is in the mask.
  306. // Your MSP can override this if it needs to do special checks on
  307. // specific combinations of media types (e.g., can never have more
  308. // than one media type on a call, can never have video without
  309. // audio, etc.) The default implementation accepts any nonempty
  310. // set of media types that is a subset of the set of all supported
  311. // media types (specified via the GetCallMediaTypes method).
  312. //
  313. virtual BOOL IsValidSetOfMediaTypes(DWORD dwMediaType, DWORD dwMask);
  314. // Note: the eventItem must be allocated by malloc or new
  315. // (when the event is processed, it is deleted).
  316. virtual HRESULT PostEvent(
  317. IN MSPEVENTITEM * EventItem
  318. );
  319. // method used by template function
  320. virtual DWORD GetCallMediaTypes(void) = 0;
  321. protected:
  322. // Private helper function (protected so derived class can call it)
  323. virtual HRESULT IsMonikerInTerminalList(IMoniker* pMoniker);
  324. virtual HRESULT UpdateTerminalListForPnp(
  325. IN BOOL bDeviceArrival
  326. );
  327. virtual HRESULT UpdateTerminalList(void);
  328. virtual HRESULT ReceiveTSPAddressData(
  329. IN PBYTE pBuffer,
  330. IN DWORD dwSize
  331. );
  332. public:
  333. // methods used by the MSPThread object.
  334. virtual HRESULT PnpNotifHandler(
  335. IN BOOL bDeviceArrival
  336. );
  337. protected:
  338. // The handle to TAPI's event, which is used to notify TAPI that the MSP
  339. // wants to send data to it.
  340. HANDLE m_htEvent;
  341. // List of events.
  342. LIST_ENTRY m_EventList;
  343. // The lock that protects the data related to event handling with TAPI.
  344. CMSPCritSection m_EventDataLock;
  345. // The pointer to the terminal manager object.
  346. ITTerminalManager * m_pITTerminalManager;
  347. // The list of static terminals that can be used on the address.
  348. CMSPArray <ITTerminal *> m_Terminals;
  349. BOOL m_fTerminalsUpToDate;
  350. // The lock that protects the data members for terminal operations.
  351. CMSPCritSection m_TerminalDataLock;
  352. private:
  353. static const STATIC_TERMINAL_TYPE m_saTerminalTypes[];
  354. static const DWORD m_sdwTerminalTypesCount;
  355. };
  356. template <class T>
  357. HRESULT CreateMSPCallHelper(
  358. IN CMSPAddress * pCMSPAddress,
  359. IN MSP_HANDLE htCall,
  360. IN DWORD dwReserved,
  361. IN DWORD dwMediaType,
  362. IN IUnknown * pOuterUnknown,
  363. OUT IUnknown ** ppMSPCall,
  364. OUT T ** ppCMSPCall
  365. )
  366. {
  367. LOG((MSP_TRACE, "CreateMSPCallHelper - enter"));
  368. HRESULT hr;
  369. T * pMSPCall;
  370. IUnknown *pUnknown = NULL;
  371. //
  372. // Check parameters.
  373. //
  374. if ( IsBadReadPtr(pCMSPAddress, sizeof(CMSPAddress) ) )
  375. {
  376. LOG((MSP_ERROR, "CreateMSPCallHelper - "
  377. "bad address pointer - exit E_POINTER"));
  378. return E_POINTER;
  379. }
  380. if ( IsBadReadPtr(pOuterUnknown, sizeof(IUnknown) ) )
  381. {
  382. LOG((MSP_ERROR, "CreateMSPCallHelper - "
  383. "bad outer unknown - we require aggregation - exit E_POINTER"));
  384. return E_POINTER;
  385. }
  386. if ( IsBadReadPtr(ppMSPCall, sizeof(IUnknown *) ) )
  387. {
  388. LOG((MSP_ERROR, "CreateMSPCallHelper - "
  389. "bad iunknown return ptr - exit E_POINTER"));
  390. return E_POINTER;
  391. }
  392. if ( IsBadReadPtr(ppCMSPCall, sizeof(T *) ) )
  393. {
  394. LOG((MSP_ERROR, "CreateMSPCallHelper - "
  395. "bad class return ptr - exit E_POINTER"));
  396. return E_POINTER;
  397. }
  398. if ( ! pCMSPAddress->IsValidSetOfMediaTypes(
  399. dwMediaType,
  400. pCMSPAddress->GetCallMediaTypes() ) )
  401. {
  402. LOG((MSP_ERROR, "CreateMSPCallHelper - "
  403. "unsupported media types - exit TAPI_E_INVALIDMEDIATYPE"));
  404. return TAPI_E_INVALIDMEDIATYPE;
  405. }
  406. // dwReserved is meaningless.
  407. // We have no way of checking htCall.
  408. // the pOuterUnknown is not NULL. This object is going to be aggregated.
  409. CComAggObject<T> * pCall;
  410. pCall = new CComAggObject<T>(pOuterUnknown);
  411. if (pCall == NULL)
  412. {
  413. LOG((MSP_ERROR, "CreateMSPCallHelper - "
  414. "could not create agg call instance - exit E_OUTOFMEMORY"));
  415. return E_OUTOFMEMORY;
  416. }
  417. // query the interface on the containing object.
  418. hr = pCall->QueryInterface(IID_IUnknown, (void **)&pUnknown);
  419. if (FAILED(hr))
  420. {
  421. LOG((MSP_ERROR, "CreateMSPCallHelper - "
  422. "QueryInterface failed: %x", hr));
  423. delete pCall;
  424. return hr;
  425. }
  426. hr = pCall->FinalConstruct();
  427. if (FAILED(hr))
  428. {
  429. LOG((MSP_ERROR, "CreateMSPCallHelper - "
  430. "FinalConstruct failed: %x.", hr));
  431. pUnknown->Release();
  432. return hr;
  433. }
  434. // Get a pointer to the real MSPCall object.
  435. pMSPCall = dynamic_cast<T *>(&(pCall->m_contained));
  436. if (pMSPCall == NULL)
  437. {
  438. LOG((MSP_ERROR, "CreateMSPCallHelper - "
  439. "can not cast to agg object to class pointer - "
  440. "exit E_UNEXPECTED"));
  441. pUnknown->Release();
  442. return E_UNEXPECTED;
  443. }
  444. //
  445. // initialize the call.
  446. //
  447. hr = pMSPCall->Init(pCMSPAddress, htCall, dwReserved, dwMediaType);
  448. if (FAILED(hr))
  449. {
  450. LOG((MSP_ERROR, "CreateMSPCallHelper - "
  451. "call init failed: %x", hr));
  452. pUnknown->Release();
  453. return hr;
  454. }
  455. *ppMSPCall = pUnknown;
  456. *ppCMSPCall = pMSPCall;
  457. LOG((MSP_TRACE, "CreateMSPCallHelper - exit S_OK"));
  458. return hr;
  459. }
  460. template <class T>
  461. HRESULT ShutdownMSPCallHelper(
  462. IN IUnknown * pUnknown,
  463. OUT T ** ppCMSPCall
  464. )
  465. {
  466. LOG((MSP_TRACE, "ShutdownMSPCallHelper - enter"));
  467. if ( IsBadReadPtr(pUnknown, sizeof(IUnknown) ) )
  468. {
  469. LOG((MSP_ERROR, "ShutdownMSPCallHelper - "
  470. "bad IUnknown pointer - exit E_POINTER"));
  471. return E_POINTER;
  472. }
  473. if ( IsBadWritePtr(ppCMSPCall, sizeof(T *) ) )
  474. {
  475. LOG((MSP_ERROR, "ShutdownMSPCallHelper - "
  476. "bad return pointer - exit E_POINTER"));
  477. return E_POINTER;
  478. }
  479. T * pMSPCall;
  480. CComAggObject<T> * pCall = dynamic_cast<CComAggObject<T> *> (pUnknown);
  481. if (pCall == NULL)
  482. {
  483. LOG((MSP_ERROR, "ShutdownMSPCallHelper - "
  484. "can't cast unknown to agg object pointer - exit E_UNEXPECTED"));
  485. return E_UNEXPECTED;
  486. }
  487. //
  488. // It was aggregated. Get a pointer to the real MSPCall object.
  489. //
  490. pMSPCall = dynamic_cast<T *> (&(pCall->m_contained));
  491. if (pMSPCall == NULL)
  492. {
  493. LOG((MSP_ERROR, "ShutdownMSPCallHelper - "
  494. "can't cast contained unknown to class pointer - "
  495. "exit E_UNEXPECTED"));
  496. return E_UNEXPECTED;
  497. }
  498. //
  499. // Now we have a call to shut down. Shut it down.
  500. //
  501. HRESULT hr = pMSPCall->ShutDown();
  502. if (FAILED(hr))
  503. {
  504. LOG((MSP_ERROR, "ShutdownMSPCallHelper - "
  505. "ShutDownMSPCall failed: %x", hr));
  506. return hr;
  507. }
  508. *ppCMSPCall = pMSPCall;
  509. LOG((MSP_TRACE, "ShutdownMSPCallHelper - exit S_OK"));
  510. return S_OK;
  511. }
  512. #endif //__MSPADDRESS_H_