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.

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