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.

1037 lines
24 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. mspstrm.cpp
  5. Abstract:
  6. This module contains implementation of CMSPStream. The object represents
  7. one stream in the filter graph.
  8. --*/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CMSPStream
  13. /////////////////////////////////////////////////////////////////////////////
  14. CMSPStream::CMSPStream()
  15. : m_dwState(STRM_INITIAL),
  16. m_dwMediaType(0),
  17. m_pFTM(NULL),
  18. m_hAddress(NULL),
  19. m_pMSPCall(NULL),
  20. m_pIGraphBuilder(NULL),
  21. m_pIMediaControl(NULL),
  22. m_pPTEventSink( NULL )
  23. {
  24. LOG((MSP_TRACE, "CMSPStream::CMSPStream - enter"));
  25. LOG((MSP_TRACE, "CMSPStream::CMSPStream - exit"));
  26. }
  27. CMSPStream::~CMSPStream()
  28. {
  29. LOG((MSP_TRACE, "CMSPStream::~CMSPStream - enter"));
  30. ReleaseSink();
  31. LOG((MSP_TRACE, "CMSPStream::~CMSPStream - exit"));
  32. }
  33. STDMETHODIMP CMSPStream::get_MediaType(
  34. OUT long * plTapiMediaType
  35. )
  36. {
  37. LOG((MSP_TRACE, "CMSPStream::get_MediaType - enter"));
  38. if (MSPB_IsBadWritePtr(plTapiMediaType, sizeof (long *)))
  39. {
  40. LOG((MSP_ERROR, "CMSPStream::get_MediaType - exit E_POINTER"));
  41. return E_POINTER;
  42. }
  43. CLock lock(m_lock);
  44. *plTapiMediaType = m_dwMediaType;
  45. LOG((MSP_TRACE, "CMSPStream::get_MediaType - exit S_OK"));
  46. return S_OK;
  47. }
  48. STDMETHODIMP CMSPStream::get_Direction(
  49. OUT TERMINAL_DIRECTION * pTerminalDirection
  50. )
  51. {
  52. LOG((MSP_TRACE, "CMSPStream::get_Direction - enter"));
  53. if (MSPB_IsBadWritePtr(pTerminalDirection, sizeof (TERMINAL_DIRECTION *)))
  54. {
  55. LOG((MSP_ERROR, "CMSPStream::get_Direction - exit E_POINTER"));
  56. return E_POINTER;
  57. }
  58. CLock lock(m_lock);
  59. *pTerminalDirection = m_Direction;
  60. LOG((MSP_TRACE, "CMSPStream::get_Direction - exit S_OK"));
  61. return S_OK;
  62. }
  63. STDMETHODIMP CMSPStream::SelectTerminal(
  64. IN ITTerminal * pTerminal
  65. )
  66. /*++
  67. Routine Description:
  68. Arguments:
  69. Return Value:
  70. S_OK
  71. E_POINTER
  72. E_OUTOFMEMORY
  73. TAPI_E_MAXTERMINALS
  74. TAPI_E_INVALIDTERMINAL
  75. --*/
  76. {
  77. LOG((MSP_TRACE, "CMSPStream::SelectTerminal - enter"));
  78. //
  79. // Check parameter.
  80. //
  81. if ( IsBadReadPtr(pTerminal, sizeof(ITTerminal) ) )
  82. {
  83. LOG((MSP_ERROR, "CMSPStream::SelectTerminal - exit E_POINTER"));
  84. return E_POINTER;
  85. }
  86. HRESULT hr;
  87. ITTerminalControl *pTerminalControl;
  88. //
  89. // Get the private interface from this terminal.
  90. //
  91. hr = pTerminal->QueryInterface(IID_ITTerminalControl,
  92. (void **) &pTerminalControl);
  93. if (FAILED(hr))
  94. {
  95. LOG((MSP_ERROR, "CMSPStream::SelectTerminal - "
  96. "can't get ITTerminalControl - exit TAPI_E_INVALIDTERMINAL"));
  97. return TAPI_E_INVALIDTERMINAL;
  98. }
  99. //
  100. // Get the address handle and release the private interface.
  101. //
  102. MSP_HANDLE hAddress;
  103. hr = pTerminalControl->get_AddressHandle(&hAddress);
  104. pTerminalControl->Release();
  105. if (FAILED(hr))
  106. {
  107. LOG((MSP_ERROR, "CMSPStream::SelectTerminal - "
  108. "can't get address handle - exit TAPI_E_INVALIDTERMINAL"));
  109. return TAPI_E_INVALIDTERMINAL;
  110. }
  111. //
  112. // Find out if the terminal belongs to this address. Reject it if it belongs
  113. // to another address, but accept it if it is an application-provided terminal
  114. // (NULL address handle).
  115. //
  116. if ( ( hAddress != NULL ) && ( hAddress != (MSP_HANDLE) m_hAddress ) )
  117. {
  118. LOG((MSP_ERROR, "CMSPStream::SelectTerminal - "
  119. "terminal from another address - exit TAPI_E_INVALIDTERMINAL"));
  120. return TAPI_E_INVALIDTERMINAL;
  121. }
  122. //
  123. // Find out if the terminal is already in our list.
  124. //
  125. CLock lock(m_lock);
  126. if (m_Terminals.Find(pTerminal) >= 0)
  127. {
  128. LOG((MSP_ERROR, "CMSPStream::SelectTerminal - "
  129. "terminal already selected - exit TAPI_E_INVALIDTERMINAL"));
  130. return TAPI_E_INVALIDTERMINAL;
  131. }
  132. //
  133. // Add the new terminal into our list and addref it.
  134. //
  135. if (!m_Terminals.Add(pTerminal))
  136. {
  137. LOG((MSP_ERROR, "CMSPStream::SelectTerminal - "
  138. "exit E_OUTOFMEMORY"));
  139. return E_OUTOFMEMORY;
  140. }
  141. pTerminal->AddRef();
  142. hr = RegisterPluggableTerminalEventSink( pTerminal );
  143. if( FAILED(hr) )
  144. {
  145. LOG((MSP_TRACE, "CMSPStream::SelectTerminal - "
  146. "something wrong in RegisterPluggableTerminalEventSink"));
  147. }
  148. LOG((MSP_TRACE, "CMSPStream::SelectTerminal - exit S_OK"));
  149. return S_OK;
  150. }
  151. STDMETHODIMP CMSPStream::UnselectTerminal(
  152. IN ITTerminal * pTerminal
  153. )
  154. {
  155. LOG((MSP_TRACE, "CMSPStream::UnselectTerminal - enter"));
  156. //
  157. // find out if the terminal is in our list.
  158. //
  159. CLock lock(m_lock);
  160. int index;
  161. if ((index = m_Terminals.Find(pTerminal)) < 0)
  162. {
  163. LOG((MSP_ERROR, "CMSPStream::UnselectTerminal - "
  164. "exit TAPI_E_INVALIDTERMINAL"));
  165. return TAPI_E_INVALIDTERMINAL;
  166. }
  167. //
  168. // Unregister the PTEventSink object
  169. //
  170. HRESULT hr = E_FAIL;
  171. hr = UnregisterPluggableTerminalEventSink( pTerminal );
  172. if( FAILED(hr) )
  173. {
  174. LOG((MSP_TRACE, "CMSPStream::UnselectTerminal - "
  175. "something wrong in UnregisterPluggableTerminalEventSink"));
  176. }
  177. //
  178. // remove the terminal from our list and release it.
  179. //
  180. if (!m_Terminals.RemoveAt(index))
  181. {
  182. LOG((MSP_ERROR, "CMSPStream::UnselectTerminal - "
  183. "exit E_UNEXPECTED"));
  184. return E_UNEXPECTED;
  185. }
  186. pTerminal->Release();
  187. LOG((MSP_TRACE, "CMSPStream::UnselectTerminal - exit S_OK"));
  188. return S_OK;
  189. }
  190. STDMETHODIMP CMSPStream::EnumerateTerminals(
  191. OUT IEnumTerminal ** ppEnumTerminal
  192. )
  193. {
  194. LOG((MSP_TRACE,
  195. "EnumerateTerminals entered. ppEnumTerminal:%x", ppEnumTerminal));
  196. if (MSPB_IsBadWritePtr(ppEnumTerminal, sizeof(VOID *)))
  197. {
  198. LOG((MSP_ERROR, "ppEnumTerminal is a bad pointer"));
  199. return E_POINTER;
  200. }
  201. // acquire the lock before accessing the Terminal object list.
  202. CLock lock(m_lock);
  203. if (m_Terminals.GetData() == NULL)
  204. {
  205. LOG((MSP_ERROR, "CMSPStream::EnumerateTerminals - "
  206. "stream appears to have been shut down - exit E_UNEXPECTED"));
  207. return E_UNEXPECTED;
  208. }
  209. typedef _CopyInterface<ITTerminal> CCopy;
  210. typedef CSafeComEnum<IEnumTerminal, &IID_IEnumTerminal,
  211. ITTerminal *, CCopy> CEnumerator;
  212. HRESULT hr;
  213. CMSPComObject<CEnumerator> *pEnum = NULL;
  214. hr = CMSPComObject<CEnumerator>::CreateInstance(&pEnum);
  215. if (pEnum == NULL)
  216. {
  217. LOG((MSP_ERROR, "Could not create enumerator object, %x", hr));
  218. return hr;
  219. }
  220. // query for the IID_IEnumTerminal i/f
  221. hr = pEnum->_InternalQueryInterface(IID_IEnumTerminal, (void**)ppEnumTerminal);
  222. if (FAILED(hr))
  223. {
  224. LOG((MSP_ERROR, "query enum interface failed, %x", hr));
  225. delete pEnum;
  226. return hr;
  227. }
  228. // The CSafeComEnum can handle zero-sized array.
  229. hr = pEnum->Init(
  230. m_Terminals.GetData(), // the begin itor
  231. m_Terminals.GetData() + m_Terminals.GetSize(), // the end itor,
  232. NULL, // IUnknown
  233. AtlFlagCopy // copy the data.
  234. );
  235. if (FAILED(hr))
  236. {
  237. LOG((MSP_ERROR, "init enumerator object failed, %x", hr));
  238. (*ppEnumTerminal)->Release();
  239. return hr;
  240. }
  241. LOG((MSP_TRACE, "CMSPStream::EnumerateTerminals - exit S_OK"));
  242. return hr;
  243. }
  244. STDMETHODIMP CMSPStream::get_Terminals(
  245. OUT VARIANT * pVariant
  246. )
  247. {
  248. LOG((MSP_TRACE, "CMSPStream::get_Terminals - enter"));
  249. //
  250. // Check parameters.
  251. //
  252. if ( MSPB_IsBadWritePtr(pVariant, sizeof(VARIANT) ) )
  253. {
  254. LOG((MSP_ERROR, "CMSPStream::get_Terminals - "
  255. "bad pointer argument - exit E_POINTER"));
  256. return E_POINTER;
  257. }
  258. //
  259. // See if this stream has been shut down. Acquire the lock before accessing
  260. // the terminal object list.
  261. //
  262. CLock lock(m_lock);
  263. if (m_Terminals.GetData() == NULL)
  264. {
  265. LOG((MSP_ERROR, "CMSPStream::get_Terminals - "
  266. "stream appears to have been shut down - exit E_UNEXPECTED"));
  267. return E_UNEXPECTED;
  268. }
  269. //
  270. // create the collection object - see mspcoll.h
  271. //
  272. HRESULT hr;
  273. typedef CTapiIfCollection< ITTerminal * > TerminalCollection;
  274. CComObject<TerminalCollection> * pCollection;
  275. hr = CComObject<TerminalCollection>::CreateInstance( &pCollection );
  276. if ( FAILED(hr) )
  277. {
  278. LOG((MSP_ERROR, "CMSPStream::get_Terminals - "
  279. "can't create collection - exit 0x%08x", hr));
  280. return hr;
  281. }
  282. //
  283. // get the Collection's IDispatch interface
  284. //
  285. IDispatch * pDispatch;
  286. hr = pCollection->_InternalQueryInterface(IID_IDispatch,
  287. (void **) &pDispatch );
  288. if ( FAILED(hr) )
  289. {
  290. LOG((MSP_ERROR, "CMSPStream::get_Terminals - "
  291. "QI for IDispatch on collection failed - exit 0x%08x", hr));
  292. delete pCollection;
  293. return hr;
  294. }
  295. //
  296. // Init the collection using an iterator -- pointers to the beginning and
  297. // the ending element plus one.
  298. //
  299. hr = pCollection->Initialize( m_Terminals.GetSize(),
  300. m_Terminals.GetData(),
  301. m_Terminals.GetData() + m_Terminals.GetSize() );
  302. if (FAILED(hr))
  303. {
  304. LOG((MSP_ERROR, "CMSPStream::get_Terminals - "
  305. "Initialize on collection failed - exit 0x%08x", hr));
  306. pDispatch->Release();
  307. return hr;
  308. }
  309. //
  310. // put the IDispatch interface pointer into the variant
  311. //
  312. LOG((MSP_TRACE, "CMSPStream::get_Terminals - "
  313. "placing IDispatch value %08x in variant", pDispatch));
  314. VariantInit(pVariant);
  315. pVariant->vt = VT_DISPATCH;
  316. pVariant->pdispVal = pDispatch;
  317. LOG((MSP_TRACE, "CMSPStream::get_Terminals - exit S_OK"));
  318. return S_OK;
  319. }
  320. STDMETHODIMP CMSPStream::StartStream()
  321. {
  322. LOG((MSP_TRACE, "CMSPStream - RUNNING GRAPH"));
  323. HRESULT hr = m_pIMediaControl->Run();
  324. if(FAILED(hr))
  325. {
  326. LOG((MSP_ERROR, "graph doesn't run, %x", hr));
  327. }
  328. return hr;
  329. }
  330. STDMETHODIMP CMSPStream::PauseStream()
  331. {
  332. LOG((MSP_TRACE, "CMSPStream - PAUSING GRAPH"));
  333. HRESULT hr = m_pIMediaControl->Pause();
  334. if(FAILED(hr))
  335. {
  336. LOG((MSP_ERROR, "graph doesn't pause, %x", hr));
  337. }
  338. return hr;
  339. }
  340. STDMETHODIMP CMSPStream::StopStream()
  341. {
  342. LOG((MSP_TRACE, "CMSPStream - STOPPING GRAPH"));
  343. HRESULT hr = m_pIMediaControl->Stop();
  344. if(FAILED(hr))
  345. {
  346. LOG((MSP_ERROR, "graph doesn't stop, %x", hr));
  347. }
  348. return hr;
  349. }
  350. // methods called by the MSPCall object.
  351. HRESULT CMSPStream::Init(
  352. IN HANDLE hAddress,
  353. IN CMSPCallBase * pMSPCall,
  354. IN IMediaEvent * pGraph,
  355. IN DWORD dwMediaType,
  356. IN TERMINAL_DIRECTION Direction
  357. )
  358. {
  359. LOG((MSP_TRACE, "CMSPStream::Init - enter"));
  360. CLock lock(m_lock);
  361. // This method is called only once when the object is created. No other
  362. // method will be called until this function succeeds. No need to lock.
  363. _ASSERTE(m_hAddress == NULL);
  364. // initialize the terminal array so that the array is not NULL. Used for
  365. // generating an empty enumerator if no terminal is selected.
  366. if (!m_Terminals.Grow())
  367. {
  368. LOG((MSP_ERROR, "CMSPStream::Init - exit E_OUTOFMEMORY"));
  369. return E_OUTOFMEMORY;
  370. }
  371. HRESULT hr;
  372. hr = CoCreateFreeThreadedMarshaler(GetControllingUnknown(), &m_pFTM);
  373. if (FAILED(hr))
  374. {
  375. LOG((MSP_ERROR, "create marshaler failed, %x", hr));
  376. return hr;
  377. }
  378. // Get the media control interface on the graph.
  379. IMediaControl *pMC;
  380. hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC);
  381. if(FAILED(hr))
  382. {
  383. LOG((MSP_ERROR, "get IMediaControl interface, %x", hr));
  384. return hr;
  385. }
  386. // Get the graph builder interface on the graph.
  387. IGraphBuilder *pGB;
  388. hr = pGraph->QueryInterface(IID_IGraphBuilder, (void **) &pGB);
  389. if(FAILED(hr))
  390. {
  391. LOG((MSP_ERROR, "get IGraphBuilder interface, %x", hr));
  392. pMC->Release();
  393. return hr;
  394. }
  395. m_hAddress = hAddress;
  396. m_pMSPCall = pMSPCall;
  397. m_pMSPCall->MSPCallAddRef();
  398. m_pIMediaControl = pMC;
  399. // no addref because QI addrefs for us above
  400. m_pIGraphBuilder = pGB;
  401. // no addref because QI addrefs for us above
  402. m_dwMediaType = dwMediaType;
  403. m_Direction = Direction;
  404. LOG((MSP_TRACE, "CMSPStream::Init - exit S_OK"));
  405. return S_OK;
  406. }
  407. HRESULT CMSPStream::ShutDown()
  408. {
  409. LOG((MSP_TRACE, "CMSPStream::Shutdown - enter"));
  410. CLock lock(m_lock);
  411. //
  412. // We are shut down, so the call is now NULL.
  413. //
  414. m_pMSPCall->MSPCallRelease();
  415. m_pMSPCall = NULL;
  416. //
  417. // Unselect all the terminals. Rather than just removing all the
  418. // terminals, we call UnselectTerminal on each one to give the derived
  419. // class a chance to do whatever else it needs to do when a terminal
  420. // is unselected.
  421. //
  422. // We walk the list in reverse order because the list shrinks with
  423. // each iteration (see msputils.h).
  424. //
  425. for ( int i = m_Terminals.GetSize() - 1; i >= 0; i-- )
  426. {
  427. UnselectTerminal(m_Terminals[i]);
  428. }
  429. //
  430. // At this point the derive class should have removed and released
  431. // all of the terminals from the list. If that's not the case, the
  432. // derived class is buggy.
  433. //
  434. _ASSERTE( m_Terminals.GetSize() == 0 );
  435. //
  436. // no longer need the sink
  437. //
  438. ReleaseSink();
  439. LOG((MSP_TRACE, "CMSPStream::Shutdown - exit S_OK"));
  440. return S_OK;
  441. }
  442. void CMSPStream::FinalRelease()
  443. {
  444. LOG((MSP_TRACE, "CMSPStream::FinalRelease - enter"));
  445. // release the two interface pointers to the graph.
  446. if (m_pIMediaControl)
  447. {
  448. m_pIMediaControl->Release();
  449. }
  450. if (m_pIGraphBuilder)
  451. {
  452. m_pIGraphBuilder->Release();
  453. }
  454. if (m_pFTM)
  455. {
  456. m_pFTM->Release();
  457. }
  458. LOG((MSP_TRACE, "CMSPStream::FinalRelease - exit"));
  459. }
  460. HRESULT CMSPStream::HandleTSPData(
  461. IN BYTE * pData,
  462. IN DWORD dwSize
  463. )
  464. {
  465. LOG((MSP_TRACE, "CMSPStream::HandleTSPData - enter"));
  466. LOG((MSP_TRACE, "CMSPStream::HandleTSPData - exit S_OK"));
  467. return S_OK;
  468. }
  469. HRESULT CMSPStream::ProcessGraphEvent(
  470. IN long lEventCode,
  471. IN LONG_PTR lParam1,
  472. IN LONG_PTR lParam2
  473. )
  474. {
  475. LOG((MSP_TRACE, "CMSPStream::ProcessGraphEvent - enter"));
  476. LOG((MSP_TRACE, "CMSPStream::ProcessGraphEvent - exit S_OK"));
  477. return S_OK;
  478. }
  479. /*++
  480. RegisterPluggableTerminalEventSink
  481. Parameters:
  482. The terminla interface
  483. Description;
  484. Is called by SelectTerminal if is a dynamic terminal
  485. --*/
  486. HRESULT CMSPStream::RegisterPluggableTerminalEventSink(
  487. IN ITTerminal* pTerminal
  488. )
  489. {
  490. LOG((MSP_TRACE, "CMSPStream::RegisterPluggableTerminalEventSink - enter"));
  491. //
  492. // Validates arguments
  493. //
  494. if( IsBadReadPtr( pTerminal, sizeof( ITTerminal) ))
  495. {
  496. LOG((MSP_ERROR, "CMSPStream::RegisterPluggableTerminalEventSink "
  497. "pTerminal invalid, returns E_POINTER"));
  498. return E_POINTER;
  499. }
  500. //
  501. // Get the type of the terminal
  502. //
  503. TERMINAL_TYPE nTerminalType;
  504. HRESULT hr = E_FAIL;
  505. hr = pTerminal->get_TerminalType( &nTerminalType );
  506. if( FAILED(hr) )
  507. {
  508. LOG((MSP_ERROR, "CMSPStream::RegisterPluggableTerminalEventSink "
  509. "get_TerminalType failed, exit E_UNEXPECTED"));
  510. return E_UNEXPECTED;
  511. }
  512. //
  513. // The terminal should by a dynamic terminal
  514. //
  515. if( TT_DYNAMIC != nTerminalType)
  516. {
  517. LOG((MSP_ERROR, "CMSPStream::RegisterPluggableTerminalEventSink "
  518. "terminal is not dynamic, exit E_INVALIDARG"));
  519. return E_INVALIDARG;
  520. }
  521. CLock lock(m_lock);
  522. //
  523. // Create the sink if we don't have one already
  524. //
  525. if(NULL == m_pPTEventSink)
  526. {
  527. //Create a PTEventSink object
  528. CComObject<CPTEventSink>* pPTEventSink;
  529. hr = CComObject<CPTEventSink>::CreateInstance(&pPTEventSink);
  530. if( FAILED(hr) )
  531. {
  532. LOG((MSP_ERROR, "CMSPStream::RegisterPluggableTerminalEventSink "
  533. "CreateInstance failed, returns E_OUTOFMEMORY"));
  534. return E_OUTOFMEMORY;
  535. }
  536. // tell sink that we are ready to be processing its events
  537. hr = pPTEventSink->SetSinkStream(this);
  538. if (FAILED(hr))
  539. {
  540. LOG((MSP_ERROR, "CMSPStream::RegisterPluggableTerminalEventSink "
  541. "event sink refused to accept sink stream. hr = %lx", hr));
  542. delete pPTEventSink;
  543. return hr;
  544. }
  545. // Get ITPluggableTerminalEventSink interface from the sink
  546. hr = pPTEventSink->QueryInterface(IID_ITPluggableTerminalEventSink, (void**)&m_pPTEventSink);
  547. if( FAILED(hr) )
  548. {
  549. LOG((MSP_ERROR, "CMSPStream::RegisterPluggableTerminalEventSink "
  550. "QI for ITPluggableTerminalEventSink failed, returns E_UNEXPECTED"));
  551. //
  552. // ok, the sink is no good. get rid of it.
  553. //
  554. pPTEventSink->SetSinkStream(NULL);
  555. delete pPTEventSink;
  556. pPTEventSink = NULL;
  557. //
  558. // sink does not expose IID_ITPluggableTerminalEventSink interface?
  559. // something is seriously wrong
  560. //
  561. return E_UNEXPECTED;
  562. }
  563. }
  564. // Get the ITDTEventHandler interface
  565. ITPluggableTerminalEventSinkRegistration* pEventRegistration = NULL;
  566. hr = pTerminal->QueryInterface( IID_ITPluggableTerminalEventSinkRegistration,
  567. (void**)&pEventRegistration
  568. );
  569. if( FAILED(hr) )
  570. {
  571. // The dynamic terminal doesn't implement ITPluggableTerminalEventSinkRegistration
  572. // This is bad! We cannot use the new event stuff
  573. LOG((MSP_ERROR, "CMSPStream::RegisterPluggableTerminalEventSink "
  574. "QI for ITPluggableTerminalEventSinkregistration failed, returns S_FALSE"));
  575. //
  576. // no need to keep the sink
  577. //
  578. ReleaseSink();
  579. return S_FALSE;
  580. }
  581. // pass the sink to the terminal
  582. hr = pEventRegistration->RegisterSink(
  583. m_pPTEventSink
  584. );
  585. // Clean up, anyway
  586. pEventRegistration->Release();
  587. if( FAILED(hr) )
  588. {
  589. LOG((MSP_ERROR, "CMSPStream::RegisterPluggableTerminalEventSink "
  590. "RegisterSink failed, returns E_FAIL"));
  591. //
  592. // no need to keep the sink
  593. //
  594. ReleaseSink();
  595. return E_FAIL;
  596. }
  597. LOG((MSP_TRACE, "CMSPStream::RegisterPluggableTerminalEventSink - exit S_OK"));
  598. return S_OK;
  599. }
  600. /*++
  601. UnregisterPluggableTerminalEventSink
  602. Parameters:
  603. The terminal interface
  604. Description;
  605. Is called by UnselectTerminal if is a dynamic terminal
  606. --*/
  607. HRESULT CMSPStream::UnregisterPluggableTerminalEventSink(
  608. IN ITTerminal* pTerminal
  609. )
  610. {
  611. LOG((MSP_TRACE, "CMSPStream::UnregisterPluggableTerminalEventSink - enter"));
  612. //
  613. // Validates arguments
  614. //
  615. if( IsBadReadPtr( pTerminal, sizeof( ITTerminal) ))
  616. {
  617. LOG((MSP_ERROR, "CMSPStream::UnregisterPluggableTerminalEventSink "
  618. "pTerminal invalid, returns E_POINTER"));
  619. return E_POINTER;
  620. }
  621. //
  622. // Get the type of the terminal
  623. //
  624. TERMINAL_TYPE nTerminalType;
  625. HRESULT hr = E_FAIL;
  626. hr = pTerminal->get_TerminalType( &nTerminalType );
  627. if( FAILED(hr) )
  628. {
  629. LOG((MSP_ERROR, "CMSPStream::UnregisterPluggableTerminalEventSink "
  630. "get_TerminalType failed, exit E_UNEXPECTED"));
  631. return E_UNEXPECTED;
  632. }
  633. //
  634. // The terminal should be a dynamic terminal
  635. //
  636. if( TT_DYNAMIC != nTerminalType)
  637. {
  638. LOG((MSP_ERROR, "CMSPStream::UnregisterPluggableTerminalEventSink "
  639. "terminal is not dynamic, exit E_INVALIDARG"));
  640. return E_INVALIDARG;
  641. }
  642. CLock lock(m_lock);
  643. //
  644. // Have we an EventSink object
  645. //
  646. if(NULL == m_pPTEventSink)
  647. {
  648. LOG((MSP_TRACE, "CMSPStream::UnregisterPluggableTerminalEventSink - "
  649. "No EventSink - exit S_OK"));
  650. return S_OK;
  651. }
  652. //
  653. // Get the ITPluggableTemrinalEventSinkRegistration interface
  654. //
  655. ITPluggableTerminalEventSinkRegistration* pEventRegistration = NULL;
  656. hr = pTerminal->QueryInterface( IID_ITPluggableTerminalEventSinkRegistration,
  657. (void**)&pEventRegistration
  658. );
  659. if( FAILED(hr) )
  660. {
  661. //
  662. // The pluggable terminal doesn't implement ITPluggableTerminalEventSinkRegistration
  663. // This is bad!
  664. LOG((MSP_ERROR, "CMSPStream::UnregisterPluggableTerminalEventSink "
  665. "QI for ITPluggableTerminalEventSinkRegistration failed, returns E_NOTIMPL"));
  666. return E_NOTIMPL;
  667. }
  668. hr = pEventRegistration->UnregisterSink( );
  669. //
  670. // Clean up, anyway
  671. //
  672. pEventRegistration->Release();
  673. if( FAILED(hr) )
  674. {
  675. LOG((MSP_ERROR, "CMSPStream::UnregisterPluggableTerminalEventSink "
  676. "UnregisterSink failed, returns E_FAIL"));
  677. return E_FAIL;
  678. }
  679. //
  680. // no longer need this sink
  681. //
  682. ReleaseSink();
  683. LOG((MSP_TRACE, "CMSPStream::UnregisterPluggableTerminalEventSink - exit S_OK"));
  684. return S_OK;
  685. }
  686. //////////////////////////////////////////////////////////////////////////////
  687. //
  688. // CMSPStream::HandleSinkEvent
  689. //
  690. //
  691. // CPTEventSink calls this method when it has an event for us to process
  692. // HandleSinkEvent delegates event processing to the call, if we have one
  693. //
  694. //////////////////////////////////////////////////////////////////////////////
  695. HRESULT CMSPStream::HandleSinkEvent(MSPEVENTITEM *pEventItem)
  696. {
  697. LOG((MSP_TRACE, "CMSPStream::HandleSinkEvent - enter"));
  698. HRESULT hr = TAPI_E_CALLUNAVAIL;
  699. CLock lock(m_lock);
  700. if (NULL != m_pMSPCall)
  701. {
  702. //
  703. // we have a call. ask it to process the event
  704. //
  705. hr = m_pMSPCall->HandleStreamEvent(pEventItem);
  706. }
  707. else
  708. {
  709. LOG((MSP_WARN,
  710. "CMSPStream::HandleSinkEvent - there is no call to pass event to"));
  711. }
  712. LOG((MSP_(hr), "CMSPStream::HandleSinkEvent - exit hr = %lx", hr));
  713. return hr;
  714. }
  715. //////////////////////////////////////////////////////////////////////////////
  716. //
  717. // CMSPStream::ReleaseSink
  718. //
  719. //
  720. // this is a helper function that lets go of sink when it no longer needed
  721. //
  722. //////////////////////////////////////////////////////////////////////////////
  723. HRESULT CMSPStream::ReleaseSink()
  724. {
  725. LOG((MSP_TRACE, "CMSPStream::ReleaseSink - enter"));
  726. HRESULT hr = S_OK;
  727. CLock lock(m_lock);
  728. //
  729. // if sink is present, let it know that we will no longer be available to
  730. // process its events and release it
  731. //
  732. if( m_pPTEventSink)
  733. {
  734. CPTEventSink *pSinkObject = static_cast<CPTEventSink *>(m_pPTEventSink);
  735. HRESULT hr = pSinkObject->SetSinkStream(NULL);
  736. if (FAILED(hr))
  737. {
  738. LOG((MSP_ERROR,
  739. "CMSPStream::ReleaseSink - pSinkObject->SetSinkStream failed. hr - %lx",
  740. hr));
  741. }
  742. m_pPTEventSink->Release();
  743. m_pPTEventSink = NULL;
  744. }
  745. LOG((MSP_(hr), "CMSPStream::ReleaseSink - exit. hr - %lx", hr));
  746. return hr;
  747. }
  748. // eof