Leaked source code of windows server 2003
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.

1097 lines
23 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. bridgetm.cpp
  5. Abstract:
  6. Implementations for the bridge terminals.
  7. Author:
  8. Mu Han (muhan) 11/12/99
  9. --*/
  10. #include "stdafx.h"
  11. HRESULT
  12. FindPin(
  13. IN IBaseFilter * pIFilter,
  14. OUT IPin ** ppIPin,
  15. IN PIN_DIRECTION direction,
  16. IN BOOL bFree = TRUE // param not used
  17. )
  18. /*++
  19. Routine Description:
  20. Find a input pin or output pin on a filter.
  21. Arguments:
  22. pIFilter - the filter that has pins.
  23. ppIPin - the place to store the returned interface pointer.
  24. direction - PINDIR_INPUT or PINDIR_OUTPUT.
  25. bFree - look for a free pin or not.
  26. Return Value:
  27. HRESULT
  28. --*/
  29. {
  30. _ASSERTE(ppIPin != NULL);
  31. HRESULT hr;
  32. DWORD dwFeched;
  33. // Get the enumerator of pins on the filter.
  34. CComPtr<IEnumPins> pIEnumPins;
  35. if (FAILED(hr = pIFilter->EnumPins(&pIEnumPins)))
  36. {
  37. BGLOG((BG_ERROR, "enumerate pins on the filter %x", hr));
  38. return hr;
  39. }
  40. IPin * pIPin = NULL;
  41. // Enumerate all the pins and break on the
  42. // first pin that meets requirement.
  43. for (;;)
  44. {
  45. if (pIEnumPins->Next(1, &pIPin, &dwFeched) != S_OK)
  46. {
  47. BGLOG((BG_ERROR, "find pin on filter."));
  48. return E_FAIL;
  49. }
  50. if (0 == dwFeched)
  51. {
  52. BGLOG((BG_ERROR, "get 0 pin from filter."));
  53. return E_FAIL;
  54. }
  55. PIN_DIRECTION dir;
  56. if (FAILED(hr = pIPin->QueryDirection(&dir)))
  57. {
  58. BGLOG((BG_ERROR, "query pin direction. %x", hr));
  59. pIPin->Release();
  60. return hr;
  61. }
  62. if (direction == dir)
  63. {
  64. if (!bFree)
  65. {
  66. break;
  67. }
  68. // Check to see if the pin is free.
  69. CComPtr<IPin> pIPinConnected;
  70. hr = pIPin->ConnectedTo(&pIPinConnected);
  71. if (pIPinConnected == NULL)
  72. {
  73. break;
  74. }
  75. }
  76. pIPin->Release();
  77. }
  78. *ppIPin = pIPin;
  79. return S_OK;
  80. }
  81. CIPConfBaseTerminal::CIPConfBaseTerminal(
  82. const GUID & ClassID,
  83. TERMINAL_DIRECTION TerminalDirection,
  84. TERMINAL_TYPE TerminalType,
  85. DWORD dwMediaType
  86. )
  87. : m_fCritSecValid(FALSE)
  88. , m_TerminalClassID(ClassID)
  89. , m_TerminalDirection(TD_BIDIRECTIONAL)
  90. , m_TerminalType(TerminalType)
  91. , m_TerminalState(TS_NOTINUSE)
  92. , m_dwMediaType(dwMediaType)
  93. , m_pFTM(NULL)
  94. , m_htAddress(NULL)
  95. {
  96. BGLOG((BG_TRACE, "CIPConfBaseTerminal::CIPConfBaseTerminal() called"));
  97. m_szName[0] = TEXT('\0');
  98. }
  99. HRESULT CIPConfBaseTerminal::FinalConstruct()
  100. /*++
  101. Routine Description:
  102. Finish the initialization of the object. If anything fails, this object
  103. will be deleted.
  104. Arguments:
  105. nothing.
  106. Return Value:
  107. S_OK
  108. E_OUTOFMEMORY
  109. --*/
  110. {
  111. ENTER_FUNCTION("CIPConfBaseTerminal::FinalConstruct");
  112. BGLOG((BG_TRACE, "%s entered", __fxName));
  113. m_fCritSecValid = TRUE;
  114. __try
  115. {
  116. InitializeCriticalSection(&m_CritSec);
  117. }
  118. __except (EXCEPTION_EXECUTE_HANDLER)
  119. {
  120. m_fCritSecValid = FALSE;
  121. }
  122. if (!m_fCritSecValid)
  123. {
  124. BGLOG((BG_ERROR, "%s init critical section failed", __fxName));
  125. return E_OUTOFMEMORY;
  126. }
  127. HRESULT hr = CoCreateFreeThreadedMarshaler(
  128. GetControllingUnknown(), &m_pFTM
  129. );
  130. if ( FAILED(hr) )
  131. {
  132. BGLOG((BG_ERROR, "%s create ftm failed, hr=%x", __fxName, hr));
  133. return hr;
  134. }
  135. return S_OK;
  136. }
  137. CIPConfBaseTerminal::~CIPConfBaseTerminal()
  138. /*++
  139. Routine Description:
  140. This is the destructor of the base terminal.
  141. Arguments:
  142. Return Value:
  143. S_OK
  144. --*/
  145. {
  146. if (m_pFTM)
  147. {
  148. m_pFTM->Release();
  149. }
  150. if (m_fCritSecValid)
  151. {
  152. DeleteCriticalSection(&m_CritSec);
  153. }
  154. BGLOG((BG_TRACE,
  155. "CIPConfBaseTerminal::~CIPConfBaseTerminal() for %ws finished", m_szName));
  156. }
  157. HRESULT CIPConfBaseTerminal::Initialize(
  158. IN WCHAR * strName,
  159. IN MSP_HANDLE htAddress,
  160. IN DWORD dwMediaType
  161. )
  162. /*++
  163. Routine Description:
  164. This function sets the name and the address handle on the terminal.
  165. Arguments:
  166. strName - The name of the terminal.
  167. htAddress - The handle that identifies the address object that this
  168. terminal belongs to.
  169. Return Value:
  170. S_OK
  171. --*/
  172. {
  173. ENTER_FUNCTION("CIPConfBaseTerminal::Initialize");
  174. BGLOG((BG_TRACE, "%s entered", __fxName));
  175. m_htAddress = htAddress;
  176. lstrcpynW(m_szName, strName, MAX_PATH);
  177. m_dwMediaType = dwMediaType;
  178. BGLOG((BG_TRACE, "%s - exit S_OK", __fxName));
  179. return S_OK;
  180. }
  181. STDMETHODIMP CIPConfBaseTerminal::get_Name(
  182. BSTR * pbsName
  183. )
  184. /*++
  185. Routine Description:
  186. This function return the name of the terminal.
  187. Arguments:
  188. pbsName - A pointer to a BSTR to receive the terminal name.
  189. Return Value:
  190. E_POINTER
  191. E_OUTOFMEMORY
  192. S_OK
  193. --*/
  194. {
  195. ENTER_FUNCTION("CIPConfBaseTerminal::get_Name");
  196. if ( IsBadWritePtr( pbsName, sizeof(BSTR) ) )
  197. {
  198. BGLOG((BG_ERROR, "%s, bad pointer", __fxName));
  199. return E_POINTER;
  200. }
  201. *pbsName = SysAllocString(m_szName);
  202. if ( *pbsName == NULL )
  203. {
  204. BGLOG((BG_ERROR, "%s, out of memory for name", __fxName));
  205. return E_OUTOFMEMORY;
  206. }
  207. return S_OK;
  208. }
  209. STDMETHODIMP CIPConfBaseTerminal::get_State(
  210. TERMINAL_STATE * pVal
  211. )
  212. /*++
  213. Routine Description:
  214. This function return the state of the terminal.
  215. Arguments:
  216. pVal - A pointer to a variable of type TERMINAL_STATE.
  217. Return Value:
  218. E_POINTER
  219. S_OK
  220. --*/
  221. {
  222. ENTER_FUNCTION("CIPConfBaseTerminal::get_State");
  223. if ( IsBadWritePtr( pVal, sizeof(TERMINAL_STATE) ) )
  224. {
  225. BGLOG((BG_ERROR, "%s, bad pointer", __fxName));
  226. return E_POINTER;
  227. }
  228. *pVal = m_TerminalState;
  229. return S_OK;
  230. }
  231. STDMETHODIMP CIPConfBaseTerminal::get_TerminalType(
  232. TERMINAL_TYPE * pVal
  233. )
  234. /*++
  235. Routine Description:
  236. This function return the type of the terminal.
  237. Arguments:
  238. pVal - A pointer to a variable of type TERMINAL_TYPE.
  239. Return Value:
  240. E_POINTER
  241. S_OK
  242. --*/
  243. {
  244. ENTER_FUNCTION("CIPConfBaseTerminal::get_TerminalType");
  245. if ( IsBadWritePtr( pVal, sizeof(TERMINAL_TYPE) ) )
  246. {
  247. BGLOG((BG_ERROR, "%s, bad pointer", __fxName));
  248. return E_POINTER;
  249. }
  250. *pVal = m_TerminalType;
  251. return S_OK;
  252. }
  253. STDMETHODIMP CIPConfBaseTerminal::get_TerminalClass(
  254. BSTR * pbsClassID
  255. )
  256. /*++
  257. Routine Description:
  258. This function return the class of the terminal.
  259. Arguments:
  260. pbsClassID - A pointer to a BSTR to receive the classID as a string.
  261. Return Value:
  262. E_POINTER
  263. E_OUTOFMEMORY
  264. S_OK
  265. --*/
  266. {
  267. ENTER_FUNCTION("CIPConfBaseTerminal::get_TerminalClass");
  268. if ( IsBadWritePtr( pbsClassID, sizeof(BSTR) ) )
  269. {
  270. BGLOG((BG_ERROR, "%s, bad pointer", __fxName));
  271. return E_POINTER;
  272. }
  273. // Convert the CLSID to an string.
  274. WCHAR *pszName = NULL;
  275. HRESULT hr = ::StringFromCLSID(m_TerminalClassID, &pszName);
  276. if (FAILED(hr))
  277. {
  278. BGLOG((BG_ERROR, "%s, failed to convert GUID, hr = %x", __fxName, hr));
  279. return hr;
  280. }
  281. // Put the string in a BSTR.
  282. BSTR bClassID = ::SysAllocString(pszName);
  283. // Free the OLE string.
  284. ::CoTaskMemFree(pszName);
  285. if (bClassID == NULL)
  286. {
  287. BGLOG((BG_ERROR, "%s, out of mem for class ID", __fxName));
  288. return E_OUTOFMEMORY;
  289. }
  290. *pbsClassID = bClassID;
  291. return S_OK;
  292. }
  293. STDMETHODIMP CIPConfBaseTerminal::get_Direction(
  294. OUT TERMINAL_DIRECTION *pDirection
  295. )
  296. /*++
  297. Routine Description:
  298. This function return the direction of the terminal.
  299. Arguments:
  300. pDirection - A pointer to a variable of type TERMINAL_DIRECTION
  301. Return Value:
  302. E_POINTER
  303. S_OK
  304. --*/
  305. {
  306. ENTER_FUNCTION("CIPConfBaseTerminal::get_Direction");
  307. if ( IsBadWritePtr( pDirection, sizeof(TERMINAL_DIRECTION) ) )
  308. {
  309. BGLOG((BG_ERROR, "%s, bad pointer", __fxName));
  310. return E_POINTER;
  311. }
  312. *pDirection = m_TerminalDirection;
  313. return S_OK;
  314. }
  315. STDMETHODIMP CIPConfBaseTerminal::get_MediaType(
  316. long * plMediaType
  317. )
  318. /*++
  319. Routine Description:
  320. This function return the media type of the terminal.
  321. Arguments:
  322. plMediaType - A pointer to a variable of type long
  323. Return Value:
  324. E_POINTER
  325. S_OK
  326. --*/
  327. {
  328. ENTER_FUNCTION("CIPConfBaseTerminal::get_MediaType");
  329. if ( IsBadWritePtr(plMediaType, sizeof(long) ) )
  330. {
  331. BGLOG((BG_ERROR, "%s, bad pointer", __fxName));
  332. return E_POINTER;
  333. }
  334. *plMediaType = (long) m_dwMediaType;
  335. return S_OK;
  336. }
  337. STDMETHODIMP CIPConfBaseTerminal::get_AddressHandle(
  338. OUT MSP_HANDLE * phtAddress
  339. )
  340. /*++
  341. Routine Description:
  342. This function return the handle of the address that created this terminal.
  343. Arguments:
  344. phtAddress - A pointer to a variable of type MSP_HANDLE
  345. Return Value:
  346. E_POINTER
  347. S_OK
  348. --*/
  349. {
  350. // this function is only called from the MSP, so only assert here.
  351. _ASSERT(!IsBadWritePtr(phtAddress, sizeof(MSP_HANDLE)));
  352. *phtAddress = m_htAddress;
  353. return S_OK;
  354. }
  355. STDMETHODIMP
  356. CIPConfBaseTerminal::CompleteConnectTerminal(void)
  357. /*++
  358. Routine Description:
  359. This function is called after a successful ConnectTerminal so that the
  360. terminal can do post-connection intitialization.
  361. Arguments:
  362. nothing
  363. Return Value:
  364. S_OK
  365. --*/
  366. {
  367. return S_OK;
  368. }
  369. STDMETHODIMP CIPConfBaseTerminal::RunRenderFilter(void)
  370. /*++
  371. Routine Description:
  372. start the rightmost render filter in the terminal
  373. (needed for dynamic filter graphs)
  374. Arguments:
  375. Return Value:
  376. E_NOTIMPL
  377. --*/
  378. {
  379. return E_NOTIMPL;
  380. }
  381. STDMETHODIMP CIPConfBaseTerminal::StopRenderFilter(void)
  382. /*++
  383. Routine Description:
  384. stops the rightmost render filter in the terminal
  385. (needed for dynamic filter graphs)
  386. Arguments:
  387. Return Value:
  388. E_NOTIMPL
  389. --*/
  390. {
  391. return E_NOTIMPL;
  392. }
  393. CIPConfBridgeTerminal::CIPConfBridgeTerminal()
  394. : CIPConfBaseTerminal(
  395. __uuidof(IPConfBridgeTerminal),
  396. (TD_CAPTURE),
  397. TT_DYNAMIC,
  398. 0)
  399. , m_pUpStreamGraph(NULL)
  400. , m_pSinkFilter(NULL)
  401. , m_pSinkInputPin(NULL)
  402. , m_pDownStreamGraph(NULL)
  403. , m_pSourceFilter(NULL)
  404. , m_pSourceOutputPin(NULL)
  405. {
  406. BGLOG((BG_TRACE, "CIPConfBridgeTerminal::CIPConfBaseTerminal() called"));
  407. }
  408. CIPConfBridgeTerminal::~CIPConfBridgeTerminal()
  409. /*++
  410. Routine Description:
  411. This is the destructor of the bridge terminal.
  412. Arguments:
  413. Return Value:
  414. S_OK
  415. --*/
  416. {
  417. if (m_pUpStreamGraph)
  418. {
  419. m_pUpStreamGraph->Release();
  420. }
  421. if (m_pSinkFilter)
  422. {
  423. m_pSinkFilter->Release();
  424. }
  425. if (m_pSinkInputPin)
  426. {
  427. m_pSinkInputPin->Release();
  428. }
  429. if (m_pDownStreamGraph)
  430. {
  431. m_pDownStreamGraph->Release();
  432. }
  433. if (m_pSourceFilter)
  434. {
  435. m_pSourceFilter->Release();
  436. }
  437. if (m_pSourceOutputPin)
  438. {
  439. m_pSourceOutputPin->Release();
  440. }
  441. BGLOG((BG_TRACE,
  442. "CIPConfBridgeTerminal::~CIPConfBridgeTerminal() for %ws finished", m_szName));
  443. }
  444. HRESULT CIPConfBridgeTerminal::CreateTerminal(
  445. IN DWORD dwMediaType,
  446. IN MSP_HANDLE htAddress,
  447. OUT ITTerminal **ppTerm
  448. )
  449. /*++
  450. Routine Description:
  451. This method creates a bridge terminal
  452. Arguments:
  453. dwMediaType - The media type of this terminal.
  454. htAddress - the handle to the address object.
  455. ppTerm - memory to store the returned terminal pointer.
  456. Return Value:
  457. S_OK
  458. E_POINTER
  459. --*/
  460. {
  461. ENTER_FUNCTION("CIPConfBridgeTerminal::CreateTerminal");
  462. BGLOG((BG_TRACE, "%s, htAddress:%x", __fxName, htAddress));
  463. _ASSERT(!IsBadWritePtr(ppTerm, sizeof(ITTerminal *)));
  464. HRESULT hr;
  465. //
  466. // Create the terminal.
  467. //
  468. CMSPComObject<CIPConfBridgeTerminal> *pTerminal = NULL;
  469. hr = CMSPComObject<CIPConfBridgeTerminal>::CreateInstance(&pTerminal);
  470. if (FAILED(hr))
  471. {
  472. BGLOG((BG_ERROR,
  473. "%s can't create the terminal object hr = %8x", __fxName, hr));
  474. return hr;
  475. }
  476. // query for the ITTerminal interface
  477. ITTerminal *pITTerminal;
  478. hr = pTerminal->_InternalQueryInterface(__uuidof(ITTerminal), (void**)&pITTerminal);
  479. if (FAILED(hr))
  480. {
  481. BGLOG((BG_ERROR,
  482. "%s, query terminal interface failed, %x", __fxName, hr));
  483. delete pTerminal;
  484. return hr;
  485. }
  486. // initialize the terminal
  487. hr = pTerminal->Initialize(
  488. dwMediaType,
  489. htAddress
  490. );
  491. if ( FAILED(hr) )
  492. {
  493. BGLOG((BG_ERROR,
  494. "%s, Initialize failed; returning 0x%08x", __fxName, hr));
  495. pITTerminal->Release();
  496. return hr;
  497. }
  498. BGLOG((BG_TRACE, "%s, Bridge erminal %p created", __fxName, pITTerminal));
  499. *ppTerm = pITTerminal;
  500. return S_OK;
  501. }
  502. // max length of a bridge terminal name
  503. #define MAX_BGTMNAME 80
  504. HRESULT CIPConfBridgeTerminal::Initialize(
  505. IN DWORD dwMediaType,
  506. IN MSP_HANDLE htAddress
  507. )
  508. {
  509. WCHAR pszTerminalName[MAX_BGTMNAME];
  510. int len;
  511. if (dwMediaType == TAPIMEDIATYPE_AUDIO)
  512. {
  513. len = LoadString (
  514. _Module.GetResourceInstance (),
  515. IDS_AUDBGNAME,
  516. pszTerminalName,
  517. MAX_BGTMNAME
  518. );
  519. }
  520. else if (dwMediaType == TAPIMEDIATYPE_VIDEO)
  521. {
  522. len = LoadString (
  523. _Module.GetResourceInstance (),
  524. IDS_VIDBGNAME,
  525. pszTerminalName,
  526. MAX_BGTMNAME
  527. );
  528. }
  529. else
  530. {
  531. LOG ((BG_ERROR, "CIPConfBridgeTerminal::Initialize receives unknown media type %d", dwMediaType));
  532. return E_INVALIDARG;
  533. }
  534. if (len == 0)
  535. {
  536. LOG ((BG_ERROR, "Failed to load bridge terminal name, media %d, err %d",
  537. dwMediaType, GetLastError ()));
  538. return E_UNEXPECTED;
  539. }
  540. return CIPConfBaseTerminal::Initialize(
  541. pszTerminalName, htAddress, dwMediaType
  542. );
  543. }
  544. HRESULT CIPConfBridgeTerminal::CreateFilters()
  545. /*++
  546. Routine Description:
  547. Create the two filters used in the terminal.
  548. Arguments:
  549. Return Value:
  550. HRESULT
  551. --*/
  552. {
  553. ENTER_FUNCTION("CIPConfBridgeTerminal::CreateFilters");
  554. BGLOG((BG_TRACE, "%s entered", __fxName));
  555. HRESULT hr;
  556. // Create the source filter.
  557. CComPtr <IBaseFilter> pSourceFilter;
  558. if (m_dwMediaType == TAPIMEDIATYPE_AUDIO)
  559. {
  560. hr = CTAPIAudioBridgeSourceFilter::CreateInstance(&pSourceFilter);
  561. }
  562. else
  563. {
  564. hr = CTAPIVideoBridgeSourceFilter::CreateInstance(&pSourceFilter);
  565. }
  566. if (FAILED(hr))
  567. {
  568. BGLOG((BG_ERROR, "%s, Create source filter failed. hr=%x", __fxName, hr));
  569. return hr;
  570. }
  571. CComPtr <IDataBridge> pIDataBridge;
  572. hr = pSourceFilter->QueryInterface(&pIDataBridge);
  573. // this should never fail.
  574. _ASSERT(SUCCEEDED(hr));
  575. // Create the sink filter.
  576. CComPtr <IBaseFilter> pSinkFilter;
  577. if (m_dwMediaType == TAPIMEDIATYPE_AUDIO)
  578. {
  579. hr = CTAPIAudioBridgeSinkFilter::CreateInstance(pIDataBridge, &pSinkFilter);
  580. }
  581. else
  582. {
  583. hr = CTAPIVideoBridgeSinkFilter::CreateInstance(pIDataBridge, &pSinkFilter);
  584. }
  585. if (FAILED(hr))
  586. {
  587. BGLOG((BG_ERROR, "%s, Create sink filter failed. hr=%x", __fxName, hr));
  588. return hr;
  589. }
  590. // Find the pins.
  591. CComPtr<IPin> pIPinOutput;
  592. if (FAILED(hr = ::FindPin(pSourceFilter, &pIPinOutput, PINDIR_OUTPUT)))
  593. {
  594. BGLOG((BG_ERROR, "%s, find output pin on sink filter. hr=%x", __fxName, hr));
  595. return hr;
  596. }
  597. CComPtr<IPin> pIPinInput;
  598. if (FAILED(hr = ::FindPin(pSinkFilter, &pIPinInput, PINDIR_INPUT)))
  599. {
  600. BGLOG((BG_ERROR, "%s, find input pin on sink filter. hr=%x", __fxName, hr));
  601. return hr;
  602. }
  603. // save the reference.
  604. m_pSinkFilter = pSinkFilter;
  605. m_pSinkFilter->AddRef();
  606. m_pSinkInputPin = pIPinInput;
  607. m_pSinkInputPin->AddRef();
  608. m_pSourceFilter = pSourceFilter;
  609. m_pSourceFilter->AddRef();
  610. m_pSourceOutputPin = pIPinOutput;
  611. m_pSourceOutputPin->AddRef();
  612. return S_OK;
  613. }
  614. HRESULT CIPConfBridgeTerminal::AddFilter(
  615. IN FILTER_TYPE FilterType,
  616. IN IGraphBuilder * pGraph,
  617. OUT IPin ** ppPins
  618. )
  619. /*++
  620. Routine Description:
  621. Add a filter into the graph provided by the stream and returning the pin
  622. that can be connected at the same time.
  623. Arguments:
  624. FilterType - the type of the filter. Either the source or the sink.
  625. pGraph - The filter graph.
  626. ppPins - A pointer to the buffer that can store the IPin pointer.
  627. Return Value:
  628. S_OK
  629. TAPI_E_TERMINALINUSE - the terminal is in use.
  630. --*/
  631. {
  632. ENTER_FUNCTION("CIPConfBridgeTerminal::AddSourceFilter");
  633. BGLOG((BG_TRACE, "%s entered", __fxName));
  634. // check to see if the terminal is already in use.
  635. if ((FilterType == SINK) && (m_pUpStreamGraph != NULL)
  636. || (FilterType == SOURCE) && (m_pDownStreamGraph != NULL))
  637. {
  638. BGLOG((BG_ERROR, "%s, terminal already in use", __fxName));
  639. return TAPI_E_TERMINALINUSE;
  640. }
  641. HRESULT hr;
  642. if (m_pSourceFilter == NULL)
  643. {
  644. // the filters have not been created, create them now.
  645. hr = CreateFilters();
  646. if (FAILED(hr))
  647. {
  648. BGLOG((BG_ERROR, "%s, can't Create filter, hr=%x", __fxName, hr));
  649. return hr;
  650. }
  651. }
  652. IBaseFilter *pFilter;
  653. IPin *pPin;
  654. if (FilterType == SINK)
  655. {
  656. pFilter = m_pSinkFilter;
  657. pPin = m_pSinkInputPin;
  658. m_pUpStreamGraph = pGraph;
  659. m_pUpStreamGraph->AddRef();
  660. }
  661. else
  662. {
  663. pFilter = m_pSourceFilter;
  664. pPin = m_pSourceOutputPin;
  665. m_pDownStreamGraph = pGraph;
  666. m_pDownStreamGraph->AddRef();
  667. }
  668. // add the filter to the graph.
  669. hr = pGraph->AddFilter(pFilter, NULL);
  670. if ( FAILED(hr) )
  671. {
  672. BGLOG((BG_ERROR, "%s, can't add filter to the graph hr=%x", __fxName, hr));
  673. return hr;
  674. }
  675. pPin->AddRef();
  676. *ppPins = pPin;
  677. return S_OK;
  678. }
  679. STDMETHODIMP CIPConfBridgeTerminal::ConnectTerminal(
  680. IN IGraphBuilder * pGraph,
  681. IN DWORD dwReserved,
  682. IN OUT DWORD * pdwNumPins,
  683. OUT IPin ** ppPins
  684. )
  685. /*++
  686. Routine Description:
  687. This function is called by the MSP while trying to connect the filter in
  688. the terminal to the rest of the graph in the MSP. It adds the filter into
  689. the graph and returns the pins can be used by the MSP.
  690. Arguments:
  691. pGraph - The filter graph.
  692. dwReserved - the direction for the connection.
  693. pdwNumPins - The maxinum number of pins the msp wants.
  694. ppPins - A pointer to the buffer that can store the IPin pointers. If it
  695. is NULL, only the actual number of pins will be returned.
  696. Return Value:
  697. S_OK
  698. TAPI_E_NOTENOUGHMEMORY - the buffer is too small.
  699. TAPI_E_TERMINALINUSE - the terminal is in use.
  700. --*/
  701. {
  702. ENTER_FUNCTION("CIPConfBridgeTerminal::ConnectTerminal");
  703. BGLOG((BG_TRACE,
  704. "%s entered, pGraph:%p, dwREserved:%p", __fxName, pGraph, dwReserved));
  705. // this function is only called from the MSP, so only assert here.
  706. _ASSERT(!IsBadReadPtr(pGraph, sizeof(IGraphBuilder)));
  707. _ASSERT(!IsBadWritePtr(pdwNumPins, sizeof(DWORD)));
  708. // there is only one pin on each side of the bridge.
  709. const DWORD dwNumOfPins = 1;
  710. //
  711. // If ppPins is NULL, just return the number of pins and don't try to
  712. // connect the terminal.
  713. //
  714. if ( ppPins == NULL )
  715. {
  716. BGLOG((BG_TRACE,
  717. "%s number of exposed pins:%d", __fxName, dwNumOfPins));
  718. *pdwNumPins = dwNumOfPins;
  719. return S_OK;
  720. }
  721. //
  722. // Otherwise, we have a pin return buffer. Check that the purported buffer
  723. // size is big enough and that the buffer is actually writable to the size
  724. // we need.
  725. //
  726. if ( *pdwNumPins < dwNumOfPins )
  727. {
  728. BGLOG((BG_ERROR, "%s not enough space to place pins.", __fxName));
  729. *pdwNumPins = dwNumOfPins;
  730. return TAPI_E_NOTENOUGHMEMORY;
  731. }
  732. _ASSERT(!IsBadWritePtr(ppPins, dwNumOfPins * sizeof(IPin *)));
  733. Lock();
  734. HRESULT hr;
  735. hr = AddFilter((dwReserved == TD_CAPTURE) ? SOURCE : SINK, pGraph, ppPins);
  736. if (FAILED(hr))
  737. {
  738. BGLOG((BG_ERROR, "%s, AddFilter failed", __fxName));
  739. }
  740. else
  741. {
  742. m_TerminalState = TS_INUSE;
  743. *pdwNumPins = 1;
  744. }
  745. Unlock();
  746. BGLOG((BG_TRACE, "CIPConfBridgeTerminal::ConnectTerminal success"));
  747. return hr;
  748. }
  749. STDMETHODIMP
  750. CIPConfBridgeTerminal::DisconnectTerminal(
  751. IN IGraphBuilder * pGraph,
  752. IN DWORD dwReserved
  753. )
  754. /*++
  755. Routine Description:
  756. This function is called by the MSP while trying to disconnect the filter in
  757. the terminal from the rest of the graph in the MSP. It adds the removes the
  758. filter from the graph and set the terminal free.
  759. Arguments:
  760. pGraph - The filter graph. It is used for validation, to make sure the
  761. terminal is disconnected from the same graph that it was
  762. originally connected to.
  763. dwReserved - A reserved dword.
  764. Return Value:
  765. S_OK
  766. E_INVALIDARG - wrong graph.
  767. --*/
  768. {
  769. ENTER_FUNCTION("CIPConfBridgeTerminal::DisconnectTerminal");
  770. BGLOG((BG_TRACE,
  771. "%s entered, pGraph:%p, dwReserved:%d", __fxName, pGraph, dwReserved));
  772. if (pGraph == NULL)
  773. {
  774. BGLOG((BG_TRACE, "%s, bad graph pointer:%p", __fxName, pGraph));
  775. return E_INVALIDARG;
  776. }
  777. Lock();
  778. HRESULT hr;
  779. if (pGraph == m_pUpStreamGraph)
  780. {
  781. hr = pGraph->RemoveFilter(m_pSinkFilter);
  782. m_pUpStreamGraph->Release();
  783. m_pUpStreamGraph = NULL;
  784. }
  785. else if (pGraph == m_pDownStreamGraph)
  786. {
  787. hr = pGraph->RemoveFilter(m_pSourceFilter);
  788. m_pDownStreamGraph->Release();
  789. m_pDownStreamGraph = NULL;
  790. }
  791. else
  792. {
  793. BGLOG((BG_TRACE, "%s, wrong graph pointer:%p", __fxName, pGraph));
  794. Unlock();
  795. return E_INVALIDARG;
  796. }
  797. if ( FAILED(hr) )
  798. {
  799. BGLOG((BG_ERROR,
  800. "%s, remove filter from graph failed; returning hr=%x",
  801. __fxName, hr));
  802. }
  803. m_TerminalState = TS_NOTINUSE;
  804. Unlock();
  805. BGLOG((BG_TRACE, "%s succeeded", __fxName));
  806. return hr;
  807. }