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.

1566 lines
35 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. confpart.cpp
  5. Abstract:
  6. This module contains implementation of the participant classes.
  7. Author:
  8. Mu Han (muhan) 15-September-1999
  9. --*/
  10. #include "stdafx.h"
  11. #include "confpart.h"
  12. #ifdef DEBUG_REFCOUNT
  13. ULONG CParticipant::InternalAddRef()
  14. {
  15. ULONG lRef = CComObjectRootEx<CComMultiThreadModelNoCS>::InternalAddRef();
  16. LOG((MSP_TRACE, "%p, %ws Addref, ref = %d",
  17. this, (m_InfoItems[0]) ? m_InfoItems[0] : L"new participant", lRef));
  18. return lRef;
  19. }
  20. ULONG CParticipant::InternalRelease()
  21. {
  22. ULONG lRef = CComObjectRootEx<CComMultiThreadModelNoCS>::InternalRelease();
  23. LOG((MSP_TRACE, "%p, %ws Release, ref = %d",
  24. this, (m_InfoItems[0]) ? m_InfoItems[0] : L"new participant", lRef));
  25. return lRef;
  26. }
  27. #endif
  28. CParticipant::CParticipant()
  29. : m_pFTM(NULL),
  30. m_dwSendingMediaTypes(0),
  31. m_dwReceivingMediaTypes(0)
  32. {
  33. // initialize the info item array.
  34. ZeroMemory(m_InfoItems, sizeof(WCHAR *) * (NUM_SDES_ITEMS));
  35. }
  36. // methods called by the call object.
  37. HRESULT CParticipant::Init(
  38. IN WCHAR * szCName,
  39. IN ITStream * pITStream,
  40. IN DWORD dwSSRC,
  41. IN DWORD dwSendRecv,
  42. IN DWORD dwMediaType
  43. )
  44. /*++
  45. Routine Description:
  46. Initialize the participant object.
  47. Arguments:
  48. szCName - the canonical name of the participant.
  49. pITStream - the stream that has the participant.
  50. dwSSRC - the SSRC of the participant in that stream.
  51. dwSendRecv - a sender or a receiver.
  52. dwMediaType - the media type of the participant.
  53. Return Value:
  54. S_OK,
  55. E_OUTOFMEMORY.
  56. --*/
  57. {
  58. LOG((MSP_TRACE, "CParticipant::Init, name:%ws", szCName));
  59. // create the marshaler.
  60. HRESULT hr;
  61. hr = CoCreateFreeThreadedMarshaler(GetControllingUnknown(), &m_pFTM);
  62. if (FAILED(hr))
  63. {
  64. LOG((MSP_ERROR, "create marshaler failed, %x", hr));
  65. return hr;
  66. }
  67. m_InfoItems[0] = (WCHAR *)malloc((lstrlenW(szCName) + 1) * sizeof(WCHAR));
  68. if (m_InfoItems[0] == NULL)
  69. {
  70. LOG((MSP_ERROR, "out of mem for CName"));
  71. return E_OUTOFMEMORY;
  72. }
  73. lstrcpyW(m_InfoItems[0], szCName);
  74. // add the stream into out list.
  75. hr = AddStream(pITStream, dwSSRC, dwSendRecv, dwMediaType);
  76. if (FAILED(hr))
  77. {
  78. LOG((MSP_ERROR, "failed to add stream %x", hr));
  79. return hr;
  80. }
  81. LOG((MSP_TRACE, "CParticipant: %ws, Init returns S_OK", szCName));
  82. return S_OK;
  83. }
  84. BOOL CParticipant::UpdateInfo(
  85. IN int Type,
  86. IN DWORD dwLen,
  87. IN WCHAR * szInfo
  88. )
  89. /*++
  90. Routine Description:
  91. Update one item of the participant info.
  92. Arguments:
  93. Type - the type of the INFO,
  94. dwLen - the length of the information.
  95. szInfo - the information.
  96. Return Value:
  97. TRUE - information changed.
  98. FALSE - the information is the same, no change was made.
  99. --*/
  100. {
  101. int index = Type - 1;
  102. // if we have an item already, find out if it is the same.
  103. if (m_InfoItems[index] != NULL)
  104. {
  105. if (lstrcmpW(m_InfoItems[index], szInfo) == 0)
  106. {
  107. return FALSE;
  108. }
  109. // if the item is new, free the old one
  110. free(m_InfoItems[index]);
  111. }
  112. // allocate memory and store it.
  113. m_InfoItems[index] = (WCHAR *)malloc((dwLen + 1) * sizeof(WCHAR));
  114. if (m_InfoItems[index] == NULL)
  115. {
  116. return FALSE;
  117. }
  118. lstrcpynW(m_InfoItems[index], szInfo, dwLen);
  119. return TRUE;
  120. }
  121. BOOL CParticipant::UpdateSSRC(
  122. IN ITStream * pITStream,
  123. IN DWORD dwSSRC,
  124. IN DWORD dwSendRecv
  125. )
  126. /*++
  127. Routine Description:
  128. Update the SSRC for a stream.
  129. Arguments:
  130. pITStream - the stream that the participant is on.
  131. dwSSRC - the SSRC of the participant.
  132. dwSendRecv - the participant is a sender or a receiver.
  133. Return Value:
  134. TRUE - information changed.
  135. FALSE - the stream is not found.
  136. --*/
  137. {
  138. CLock lock(m_lock);
  139. // if the stream is already there, update the SSRC and return.
  140. int index = m_Streams.Find(pITStream);
  141. if ( index >= 0)
  142. {
  143. m_StreamInfo[index].dwSSRC = dwSSRC;
  144. m_StreamInfo[index].dwSendRecv |= dwSendRecv;
  145. return TRUE;
  146. }
  147. return FALSE;
  148. }
  149. BOOL CParticipant::HasSSRC(
  150. IN ITStream * pITStream,
  151. IN DWORD dwSSRC
  152. )
  153. /*++
  154. Routine Description:
  155. find out if the participant has the SSRC for a stream.
  156. Arguments:
  157. pITStream - the stream that the participant is on.
  158. dwSSRC - the SSRC of the participant.
  159. Return Value:
  160. TRUE - the SSRC exists.
  161. FALSE - the SSRC does not exist.
  162. --*/
  163. {
  164. CLock lock(m_lock);
  165. int index = m_Streams.Find(pITStream);
  166. if (index >= 0)
  167. {
  168. return (m_StreamInfo[index].dwSSRC == dwSSRC);
  169. }
  170. return FALSE;
  171. }
  172. BOOL CParticipant::GetSSRC(
  173. IN ITStream * pITStream,
  174. OUT DWORD * pdwSSRC
  175. )
  176. /*++
  177. Routine Description:
  178. Update the SSRC for a stream.
  179. Arguments:
  180. pITStream - the stream that the participant is on.
  181. pdwSSRC - the address to store the SSRC of the participant.
  182. Return Value:
  183. TRUE - the SSRC is found.
  184. FALSE - the SSRC is not found.
  185. --*/
  186. {
  187. CLock lock(m_lock);
  188. // if the stream is already there, update the SSRC and return.
  189. int index = m_Streams.Find(pITStream);
  190. if ( index >= 0)
  191. {
  192. *pdwSSRC = m_StreamInfo[index].dwSSRC;
  193. return TRUE;
  194. }
  195. return FALSE;
  196. }
  197. DWORD CParticipant::GetSendRecvStatus(
  198. IN ITStream * pITStream
  199. )
  200. /*++
  201. Routine Description:
  202. find out the current send and recv status on a given stream.
  203. Arguments:
  204. pITStream - the stream that the participant is on.
  205. Return Value:
  206. A bit mask of send and receive status
  207. --*/
  208. {
  209. CLock lock(m_lock);
  210. int index = m_Streams.Find(pITStream);
  211. if (index >= 0)
  212. {
  213. return m_StreamInfo[index].dwSendRecv;
  214. }
  215. return 0;
  216. }
  217. void CParticipant::FinalRelease()
  218. /*++
  219. Routine Description:
  220. release everything before being deleted.
  221. Arguments:
  222. Return Value:
  223. --*/
  224. {
  225. LOG((MSP_TRACE, "CParticipant::FinalRelease, name %ws", m_InfoItems[0]));
  226. if (m_pFTM)
  227. {
  228. m_pFTM->Release();
  229. }
  230. for (int i = 0; i < NUM_SDES_ITEMS; i ++)
  231. {
  232. if (m_InfoItems[i])
  233. {
  234. free(m_InfoItems[i]);
  235. }
  236. }
  237. for (i = 0; i < m_Streams.GetSize(); i ++)
  238. {
  239. m_Streams[i]->Release();
  240. }
  241. m_Streams.RemoveAll();
  242. LOG((MSP_TRACE, "CParticipant::FinalRelease - exit"));
  243. }
  244. // ITParticipant methods, called by the app.
  245. STDMETHODIMP CParticipant::get_ParticipantTypedInfo(
  246. IN PARTICIPANT_TYPED_INFO InfoType,
  247. OUT BSTR * ppInfo
  248. )
  249. /*++
  250. Routine Description:
  251. Get a information item for this participant.
  252. Arguments:
  253. InfoType - The type of the information asked.
  254. ppInfo - the mem address to store a BSTR.
  255. Return Value:
  256. S_OK,
  257. E_INVALIDARG,
  258. E_POINTER,
  259. E_OUTOFMEMORY,
  260. TAPI_E_NOITEMS
  261. */
  262. {
  263. LOG((MSP_TRACE, "CParticipant get info, type:%d", InfoType));
  264. if (InfoType > PTI_PRIVATE || InfoType < PTI_CANONICALNAME)
  265. {
  266. LOG((MSP_ERROR, "CParticipant get info - exit invalid arg"));
  267. return E_INVALIDARG;
  268. }
  269. if (IsBadWritePtr(ppInfo, sizeof(BSTR)))
  270. {
  271. LOG((MSP_ERROR, "CParticipant get info - exit E_POINTER"));
  272. return E_POINTER;
  273. }
  274. // check if we have that info.
  275. CLock lock(m_lock);
  276. int index = (int)InfoType;
  277. if (m_InfoItems[index] == NULL)
  278. {
  279. LOG((MSP_INFO, "CParticipant get info - no item for %d", InfoType));
  280. return TAPI_E_NOITEMS;
  281. }
  282. // make a BSTR out of it.
  283. BSTR pName = SysAllocString(m_InfoItems[index]);
  284. if (pName == NULL)
  285. {
  286. LOG((MSP_ERROR, "CParticipant get info - exit out of mem"));
  287. return E_OUTOFMEMORY;
  288. }
  289. // return the BSTR.
  290. *ppInfo = pName;
  291. return S_OK;
  292. }
  293. STDMETHODIMP CParticipant::get_MediaTypes(
  294. // IN TERMINAL_DIRECTION Direction,
  295. OUT long * plMediaTypes
  296. )
  297. /*++
  298. Routine Description:
  299. Get the media type of the participant
  300. Arguments:
  301. plMediaType - the mem address to store a long.
  302. Return Value:
  303. S_OK,
  304. E_POINTER,
  305. */
  306. {
  307. LOG((MSP_TRACE, "CParticipant::get_MediaTypes - enter"));
  308. if (IsBadWritePtr(plMediaTypes, sizeof (long)))
  309. {
  310. LOG((MSP_ERROR, "CParticipant::get_MediaType - exit E_POINTER"));
  311. return E_POINTER;
  312. }
  313. CLock lock(m_lock);
  314. #if 0
  315. if (Direction == TD_RENDER)
  316. {
  317. *plMediaTypes = (long)m_dwReceivingMediaTypes;
  318. }
  319. else
  320. {
  321. *plMediaTypes = (long)m_dwSendingMediaTypes;
  322. }
  323. #endif
  324. *plMediaTypes = (long)(m_dwSendingMediaTypes | m_dwReceivingMediaTypes);
  325. LOG((MSP_TRACE, "CParticipant::get_MediaType:%x - exit S_OK", *plMediaTypes));
  326. return S_OK;
  327. }
  328. STDMETHODIMP CParticipant::put_Status(
  329. IN ITStream * pITStream,
  330. IN VARIANT_BOOL fEnable
  331. )
  332. {
  333. ENTER_FUNCTION("CParticipant::put_Status");
  334. LOG((MSP_TRACE, "%s entered. %hs %ws for %p",
  335. __fxName, fEnable ? "Enable" : "Disable", m_InfoItems[0], pITStream));
  336. HRESULT hr;
  337. // if the caller specified a stream, find the stream and use it.
  338. if (pITStream != NULL)
  339. {
  340. m_lock.Lock();
  341. int index;
  342. if ((index = m_Streams.Find(pITStream)) < 0)
  343. {
  344. m_lock.Unlock();
  345. LOG((MSP_ERROR, "%s stream %p not found", __fxName, pITStream));
  346. return E_INVALIDARG;
  347. }
  348. DWORD dwSSRC = m_StreamInfo[index].dwSSRC;
  349. // add ref so that it won't go away.
  350. pITStream->AddRef();
  351. m_lock.Unlock();
  352. hr = ((CIPConfMSPStream *)pITStream)->EnableParticipant(
  353. dwSSRC,
  354. fEnable
  355. );
  356. pITStream->Release();
  357. return hr;
  358. }
  359. // if the caller didn't specify a stream, set the status on all streams.
  360. m_lock.Lock();
  361. int nSize = m_Streams.GetSize();
  362. ITStream ** Streams = (ITStream **)malloc(sizeof(ITStream*) * nSize);
  363. if (Streams == NULL)
  364. {
  365. m_lock.Unlock();
  366. LOG((MSP_ERROR, "%s out of memory", __fxName));
  367. return E_OUTOFMEMORY;
  368. }
  369. DWORD * pdwSSRCList = (DWORD *)malloc(sizeof(DWORD) * nSize);
  370. if (pdwSSRCList == NULL)
  371. {
  372. m_lock.Unlock();
  373. free(Streams);
  374. LOG((MSP_ERROR, "%s out of memory", __fxName));
  375. return E_OUTOFMEMORY;
  376. }
  377. for (int i = 0; i < nSize; i ++)
  378. {
  379. Streams[i] = m_Streams[i];
  380. Streams[i]->AddRef();
  381. pdwSSRCList[i] = m_StreamInfo[i].dwSSRC;
  382. }
  383. m_lock.Unlock();
  384. for (i = 0; i < nSize; i ++)
  385. {
  386. hr = ((CIPConfMSPStream *)Streams[i])->
  387. EnableParticipant(pdwSSRCList[i], fEnable);
  388. if (FAILED(hr))
  389. {
  390. break;
  391. }
  392. }
  393. for (i = 0; i < nSize; i ++)
  394. {
  395. Streams[i]->Release();
  396. }
  397. free(Streams);
  398. free(pdwSSRCList);
  399. return hr;
  400. }
  401. STDMETHODIMP CParticipant::get_Status(
  402. IN ITStream * pITStream,
  403. OUT VARIANT_BOOL * pfEnable
  404. )
  405. {
  406. ENTER_FUNCTION("CParticipant::get_Status");
  407. LOG((MSP_TRACE, "%s entered. %ws %p",
  408. __fxName, m_InfoItems[0], pITStream));
  409. if (IsBadWritePtr(pfEnable, sizeof(VARIANT_BOOL)))
  410. {
  411. LOG((MSP_ERROR, "%s bad pointer argument - exit E_POINTER", __fxName));
  412. return E_POINTER;
  413. }
  414. HRESULT hr;
  415. BOOL fEnable;
  416. // if the caller specified a stream, find the stream and use it.
  417. if (pITStream != NULL)
  418. {
  419. m_lock.Lock();
  420. int index;
  421. if ((index = m_Streams.Find(pITStream)) < 0)
  422. {
  423. m_lock.Unlock();
  424. LOG((MSP_ERROR, "%s stream %p not found", __fxName, pITStream));
  425. return E_INVALIDARG;
  426. }
  427. DWORD dwSSRC = m_StreamInfo[index].dwSSRC;
  428. // add ref so that it won't go away.
  429. pITStream->AddRef();
  430. m_lock.Unlock();
  431. hr = ((CIPConfMSPStream *)pITStream)->GetParticipantStatus(
  432. dwSSRC,
  433. &fEnable
  434. );
  435. pITStream->Release();
  436. *pfEnable = (fEnable) ? VARIANT_TRUE : VARIANT_FALSE;
  437. return hr;
  438. }
  439. // if the caller didn't specify a stream, get the status from all streams.
  440. m_lock.Lock();
  441. int nSize = m_Streams.GetSize();
  442. ITStream ** Streams = (ITStream **)malloc(sizeof(ITStream*) * nSize);
  443. if (Streams == NULL)
  444. {
  445. m_lock.Unlock();
  446. LOG((MSP_ERROR, "%s out of memory", __fxName));
  447. return E_OUTOFMEMORY;
  448. }
  449. DWORD * pdwSSRCList = (DWORD *)malloc(sizeof(DWORD) * nSize);
  450. if (pdwSSRCList == NULL)
  451. {
  452. m_lock.Unlock();
  453. free(Streams);
  454. LOG((MSP_ERROR, "%s out of memory", __fxName));
  455. return E_OUTOFMEMORY;
  456. }
  457. for (int i = 0; i < nSize; i ++)
  458. {
  459. Streams[i] = m_Streams[i];
  460. Streams[i]->AddRef();
  461. pdwSSRCList[i] = m_StreamInfo[i].dwSSRC;
  462. }
  463. m_lock.Unlock();
  464. fEnable = FALSE;
  465. for (i = 0; i < nSize; i ++)
  466. {
  467. BOOL fEnabledOnStream;
  468. hr = ((CIPConfMSPStream *)Streams[i])->
  469. GetParticipantStatus(pdwSSRCList[i], &fEnabledOnStream);
  470. if (FAILED(hr))
  471. {
  472. break;
  473. }
  474. // as long as it is enabled on one stream, it is enabled.
  475. fEnable = fEnable || fEnabledOnStream;
  476. }
  477. for (i = 0; i < nSize; i ++)
  478. {
  479. Streams[i]->Release();
  480. }
  481. free(Streams);
  482. free(pdwSSRCList);
  483. *pfEnable = (fEnable) ? VARIANT_TRUE : VARIANT_FALSE;
  484. return hr;
  485. }
  486. STDMETHODIMP CParticipant::EnumerateStreams(
  487. OUT IEnumStream ** ppEnumStream
  488. )
  489. {
  490. LOG((MSP_TRACE,
  491. "EnumerateStreams entered. ppEnumStream:%x", ppEnumStream));
  492. //
  493. // Check parameters.
  494. //
  495. if (IsBadWritePtr(ppEnumStream, sizeof(VOID *)))
  496. {
  497. LOG((MSP_ERROR, "CParticipant::EnumerateStreams - "
  498. "bad pointer argument - exit E_POINTER"));
  499. return E_POINTER;
  500. }
  501. //
  502. // First see if this call has been shut down.
  503. // acquire the lock before accessing the stream object list.
  504. //
  505. CLock lock(m_lock);
  506. if (m_Streams.GetData() == NULL)
  507. {
  508. LOG((MSP_ERROR, "CParticipant::EnumerateStreams - "
  509. "call appears to have been shut down - exit E_UNEXPECTED"));
  510. // This call has been shut down.
  511. return E_UNEXPECTED;
  512. }
  513. //
  514. // Create an enumerator object.
  515. //
  516. typedef _CopyInterface<ITStream> CCopy;
  517. typedef CSafeComEnum<IEnumStream, &__uuidof(IEnumStream),
  518. ITStream *, CCopy> CEnumerator;
  519. HRESULT hr;
  520. CComObject<CEnumerator> *pEnum = NULL;
  521. hr = ::CreateCComObjectInstance(&pEnum);
  522. if (pEnum == NULL)
  523. {
  524. LOG((MSP_ERROR, "CParticipant::EnumerateStreams - "
  525. "Could not create enumerator object, %x", hr));
  526. return hr;
  527. }
  528. //
  529. // query for the __uuidof(IEnumStream) i/f
  530. //
  531. hr = pEnum->_InternalQueryInterface(__uuidof(IEnumStream), (void**)ppEnumStream);
  532. if (FAILED(hr))
  533. {
  534. LOG((MSP_ERROR, "CParticipant::EnumerateStreams - "
  535. "query enum interface failed, %x", hr));
  536. delete pEnum;
  537. return hr;
  538. }
  539. //
  540. // Init the enumerator object. The CSafeComEnum can handle zero-sized array.
  541. //
  542. hr = pEnum->Init(
  543. m_Streams.GetData(), // the begin itor
  544. m_Streams.GetData() + m_Streams.GetSize(), // the end itor,
  545. NULL, // IUnknown
  546. AtlFlagCopy // copy the data.
  547. );
  548. if (FAILED(hr))
  549. {
  550. LOG((MSP_ERROR, "CParticipant::EnumerateStreams - "
  551. "init enumerator object failed, %x", hr));
  552. (*ppEnumStream)->Release();
  553. return hr;
  554. }
  555. LOG((MSP_TRACE, "CParticipant::EnumerateStreams - exit S_OK"));
  556. return hr;
  557. }
  558. STDMETHODIMP CParticipant::get_Streams(
  559. OUT VARIANT * pVariant
  560. )
  561. {
  562. LOG((MSP_TRACE, "CParticipant::get_Streams - enter"));
  563. //
  564. // Check parameters.
  565. //
  566. if ( IsBadWritePtr(pVariant, sizeof(VARIANT) ) )
  567. {
  568. LOG((MSP_ERROR, "CParticipant::get_Streams - "
  569. "bad pointer argument - exit E_POINTER"));
  570. return E_POINTER;
  571. }
  572. //
  573. // See if this call has been shut down. Acquire the lock before accessing
  574. // the stream object list.
  575. //
  576. CLock lock(m_lock);
  577. if (m_Streams.GetData() == NULL)
  578. {
  579. LOG((MSP_ERROR, "CParticipant::get_Streams - "
  580. "call appears to have been shut down - exit E_UNEXPECTED"));
  581. // This call has been shut down.
  582. return E_UNEXPECTED;
  583. }
  584. //
  585. // create the collection object - see mspcoll.h
  586. //
  587. typedef CTapiIfCollection< ITStream * > StreamCollection;
  588. CComObject<StreamCollection> * pCollection;
  589. HRESULT hr;
  590. hr = ::CreateCComObjectInstance(&pCollection);
  591. if ( FAILED(hr) )
  592. {
  593. LOG((MSP_ERROR, "CParticipant::get_Streams - "
  594. "can't create collection - exit 0x%08x", hr));
  595. return hr;
  596. }
  597. //
  598. // get the Collection's IDispatch interface
  599. //
  600. IDispatch * pDispatch;
  601. hr = pCollection->_InternalQueryInterface(__uuidof(IDispatch),
  602. (void **) &pDispatch );
  603. if ( FAILED(hr) )
  604. {
  605. LOG((MSP_ERROR, "CParticipant::get_Streams - "
  606. "QI for IDispatch on collection failed - exit 0x%08x", hr));
  607. delete pCollection;
  608. return hr;
  609. }
  610. //
  611. // Init the collection using an iterator -- pointers to the beginning and
  612. // the ending element plus one.
  613. //
  614. hr = pCollection->Initialize( m_Streams.GetSize(),
  615. m_Streams.GetData(),
  616. m_Streams.GetData() + m_Streams.GetSize() );
  617. if (FAILED(hr))
  618. {
  619. LOG((MSP_ERROR, "CParticipant::get_Streams - "
  620. "Initialize on collection failed - exit 0x%08x", hr));
  621. pDispatch->Release();
  622. return hr;
  623. }
  624. //
  625. // put the IDispatch interface pointer into the variant
  626. //
  627. LOG((MSP_INFO, "CParticipant::get_Streams - "
  628. "placing IDispatch value %08x in variant", pDispatch));
  629. VariantInit(pVariant);
  630. pVariant->vt = VT_DISPATCH;
  631. pVariant->pdispVal = pDispatch;
  632. LOG((MSP_TRACE, "CParticipant::get_Streams - exit S_OK"));
  633. return S_OK;
  634. }
  635. HRESULT CParticipant::AddStream(
  636. IN ITStream * pITStream,
  637. IN DWORD dwSSRC,
  638. IN DWORD dwSendRecv,
  639. IN DWORD dwMediaType
  640. )
  641. /*++
  642. Routine Description:
  643. A participant might appear on more than one streams. This function adds
  644. a new stream and the SSRC into the participant's list.
  645. Arguments:
  646. pITStream - the stream that has the participant.
  647. dwSSRC - the SSRC of the participant in that stream.
  648. dwSendRecv - the participant is a sender or receiver in the stream.
  649. dwMediaType - the media type of the stream.
  650. Return Value:
  651. S_OK,
  652. E_OUTOFMEMORY,
  653. */
  654. {
  655. CLock lock(m_lock);
  656. // if the stream is already there, update the SSRC and return.
  657. int index = m_Streams.Find(pITStream);
  658. if ( index >= 0)
  659. {
  660. m_StreamInfo[index].dwSSRC = dwSSRC;
  661. m_StreamInfo[index].dwSendRecv |= dwSendRecv;
  662. return S_OK;
  663. }
  664. // add the stream.
  665. if (!m_Streams.Add(pITStream))
  666. {
  667. return E_OUTOFMEMORY;
  668. }
  669. // add the SSRC and sender flag.
  670. STREAM_INFO Info;
  671. Info.dwSSRC = dwSSRC;
  672. Info.dwSendRecv = dwSendRecv;
  673. Info.dwState = PESTREAM_RECOVER;
  674. if (!m_StreamInfo.Add(Info))
  675. {
  676. m_Streams.Remove(pITStream);
  677. return E_OUTOFMEMORY;
  678. }
  679. pITStream->AddRef();
  680. // update the mediatype.
  681. if (dwSendRecv & PART_SEND)
  682. {
  683. m_dwSendingMediaTypes |= dwMediaType;
  684. }
  685. if (dwSendRecv & PART_RECV)
  686. {
  687. m_dwReceivingMediaTypes |= dwMediaType;
  688. }
  689. return S_OK;
  690. }
  691. HRESULT CParticipant::RemoveStream(
  692. IN ITStream * pITStream,
  693. IN DWORD dwSSRC,
  694. OUT BOOL * pbLast
  695. )
  696. /*++
  697. Routine Description:
  698. A participant might appear on more than one streams. This function remove
  699. a stream from the participant's list.
  700. Arguments:
  701. pITStream - the stream that has the participant.
  702. dwSSRC - the SSRC of the participant in that stream.
  703. pbLast - the memory space to store a boolean value, specifying if the
  704. stream removed was the last one in the list.
  705. Return Value:
  706. S_OK,
  707. E_POINTER,
  708. */
  709. {
  710. CLock lock(m_lock);
  711. // first find the stream.
  712. int index = m_Streams.Find(pITStream);
  713. if (index < 0)
  714. {
  715. return E_FAIL;
  716. }
  717. if (m_Streams.GetSize() != m_StreamInfo.GetSize())
  718. {
  719. return E_UNEXPECTED;
  720. }
  721. // then check the SSRC.
  722. if (m_StreamInfo[index].dwSSRC != dwSSRC)
  723. {
  724. // this is not the participant being looking for.
  725. return E_FAIL;
  726. }
  727. // SSRC match, we found the participant. remove the stream and info.
  728. m_Streams.RemoveAt(index);
  729. m_StreamInfo.RemoveAt(index);
  730. // release the refcount we had in the list.
  731. pITStream->Release();
  732. // recalculate the media types.
  733. m_dwSendingMediaTypes = 0;
  734. m_dwReceivingMediaTypes = 0;
  735. for (int i = 0; i < m_Streams.GetSize(); i ++)
  736. {
  737. if (m_StreamInfo[i].dwSendRecv & PART_SEND)
  738. {
  739. m_dwSendingMediaTypes |= ((CIPConfMSPStream *)m_Streams[i])->MediaType();
  740. }
  741. if (m_StreamInfo[i].dwSendRecv & PART_RECV)
  742. {
  743. m_dwReceivingMediaTypes |= ((CIPConfMSPStream *)m_Streams[i])->MediaType();
  744. }
  745. }
  746. *pbLast = (m_Streams.GetSize() == 0);
  747. return S_OK;
  748. }
  749. HRESULT CParticipant::SetStreamState (
  750. IN ITStream * pITStream,
  751. IN PESTREAM_STATE state
  752. )
  753. /*++
  754. Routine Description:
  755. Sets the state on stream.
  756. --*/
  757. {
  758. CLock lock(m_lock);
  759. // first find the stream.
  760. int index = m_Streams.Find(pITStream);
  761. if (index < 0)
  762. return E_FAIL;
  763. if (m_Streams.GetSize() != m_StreamInfo.GetSize())
  764. return E_UNEXPECTED;
  765. DWORD dw = m_StreamInfo[index].dwState;
  766. switch (state)
  767. {
  768. case PESTREAM_RECOVER:
  769. // set recover
  770. dw |= PESTREAM_RECOVER;
  771. // clear timeout bit
  772. dw |= PESTREAM_TIMEOUT;
  773. dw &= (PESTREAM_TIMEOUT ^ PESTREAM_FULLBITS);
  774. break;
  775. case PESTREAM_TIMEOUT:
  776. // set timeout
  777. dw |= PESTREAM_TIMEOUT;
  778. // clear recover bit
  779. dw |= PESTREAM_RECOVER;
  780. dw &= (PESTREAM_RECOVER ^ PESTREAM_FULLBITS);
  781. break;
  782. default:
  783. LOG ((MSP_ERROR, "unknown stream state. %x", state));
  784. return E_INVALIDARG;
  785. }
  786. m_StreamInfo[index].dwState = dw;
  787. return S_OK;
  788. }
  789. HRESULT CParticipant::GetStreamState (
  790. IN ITStream * pITStream,
  791. OUT DWORD * pdwState
  792. )
  793. /*++
  794. Routine Description:
  795. Gets the state on stream.
  796. --*/
  797. {
  798. CLock lock(m_lock);
  799. // first find the stream.
  800. int index = m_Streams.Find(pITStream);
  801. if (index < 0)
  802. return E_FAIL;
  803. if (m_Streams.GetSize() != m_StreamInfo.GetSize())
  804. return E_UNEXPECTED;
  805. *pdwState = m_StreamInfo[index].dwState;
  806. return S_OK;
  807. }
  808. INT CParticipant::GetStreamCount (DWORD dwSendRecv)
  809. {
  810. // this is called by ourself
  811. _ASSERTE ((dwSendRecv & PART_SEND) || (dwSendRecv & PART_RECV));
  812. CLock lock(m_lock);
  813. int i, count = 0;
  814. for (i=0; i<m_StreamInfo.GetSize (); i++)
  815. {
  816. if (m_StreamInfo[i].dwSendRecv & dwSendRecv)
  817. count ++;
  818. }
  819. return count;
  820. }
  821. INT CParticipant::GetStreamTimeOutCount (DWORD dwSendRecv)
  822. {
  823. // this is called by ourself
  824. _ASSERTE ((dwSendRecv & PART_SEND) || (dwSendRecv & PART_RECV));
  825. CLock lock(m_lock);
  826. int i, count = 0;
  827. for (i=0; i<m_StreamInfo.GetSize (); i++)
  828. {
  829. if ((m_StreamInfo[i].dwSendRecv & dwSendRecv) &&
  830. (m_StreamInfo[i].dwState & PESTREAM_TIMEOUT))
  831. count ++;
  832. }
  833. return count;
  834. }
  835. BOOL CParticipantList::FindByCName(WCHAR *szCName, int *pIndex) const
  836. /*++
  837. Routine Description:
  838. Find a participant by its canonical name. If the function returns true,
  839. *pIndex contains the index of the participant. If the function returns
  840. false, *pIndex contains the index where the new participant should be
  841. inserted.
  842. Arguments:
  843. szCName - the canonical name of the participant.
  844. pIndex - the memory address to store an integer.
  845. Return Value:
  846. TRUE - the participant is found.
  847. FALSE - the participant is not in the list.
  848. */
  849. {
  850. for(int i = 0; i < m_nSize; i++)
  851. {
  852. // This list is an ordered list based on dictionary order. We are using
  853. // a linear search here, it could be changed to a binary search.
  854. // CompareCName will return 0 if the name is the same, <0 if the szCName
  855. // is bigger, >0 if the szCName is smaller.
  856. int res = ((CParticipant *)m_aT[i])->CompareCName(szCName);
  857. if(res >= 0)
  858. {
  859. *pIndex = i;
  860. return (res == 0);
  861. }
  862. }
  863. *pIndex = m_nSize;
  864. return FALSE; // not found
  865. }
  866. BOOL CParticipantList::InsertAt(int nIndex, ITParticipant *pITParticipant)
  867. /*++
  868. Routine Description:
  869. Insert a participant into the list at a given index.
  870. Arguments:
  871. nIndex - the location where the new object is inserted.
  872. pITParticipant - the object to be inserted.
  873. Return Value:
  874. TRUE - the participant is inserted.
  875. FALSE - out of memory.
  876. */
  877. {
  878. _ASSERTE(nIndex >= 0 && nIndex <= m_nSize);
  879. if(m_nSize == m_nAllocSize)
  880. {
  881. if (!Grow()) return FALSE;
  882. }
  883. memmove((void*)&m_aT[nIndex+1], (void*)&m_aT[nIndex],
  884. (m_nSize - nIndex) * sizeof(ITParticipant *));
  885. m_nSize++;
  886. SetAtIndex(nIndex, pITParticipant);
  887. return TRUE;
  888. }
  889. CParticipantEvent::CParticipantEvent()
  890. : m_pFTM(NULL),
  891. m_pITParticipant(NULL),
  892. m_pITSubStream(NULL),
  893. m_Event(PE_NEW_PARTICIPANT)
  894. {}
  895. // methods called by the call object.
  896. HRESULT CParticipantEvent::Init(
  897. IN PARTICIPANT_EVENT Event,
  898. IN ITParticipant * pITParticipant,
  899. IN ITSubStream * pITSubStream
  900. )
  901. /*++
  902. Routine Description:
  903. Initialize the ParticipantEvent object.
  904. Arguments:
  905. Event - the event.
  906. pITParticipant - the participant.
  907. pITSubStream - the substream, can be NULL.
  908. Return Value:
  909. S_OK,
  910. --*/
  911. {
  912. LOG((MSP_TRACE, "CParticipantEvent::Init"));
  913. // create the marshaler.
  914. HRESULT hr;
  915. hr = CoCreateFreeThreadedMarshaler(GetControllingUnknown(), &m_pFTM);
  916. if (FAILED(hr))
  917. {
  918. LOG((MSP_ERROR, "create marshaler failed, %x", hr));
  919. return hr;
  920. }
  921. m_Event = Event;
  922. m_pITParticipant = pITParticipant;
  923. if (m_pITParticipant) m_pITParticipant->AddRef();
  924. m_pITSubStream = pITSubStream;
  925. if (m_pITSubStream) m_pITSubStream->AddRef();
  926. LOG((MSP_TRACE, "CParticipantEvent Init returns S_OK"));
  927. return S_OK;
  928. }
  929. void CParticipantEvent::FinalRelease()
  930. /*++
  931. Routine Description:
  932. release everything before being deleted.
  933. Arguments:
  934. Return Value:
  935. --*/
  936. {
  937. LOG((MSP_TRACE, "CParticipantEvent::FinalRelease - enter"));
  938. if (m_pFTM)
  939. {
  940. m_pFTM->Release();
  941. }
  942. if (m_pITParticipant) m_pITParticipant->Release();
  943. if (m_pITSubStream) m_pITSubStream->Release();
  944. LOG((MSP_TRACE, "CParticipantEvent::FinalRelease - exit"));
  945. }
  946. STDMETHODIMP CParticipantEvent::get_Event(
  947. OUT PARTICIPANT_EVENT * pParticipantEvent
  948. )
  949. {
  950. if (IsBadWritePtr(pParticipantEvent, sizeof (PARTICIPANT_EVENT)))
  951. {
  952. LOG((MSP_ERROR, "CParticipantEvent::get_Event - exit E_POINTER"));
  953. return E_POINTER;
  954. }
  955. *pParticipantEvent = m_Event;
  956. return S_OK;
  957. }
  958. STDMETHODIMP CParticipantEvent::get_Participant(
  959. OUT ITParticipant ** ppITParticipant
  960. )
  961. {
  962. if (IsBadWritePtr(ppITParticipant, sizeof (void *)))
  963. {
  964. LOG((MSP_ERROR, "CParticipantEvent::get_participant - exit E_POINTER"));
  965. return E_POINTER;
  966. }
  967. if (!m_pITParticipant)
  968. {
  969. // LOG((MSP_ERROR, "CParticipantevnt::get_Participant - exit no item"));
  970. return TAPI_E_NOITEMS;
  971. }
  972. m_pITParticipant->AddRef();
  973. *ppITParticipant = m_pITParticipant;
  974. return S_OK;
  975. }
  976. STDMETHODIMP CParticipantEvent::get_SubStream(
  977. OUT ITSubStream** ppSubStream
  978. )
  979. {
  980. if (IsBadWritePtr(ppSubStream, sizeof (void *)))
  981. {
  982. LOG((MSP_ERROR, "CParticipantEvent::get_SubStream - exit E_POINTER"));
  983. return E_POINTER;
  984. }
  985. if (!m_pITSubStream)
  986. {
  987. LOG((MSP_WARN, "CParticipantevnt::get_SubStream - exit no item"));
  988. return TAPI_E_NOITEMS;
  989. }
  990. m_pITSubStream->AddRef();
  991. *ppSubStream = m_pITSubStream;
  992. return S_OK;
  993. }
  994. HRESULT CreateParticipantEvent(
  995. IN PARTICIPANT_EVENT Event,
  996. IN ITParticipant * pITParticipant,
  997. IN ITSubStream * pITSubStream,
  998. OUT IDispatch ** ppIDispatch
  999. )
  1000. {
  1001. // create the object.
  1002. CComObject<CParticipantEvent> * pCOMParticipantEvent;
  1003. HRESULT hr;
  1004. hr = ::CreateCComObjectInstance(&pCOMParticipantEvent);
  1005. if (NULL == pCOMParticipantEvent)
  1006. {
  1007. LOG((MSP_ERROR, "could not create participant event:%x", hr));
  1008. return hr;
  1009. }
  1010. IDispatch * pIDispatch;
  1011. // get the interface pointer.
  1012. hr = pCOMParticipantEvent->_InternalQueryInterface(
  1013. __uuidof(IDispatch),
  1014. (void **)&pIDispatch
  1015. );
  1016. if (FAILED(hr))
  1017. {
  1018. LOG((MSP_ERROR, "Create ParticipantEvent QueryInterface failed: %x", hr));
  1019. delete pCOMParticipantEvent;
  1020. return hr;
  1021. }
  1022. // Initialize the object.
  1023. hr = pCOMParticipantEvent->Init(
  1024. Event,
  1025. pITParticipant,
  1026. pITSubStream
  1027. );
  1028. if (FAILED(hr))
  1029. {
  1030. LOG((MSP_ERROR, "CreateMSPParticipantEvent:call init failed: %x", hr));
  1031. pIDispatch->Release();
  1032. return hr;
  1033. }
  1034. *ppIDispatch = pIDispatch;
  1035. return S_OK;
  1036. }
  1037. HRESULT CreateParticipantEnumerator(
  1038. IN ITParticipant ** begin,
  1039. IN ITParticipant ** end,
  1040. OUT IEnumParticipant ** ppEnumParticipant
  1041. )
  1042. {
  1043. //
  1044. // Create an enumerator object.
  1045. //
  1046. typedef _CopyInterface<ITParticipant> CCopy;
  1047. typedef CSafeComEnum<IEnumParticipant, &__uuidof(IEnumParticipant),
  1048. ITParticipant *, CCopy> CEnumerator;
  1049. HRESULT hr;
  1050. CComObject<CEnumerator> *pEnum = NULL;
  1051. hr = ::CreateCComObjectInstance(&pEnum);
  1052. if (pEnum == NULL)
  1053. {
  1054. LOG((MSP_ERROR, "CreateParticipantEnumerator - "
  1055. "Could not create enumerator object, %x", hr));
  1056. return hr;
  1057. }
  1058. //
  1059. // query for the __uuidof(IEnumParticipant) i/f
  1060. //
  1061. hr = pEnum->_InternalQueryInterface(
  1062. __uuidof(IEnumParticipant),
  1063. (void**)ppEnumParticipant
  1064. );
  1065. if (FAILED(hr))
  1066. {
  1067. LOG((MSP_ERROR, "CreateParticipantEnumerator - "
  1068. "query enum interface failed, %x", hr));
  1069. delete pEnum;
  1070. return hr;
  1071. }
  1072. //
  1073. // Init the enumerator object. The CSafeComEnum can handle zero-sized array.
  1074. //
  1075. hr = pEnum->Init(
  1076. begin, // the begin itor
  1077. end, // the end itor,
  1078. NULL, // IUnknown
  1079. AtlFlagCopy // copy the data.
  1080. );
  1081. if (FAILED(hr))
  1082. {
  1083. LOG((MSP_ERROR, "CreateParticipantEnumerator - "
  1084. "init enumerator object failed, %x", hr));
  1085. (*ppEnumParticipant)->Release();
  1086. return hr;
  1087. }
  1088. LOG((MSP_TRACE, "CreateParticipantEnumerator - exit S_OK"));
  1089. return hr;
  1090. }
  1091. HRESULT CreateParticipantCollection(
  1092. IN ITParticipant ** begin,
  1093. IN ITParticipant ** end,
  1094. IN int nSize,
  1095. OUT VARIANT * pVariant
  1096. )
  1097. {
  1098. //
  1099. // create the collection object - see mspcoll.h
  1100. //
  1101. typedef CTapiIfCollection< ITParticipant * > ParticipantCollection;
  1102. CComObject<ParticipantCollection> * pCollection;
  1103. HRESULT hr;
  1104. hr = ::CreateCComObjectInstance(&pCollection);
  1105. if ( FAILED(hr) )
  1106. {
  1107. LOG((MSP_ERROR, "CreateParticipantCollection - "
  1108. "can't create collection - exit 0x%08x", hr));
  1109. return hr;
  1110. }
  1111. //
  1112. // get the Collection's IDispatch interface
  1113. //
  1114. IDispatch * pDispatch;
  1115. hr = pCollection->_InternalQueryInterface(__uuidof(IDispatch),
  1116. (void **) &pDispatch );
  1117. if ( FAILED(hr) )
  1118. {
  1119. LOG((MSP_ERROR, "CreateParticipantCollection - "
  1120. "QI for IDispatch on collection failed - exit 0x%08x", hr));
  1121. delete pCollection;
  1122. return hr;
  1123. }
  1124. //
  1125. // Init the collection using an iterator -- pointers to the beginning and
  1126. // the ending element plus one.
  1127. //
  1128. hr = pCollection->Initialize(nSize, begin, end);
  1129. if (FAILED(hr))
  1130. {
  1131. LOG((MSP_ERROR, "CreateParticipantCollection- "
  1132. "Initialize on collection failed - exit 0x%08x", hr));
  1133. pDispatch->Release();
  1134. return hr;
  1135. }
  1136. //
  1137. // put the IDispatch interface pointer into the variant
  1138. //
  1139. VariantInit(pVariant);
  1140. pVariant->vt = VT_DISPATCH;
  1141. pVariant->pdispVal = pDispatch;
  1142. LOG((MSP_TRACE, "CreateParticipantCollection - exit S_OK"));
  1143. return S_OK;
  1144. }