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.

819 lines
17 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. mspterm.cpp
  5. Abstract:
  6. Implementations for the CIPConfBaseTerminal, CSingleFilterTerminal, and various
  7. work item / worker thread classes.
  8. Author:
  9. Zoltan Szilagyi (zoltans) September 6,1998
  10. --*/
  11. #include "stdafx.h"
  12. CIPConfBaseTerminal::CIPConfBaseTerminal()
  13. : m_fCritSecValid(FALSE)
  14. , m_TerminalClassID(GUID_NULL)
  15. , m_TerminalDirection(TD_CAPTURE)
  16. , m_TerminalType(TT_STATIC)
  17. , m_TerminalState(TS_NOTINUSE)
  18. , m_dwMediaType(0)
  19. , m_pFTM(NULL)
  20. , m_htAddress(NULL)
  21. , m_pGraph(NULL)
  22. , m_pFilter(NULL)
  23. {
  24. LOG((MSP_TRACE, "CIPConfBaseTerminal::CIPConfBaseTerminal() called"));
  25. m_szName[0] = '\0';
  26. }
  27. HRESULT CIPConfBaseTerminal::FinalConstruct()
  28. /*++
  29. Routine Description:
  30. Finish the initialization of the object. If anything fails, this object
  31. will be deleted.
  32. Arguments:
  33. nothing.
  34. Return Value:
  35. S_OK
  36. E_OUTOFMEMORY
  37. --*/
  38. {
  39. ENTER_FUNCTION("CIPConfBaseTerminal::FinalConstruct");
  40. LOG((MSP_TRACE, "%s entered", __fxName));
  41. m_fCritSecValid = TRUE;
  42. __try
  43. {
  44. InitializeCriticalSection(&m_CritSec);
  45. }
  46. __except (EXCEPTION_EXECUTE_HANDLER)
  47. {
  48. m_fCritSecValid = FALSE;
  49. }
  50. if (!m_fCritSecValid)
  51. {
  52. LOG((MSP_ERROR, "%s init critical section failed", __fxName));
  53. return E_OUTOFMEMORY;
  54. }
  55. HRESULT hr = CoCreateFreeThreadedMarshaler(
  56. GetControllingUnknown(), &m_pFTM
  57. );
  58. if ( FAILED(hr) )
  59. {
  60. LOG((MSP_ERROR, "%s create ftm failed, hr=%x", __fxName, hr));
  61. return hr;
  62. }
  63. return S_OK;
  64. }
  65. CIPConfBaseTerminal::~CIPConfBaseTerminal()
  66. /*++
  67. Routine Description:
  68. This is the destructor of the base terminal.
  69. Arguments:
  70. Return Value:
  71. S_OK
  72. --*/
  73. {
  74. if (m_pGraph)
  75. {
  76. m_pGraph->Release();
  77. }
  78. if (m_pFilter)
  79. {
  80. m_pFilter->Release();
  81. }
  82. if (m_pFTM)
  83. {
  84. m_pFTM->Release();
  85. }
  86. if (m_fCritSecValid)
  87. {
  88. DeleteCriticalSection(&m_CritSec);
  89. }
  90. LOG((MSP_TRACE,
  91. "CIPConfBaseTerminal::~CIPConfBaseTerminal() for %ws finished", m_szName));
  92. }
  93. HRESULT CIPConfBaseTerminal::Initialize(
  94. IN WCHAR * strName,
  95. IN MSP_HANDLE htAddress
  96. )
  97. /*++
  98. Routine Description:
  99. This function sets the name and the address handle on the terminal.
  100. Arguments:
  101. strName - The name of the terminal.
  102. htAddress - The handle that identifies the address object that this
  103. terminal belongs to.
  104. Return Value:
  105. S_OK
  106. --*/
  107. {
  108. ENTER_FUNCTION("CIPConfBaseTerminal::Initialize");
  109. LOG((MSP_TRACE, "%s entered", __fxName));
  110. m_htAddress = htAddress;
  111. lstrcpynW(m_szName, strName, MAX_PATH);
  112. LOG((MSP_TRACE, "%s - exit S_OK", __fxName));
  113. return S_OK;
  114. }
  115. HRESULT CIPConfBaseTerminal::Initialize(
  116. IN char * strName,
  117. IN MSP_HANDLE htAddress
  118. )
  119. /*++
  120. Routine Description:
  121. This function sets the name and the address handle on the terminal. This
  122. function takes ascii string name.
  123. Arguments:
  124. strName - The name of the terminal.
  125. htAddress - The handle that identifies the address object that this
  126. terminal belongs to.
  127. Return Value:
  128. S_OK
  129. --*/
  130. {
  131. ENTER_FUNCTION("CIPConfBaseTerminal::Initialize");
  132. LOG((MSP_TRACE, "%s entered", __fxName));
  133. m_htAddress = htAddress;
  134. MultiByteToWideChar(
  135. GetACP(),
  136. 0,
  137. strName,
  138. lstrlenA(strName)+1,
  139. m_szName,
  140. MAX_PATH
  141. );
  142. LOG((MSP_TRACE, "%s - exit S_OK", __fxName));
  143. return S_OK;
  144. }
  145. STDMETHODIMP CIPConfBaseTerminal::get_Name(
  146. BSTR * pbsName
  147. )
  148. /*++
  149. Routine Description:
  150. This function return the name of the terminal.
  151. Arguments:
  152. pbsName - A pointer to a BSTR to receive the terminal name.
  153. Return Value:
  154. E_POINTER
  155. E_OUTOFMEMORY
  156. S_OK
  157. --*/
  158. {
  159. ENTER_FUNCTION("CIPConfBaseTerminal::get_Name");
  160. if ( IsBadWritePtr( pbsName, sizeof(BSTR) ) )
  161. {
  162. LOG((MSP_ERROR, "%s, bad pointer", __fxName));
  163. return E_POINTER;
  164. }
  165. *pbsName = SysAllocString(m_szName);
  166. if ( *pbsName == NULL )
  167. {
  168. LOG((MSP_ERROR, "%s, out of memory for name", __fxName));
  169. return E_OUTOFMEMORY;
  170. }
  171. return S_OK;
  172. }
  173. STDMETHODIMP CIPConfBaseTerminal::get_State(
  174. TERMINAL_STATE * pVal
  175. )
  176. /*++
  177. Routine Description:
  178. This function return the state of the terminal.
  179. Arguments:
  180. pVal - A pointer to a variable of type TERMINAL_STATE.
  181. Return Value:
  182. E_POINTER
  183. S_OK
  184. --*/
  185. {
  186. ENTER_FUNCTION("CIPConfBaseTerminal::get_State");
  187. if ( IsBadWritePtr( pVal, sizeof(TERMINAL_STATE) ) )
  188. {
  189. LOG((MSP_ERROR, "%s, bad pointer", __fxName));
  190. return E_POINTER;
  191. }
  192. *pVal = m_TerminalState;
  193. return S_OK;
  194. }
  195. STDMETHODIMP CIPConfBaseTerminal::get_TerminalType(
  196. TERMINAL_TYPE * pVal
  197. )
  198. /*++
  199. Routine Description:
  200. This function return the type of the terminal.
  201. Arguments:
  202. pVal - A pointer to a variable of type TERMINAL_TYPE.
  203. Return Value:
  204. E_POINTER
  205. S_OK
  206. --*/
  207. {
  208. ENTER_FUNCTION("CIPConfBaseTerminal::get_TerminalType");
  209. if ( IsBadWritePtr( pVal, sizeof(TERMINAL_TYPE) ) )
  210. {
  211. LOG((MSP_ERROR, "%s, bad pointer", __fxName));
  212. return E_POINTER;
  213. }
  214. *pVal = m_TerminalType;
  215. return S_OK;
  216. }
  217. STDMETHODIMP CIPConfBaseTerminal::get_TerminalClass(
  218. BSTR * pbsClassID
  219. )
  220. /*++
  221. Routine Description:
  222. This function return the class of the terminal.
  223. Arguments:
  224. pbsClassID - A pointer to a BSTR to receive the classID as a string.
  225. Return Value:
  226. E_POINTER
  227. E_OUTOFMEMORY
  228. S_OK
  229. --*/
  230. {
  231. ENTER_FUNCTION("CIPConfBaseTerminal::get_TerminalClass");
  232. if ( IsBadWritePtr( pbsClassID, sizeof(BSTR) ) )
  233. {
  234. LOG((MSP_ERROR, "%s, bad pointer", __fxName));
  235. return E_POINTER;
  236. }
  237. // Convert the CLSID to an string.
  238. WCHAR *pszName = NULL;
  239. HRESULT hr = ::StringFromCLSID(m_TerminalClassID, &pszName);
  240. if (FAILED(hr))
  241. {
  242. LOG((MSP_ERROR, "%s, failed to convert GUID, hr = %x", __fxName, hr));
  243. return hr;
  244. }
  245. // Put the string in a BSTR.
  246. BSTR bClassID = ::SysAllocString(pszName);
  247. // Free the OLE string.
  248. ::CoTaskMemFree(pszName);
  249. if (bClassID == NULL)
  250. {
  251. LOG((MSP_ERROR, "%s, out of mem for class ID", __fxName));
  252. return E_OUTOFMEMORY;
  253. }
  254. *pbsClassID = bClassID;
  255. return S_OK;
  256. }
  257. STDMETHODIMP CIPConfBaseTerminal::get_Direction(
  258. OUT TERMINAL_DIRECTION *pDirection
  259. )
  260. /*++
  261. Routine Description:
  262. This function return the direction of the terminal.
  263. Arguments:
  264. pDirection - A pointer to a variable of type TERMINAL_DIRECTION
  265. Return Value:
  266. E_POINTER
  267. S_OK
  268. --*/
  269. {
  270. ENTER_FUNCTION("CIPConfBaseTerminal::get_TerminalClass");
  271. if ( IsBadWritePtr( pDirection, sizeof(TERMINAL_DIRECTION) ) )
  272. {
  273. LOG((MSP_ERROR, "%s, bad pointer", __fxName));
  274. return E_POINTER;
  275. }
  276. *pDirection = m_TerminalDirection;
  277. return S_OK;
  278. }
  279. STDMETHODIMP CIPConfBaseTerminal::get_MediaType(
  280. long * plMediaType
  281. )
  282. /*++
  283. Routine Description:
  284. This function return the media type of the terminal.
  285. Arguments:
  286. plMediaType - A pointer to a variable of type long
  287. Return Value:
  288. E_POINTER
  289. S_OK
  290. --*/
  291. {
  292. ENTER_FUNCTION("CIPConfBaseTerminal::get_MediaType");
  293. if ( IsBadWritePtr(plMediaType, sizeof(long) ) )
  294. {
  295. LOG((MSP_ERROR, "%s, bad pointer", __fxName));
  296. return E_POINTER;
  297. }
  298. *plMediaType = (long) m_dwMediaType;
  299. return S_OK;
  300. }
  301. STDMETHODIMP CIPConfBaseTerminal::get_AddressHandle(
  302. OUT MSP_HANDLE * phtAddress
  303. )
  304. /*++
  305. Routine Description:
  306. This function return the handle of the address that created this terminal.
  307. Arguments:
  308. phtAddress - A pointer to a variable of type MSP_HANDLE
  309. Return Value:
  310. E_POINTER
  311. S_OK
  312. --*/
  313. {
  314. // this function is only called from the MSP, so only assert here.
  315. _ASSERT(!IsBadWritePtr(phtAddress, sizeof(MSP_HANDLE)));
  316. *phtAddress = m_htAddress;
  317. return S_OK;
  318. }
  319. STDMETHODIMP CIPConfBaseTerminal::ConnectTerminal(
  320. IN IGraphBuilder * pGraph,
  321. IN DWORD dwReserved,
  322. IN OUT DWORD * pdwNumPins,
  323. OUT IPin ** ppPins
  324. )
  325. /*++
  326. Routine Description:
  327. This function is called by the MSP while trying to connect the filter in
  328. the terminal to the rest of the graph in the MSP. It adds the filter into
  329. the graph and returns the pins can be used by the MSP.
  330. Arguments:
  331. pGraph - The filter graph.
  332. dwReserved - A reserved dword.
  333. pdwNumPins - The maxinum number of pins the msp wants.
  334. ppPins - A pointer to the buffer that can store the IPin pointers. If it
  335. is NULL, only the actual number of pins will be returned.
  336. Return Value:
  337. S_OK
  338. TAPI_E_NOTENOUGHMEMORY - the buffer is too small.
  339. TAPI_E_TERMINALINUSE - the terminal is in use.
  340. --*/
  341. {
  342. ENTER_FUNCTION("CIPConfBaseTerminal::ConnectTerminal");
  343. LOG((MSP_TRACE,
  344. "%s entered, pGraph:%p, dwREserved:%p", __fxName, pGraph, dwReserved));
  345. // this function is only called from the MSP, so only assert here.
  346. _ASSERT(!IsBadReadPtr(pGraph, sizeof(IGraphBuilder)));
  347. _ASSERT(!IsBadWritePtr(pdwNumPins, sizeof(DWORD)));
  348. // find the number of exposed pins on the filter.
  349. // This function doesn't fail.
  350. DWORD dwActualNumPins = GetNumExposedPins();
  351. //
  352. // If ppPins is NULL, just return the number of pins and don't try to
  353. // connect the terminal.
  354. //
  355. if ( ppPins == NULL )
  356. {
  357. LOG((MSP_TRACE,
  358. "%s number of exposed pins:%d", __fxName, dwActualNumPins));
  359. *pdwNumPins = dwActualNumPins;
  360. return S_OK;
  361. }
  362. //
  363. // Otherwise, we have a pin return buffer. Check that the purported buffer
  364. // size is big enough and that the buffer is actually writable to the size
  365. // we need.
  366. //
  367. if ( *pdwNumPins < dwActualNumPins )
  368. {
  369. LOG((MSP_ERROR,
  370. "%s not enough space to place pins.", __fxName));
  371. *pdwNumPins = dwActualNumPins;
  372. return TAPI_E_NOTENOUGHMEMORY;
  373. }
  374. if ( IsBadWritePtr(ppPins, dwActualNumPins * sizeof(IPin *) ) )
  375. {
  376. LOG((MSP_ERROR,
  377. "%s, bad pins array pointer; exit E_POINTER", __fxName));
  378. return E_POINTER;
  379. }
  380. //
  381. // Check if we're already connected, and if so, change our state to
  382. // connected. Note that this makes sense for both core static terminals
  383. // and dynamic terminals. Also note that we need to protect this with
  384. // a critical section, but after this we can let go of the lock because
  385. // anyone who subsequently enters the critical section will bail at this
  386. // point.
  387. //
  388. Lock();
  389. //
  390. // check if already connected
  391. //
  392. if (TS_INUSE == m_TerminalState)
  393. {
  394. LOG((MSP_ERROR,
  395. "%s, terminal already in use", __fxName));
  396. Unlock();
  397. return TAPI_E_TERMINALINUSE;
  398. }
  399. IPin * pTerminalPin;
  400. // add filter to the filter graph
  401. HRESULT hr = AddFilterToGraph(pGraph);
  402. if (FAILED(hr))
  403. {
  404. LOG((MSP_ERROR, "%s, can't add filters to graph", __fxName));
  405. Unlock();
  406. return hr;
  407. }
  408. //
  409. // Get the pins that our filter exposes.
  410. //
  411. *pdwNumPins = dwActualNumPins;
  412. hr = GetExposedPins(ppPins, dwActualNumPins);
  413. if ( FAILED(hr) )
  414. {
  415. LOG((MSP_ERROR, "%s, GetExposedPins returned hr=%x", __fxName, hr));
  416. // best effort attempt to disconnect - ignore error code
  417. RemoveFilterFromGraph(pGraph);
  418. Unlock();
  419. return hr;
  420. }
  421. m_pGraph = pGraph;
  422. m_pGraph->AddRef();
  423. m_TerminalState = TS_INUSE;
  424. Unlock();
  425. LOG((MSP_TRACE, "CIPConfBaseTerminal::ConnectTerminal success"));
  426. return hr;
  427. }
  428. STDMETHODIMP
  429. CIPConfBaseTerminal::CompleteConnectTerminal(void)
  430. /*++
  431. Routine Description:
  432. This function is called after a successful ConnectTerminal so that the
  433. terminal can do post-connection intitialization.
  434. Arguments:
  435. nothing
  436. Return Value:
  437. S_OK
  438. --*/
  439. {
  440. return S_OK;
  441. }
  442. STDMETHODIMP
  443. CIPConfBaseTerminal::DisconnectTerminal(
  444. IN IGraphBuilder * pGraph,
  445. IN DWORD dwReserved
  446. )
  447. /*++
  448. Routine Description:
  449. This function is called by the MSP while trying to disconnect the filter in
  450. the terminal from the rest of the graph in the MSP. It adds the removes the
  451. filter from the graph and set the terminal free.
  452. Arguments:
  453. pGraph - The filter graph. It is used for validation, to make sure the
  454. terminal is disconnected from the same graph that it was
  455. originally connected to.
  456. dwReserved - A reserved dword.
  457. Return Value:
  458. S_OK
  459. E_INVALIDARG - wrong graph.
  460. --*/
  461. {
  462. ENTER_FUNCTION("CIPConfBaseTerminal::DisconnectTerminal");
  463. LOG((MSP_TRACE,
  464. "%s entered, pGraph:%p, dwReserved:%d", __fxName, pGraph, dwReserved));
  465. Lock();
  466. //
  467. // If not in use, then there is nothing to be done.
  468. //
  469. if ( TS_INUSE != m_TerminalState )
  470. {
  471. _ASSERTE(m_pGraph == NULL);
  472. LOG((MSP_TRACE, "%s, success; not in use", __fxName));
  473. Unlock();
  474. return S_OK;
  475. }
  476. //
  477. // Check that we are being disconnected from the correct graph.
  478. //
  479. if (pGraph == NULL || m_pGraph != pGraph )
  480. {
  481. LOG((MSP_TRACE, "%s, wrong graph:%p", __fxName, pGraph));
  482. Unlock();
  483. return E_INVALIDARG;
  484. }
  485. HRESULT hr = S_OK;
  486. //
  487. // Remove filter from the graph, release our reference to the graph,
  488. // and set ourselves to notinuse state
  489. //
  490. hr = RemoveFilterFromGraph(m_pGraph);
  491. m_pGraph->Release();
  492. m_pGraph = NULL;
  493. m_TerminalState = TS_NOTINUSE;
  494. Unlock();
  495. if ( FAILED(hr) )
  496. {
  497. LOG((MSP_ERROR,
  498. "%s, remove filters from graph failed; returning 0x%08x",
  499. __fxName, hr));
  500. }
  501. else
  502. {
  503. LOG((MSP_TRACE, "%s succeeded", __fxName));
  504. }
  505. return hr;
  506. }
  507. STDMETHODIMP CIPConfBaseTerminal::RunRenderFilter(void)
  508. /*++
  509. Routine Description:
  510. start the rightmost render filter in the terminal
  511. (needed for dynamic filter graphs)
  512. Arguments:
  513. Return Value:
  514. E_NOTIMPL
  515. --*/
  516. {
  517. return E_NOTIMPL;
  518. }
  519. STDMETHODIMP CIPConfBaseTerminal::StopRenderFilter(void)
  520. /*++
  521. Routine Description:
  522. stops the rightmost render filter in the terminal
  523. (needed for dynamic filter graphs)
  524. Arguments:
  525. Return Value:
  526. E_NOTIMPL
  527. --*/
  528. {
  529. return E_NOTIMPL;
  530. }
  531. HRESULT CIPConfBaseTerminal::AddFilterToGraph(
  532. IN IGraphBuilder *pGraph
  533. )
  534. /*++
  535. Routine Description:
  536. Add the internal filter into a graph.
  537. Arguments:
  538. pGraph - the filter graph to add the filter to.
  539. Return Value:
  540. HRESULT
  541. --*/
  542. {
  543. ENTER_FUNCTION("CIPConfBaseTerminal::AddFilterToGraph");
  544. LOG((MSP_TRACE, "%s entered, pGraph:%p", __fxName, pGraph));
  545. HRESULT hr;
  546. if (m_pFilter == NULL)
  547. {
  548. hr = CreateFilter();
  549. if (FAILED(hr))
  550. {
  551. LOG((MSP_ERROR, "%s, Create filter failed. hr=%x", __fxName, hr));
  552. return hr;
  553. }
  554. }
  555. _ASSERT(pGraph != NULL);
  556. _ASSERT(m_pFilter != NULL);
  557. hr = pGraph->AddFilter(m_pFilter, NULL);
  558. return hr;
  559. }
  560. HRESULT CIPConfBaseTerminal::RemoveFilterFromGraph(
  561. IN IGraphBuilder *pGraph
  562. )
  563. /*++
  564. Routine Description:
  565. Remove the internal filter from the graph it was added.
  566. Arguments:
  567. pGraph - the filter graph to remove the filter from.
  568. Return Value:
  569. S_FALSE - the internal filter doesn't exist.
  570. --*/
  571. {
  572. ENTER_FUNCTION("CIPConfBaseTerminal::RemoveFilterFromGraph");
  573. LOG((MSP_TRACE, "%s entered, pGraph:%p", __fxName, pGraph));
  574. if (m_pFilter == NULL)
  575. {
  576. LOG((MSP_TRACE, "%s, no filter to remove", __fxName));
  577. return S_FALSE;
  578. }
  579. // remove the filter from the graph
  580. _ASSERT(pGraph != NULL);
  581. HRESULT hr = pGraph->RemoveFilter(m_pFilter);
  582. m_pFilter->Release();
  583. m_pFilter = NULL;
  584. return hr;
  585. }