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.

1489 lines
34 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. callhub.cpp
  5. Abstract:
  6. Implements all the methods on callhub interfaces.
  7. Author:
  8. mquinton - 11-21-97
  9. Notes:
  10. Revision History:
  11. --*/
  12. #include "stdafx.h"
  13. extern CHashTable * gpCallHubHashTable;
  14. extern CHashTable * gpCallHashTable;
  15. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  16. //
  17. // callhub.cpp
  18. //
  19. // this module implements the callhub object
  20. //
  21. // the callhub object is the "third party" view of a call.
  22. //
  23. // callhubs can be created in four different ways:
  24. //
  25. // 1 - the service provider supports them. they indicate this through
  26. // the linedevcapsflag_callhub bit in LINEDEVCAPS. this means
  27. // that the sp used the dwCallID field to associate calls.
  28. // tapisrv will synthesize the callhubs based on this information
  29. //
  30. // 2 - almost the same as 1, except that the sp does not set the
  31. // the linedevcapsflag_callhub bit (because it is a tapi2.x
  32. // sp). tapisrv and tapi3 have to guess whether or not the sp
  33. // supports callhubs. it does this simply by seeing if the
  34. // dwcallid field is non-zero. however, this creates a problem
  35. // before a call is made, since we can't get to the dwcallid
  36. // field. in this case, i set a flag in the address object
  37. // ADDRESSFLAG_CALLHUB or _NOCALLHUB to flag whether this is
  38. // supported. however, for the very first call, we won't know
  39. // until the call is actually made.
  40. //
  41. // 3 - participant based callhub (also called part based). the sp
  42. // supports participants, as indicated by the linedevcapsflag_participantinfo
  43. // tapi3 breaks out all the participants into their own participant
  44. // objects
  45. //
  46. // 4 - fake call hub. if the sp doesn't support anything, we create
  47. // a callhub, and fake the other end.
  48. //
  49. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  50. BOOL
  51. FindCallObject(
  52. HCALL hCall,
  53. CCall ** ppCall
  54. );
  55. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  56. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  57. HRESULT
  58. CCallHub::Initialize(
  59. CTAPI * pTapi,
  60. HCALLHUB hCallHub,
  61. DWORD dwFlags
  62. )
  63. {
  64. HRESULT hr;
  65. LOG((TL_TRACE,"Initialize - enter" ));
  66. Lock();
  67. m_pTAPI = pTapi;
  68. m_hCallHub = hCallHub;
  69. m_State = CHS_ACTIVE;
  70. m_dwFlags |= dwFlags;
  71. #if DBG
  72. m_pDebug = (PWSTR) ClientAlloc( 1 );
  73. #endif
  74. m_dwRef = 2;
  75. //
  76. // save in tapi's list
  77. //
  78. pTapi->AddCallHub( this );
  79. pTapi->AddRef();
  80. if ( NULL != hCallHub )
  81. {
  82. //
  83. // add it to the global hash table
  84. // hash table is only for callhubs with
  85. // hcallhub handles, because we only need
  86. // the hash table when tapi sends a message
  87. // with the tapi handle in it
  88. //
  89. gpCallHubHashTable->Lock();
  90. hr = gpCallHubHashTable->Insert( (ULONG_PTR)hCallHub, (ULONG_PTR)this, pTapi );
  91. gpCallHubHashTable->Unlock();
  92. //
  93. // see if there are any existing
  94. // calls for this callhub
  95. //
  96. FindExistingTapisrvCallhubCalls();
  97. }
  98. //
  99. // tell the app
  100. //
  101. CCallHubEvent::FireEvent(
  102. CHE_CALLHUBNEW,
  103. this,
  104. NULL,
  105. pTapi
  106. );
  107. Unlock();
  108. LOG((TL_TRACE, S_OK,"Initialize - exit" ));
  109. return S_OK;
  110. }
  111. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  112. //
  113. // Clear - clears the callhub. there is no native tapi way
  114. // to do this, so just iterate through all the calls and
  115. // try to drop them
  116. //
  117. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  118. STDMETHODIMP
  119. CCallHub::Clear()
  120. {
  121. HRESULT hr = S_OK;
  122. ITBasicCallControl * pCall;
  123. BOOL bFailure = FALSE;
  124. int iCount;
  125. CCall * pConferenceControllerCall;
  126. CTArray <ITBasicCallControl *> aLocalCalls;
  127. Lock();
  128. LOG((TL_TRACE, "Clear - enter "));
  129. //If there's a conference controller call - drop it
  130. if(m_pConferenceControllerCall != NULL)
  131. {
  132. LOG((TL_INFO, "Clear - disconnect conf controller call"));
  133. pConferenceControllerCall = m_pConferenceControllerCall;
  134. m_pConferenceControllerCall = NULL;
  135. Unlock();
  136. pConferenceControllerCall->Disconnect(DC_NORMAL);
  137. pConferenceControllerCall->Release();
  138. Lock();
  139. }
  140. //
  141. // go through all the calls
  142. //
  143. for (iCount = 0; iCount < m_CallArray.GetSize(); iCount++ )
  144. {
  145. //
  146. // try to get to the basic call control interface
  147. //
  148. hr = (m_CallArray[iCount])->QueryInterface(
  149. IID_ITBasicCallControl,
  150. (void **)&pCall
  151. );
  152. if (SUCCEEDED(hr))
  153. {
  154. //
  155. // Add it to our private list. We have to avoid doing
  156. // disconnect and release on a call while holding the
  157. // callhub lock. There is a timing window in between disconnect
  158. // and release where the disconnect call state event can lock
  159. // the call. Then it locks the callhub, which makes a deadlock.
  160. //
  161. aLocalCalls.Add(pCall);
  162. }
  163. else
  164. {
  165. bFailure = TRUE;
  166. }
  167. }
  168. Unlock();
  169. //
  170. // Now that we've unlocked the callhub (see above), go through our
  171. // private list of calls and drop and release each one.
  172. //
  173. for ( iCount = 0; iCount < aLocalCalls.GetSize(); iCount++ )
  174. {
  175. pCall = aLocalCalls[iCount];
  176. //
  177. // if we can, try to disconnect.
  178. //
  179. pCall->Disconnect(DC_NORMAL);
  180. pCall->Release();
  181. }
  182. //
  183. // clean up the list.
  184. //
  185. aLocalCalls.Shutdown();
  186. LOG((TL_TRACE, "Clear - exit "));
  187. return (bFailure?S_FALSE:S_OK);
  188. }
  189. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  190. //
  191. // just enumerate the calls
  192. //
  193. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  194. STDMETHODIMP
  195. CCallHub::EnumerateCalls(
  196. IEnumCall ** ppEnumCall
  197. )
  198. {
  199. HRESULT hr = S_OK;
  200. LOG((TL_TRACE, "EnumerateCalls enter" ));
  201. LOG((TL_TRACE, " ppEnumCalls----->%p", ppEnumCall ));
  202. if ( TAPIIsBadWritePtr( ppEnumCall, sizeof (IEnumCall *) ) )
  203. {
  204. LOG((TL_ERROR, "EnumCalls - bad pointer"));
  205. return E_POINTER;
  206. }
  207. //
  208. // create the enumerator
  209. //
  210. CComObject< CTapiEnum< IEnumCall, ITCallInfo, &IID_IEnumCall > > * p;
  211. hr = CComObject< CTapiEnum< IEnumCall, ITCallInfo, &IID_IEnumCall > >
  212. ::CreateInstance( &p );
  213. if (S_OK != hr)
  214. {
  215. LOG((TL_ERROR, "EnumerateCalls - could not create enum" ));
  216. return hr;
  217. }
  218. Lock();
  219. //
  220. // initialize it with our call
  221. //
  222. p->Initialize( m_CallArray );
  223. Unlock();
  224. //
  225. // return it
  226. //
  227. *ppEnumCall = p;
  228. LOG((TL_TRACE, "EnumerateCalls exit - return S_OK" ));
  229. return S_OK;
  230. }
  231. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  232. //
  233. // collection of calls
  234. //
  235. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  236. STDMETHODIMP
  237. CCallHub::get_Calls(
  238. VARIANT * pVariant
  239. )
  240. {
  241. HRESULT hr;
  242. IDispatch * pDisp;
  243. LOG((TL_TRACE, "get_Calls enter"));
  244. LOG((TL_TRACE, " pVariant ------->%p", pVariant));
  245. if ( TAPIIsBadWritePtr( pVariant, sizeof(VARIANT) ) )
  246. {
  247. LOG((TL_ERROR, "get_Calls - invalid pointer" ));
  248. return E_POINTER;
  249. }
  250. CComObject< CTapiCollection< ITCallInfo > > * p;
  251. CComObject< CTapiCollection< ITCallInfo > >::CreateInstance( &p );
  252. if (NULL == p)
  253. {
  254. LOG((TL_ERROR, "get_Calls - could not create collection" ));
  255. return E_OUTOFMEMORY;
  256. }
  257. Lock();
  258. //
  259. // initialize
  260. //
  261. hr = p->Initialize( m_CallArray );
  262. Unlock();
  263. if (S_OK != hr)
  264. {
  265. LOG((TL_ERROR, "get_Calls - could not initialize collection" ));
  266. delete p;
  267. return hr;
  268. }
  269. //
  270. // get the IDispatch interface
  271. //
  272. hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp );
  273. if (S_OK != hr)
  274. {
  275. LOG((TL_ERROR, "get_Calls - could not get IDispatch interface" ));
  276. delete p;
  277. return hr;
  278. }
  279. //
  280. // put it in the variant
  281. //
  282. VariantInit(pVariant);
  283. pVariant->vt = VT_DISPATCH;
  284. pVariant->pdispVal = pDisp;
  285. LOG((TL_TRACE, "get_Calls exit - return S_OK"));
  286. return S_OK;
  287. }
  288. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  289. //
  290. // get the current number of calls
  291. //
  292. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  293. STDMETHODIMP
  294. CCallHub::get_NumCalls(
  295. long * plCalls
  296. )
  297. {
  298. HRESULT hr = S_OK;
  299. if ( TAPIIsBadWritePtr( plCalls, sizeof(LONG) ) )
  300. {
  301. LOG((TL_ERROR, "get_NumCalls - bad pointer"));
  302. return E_POINTER;
  303. }
  304. Lock();
  305. *plCalls = m_CallArray.GetSize();
  306. Unlock();
  307. return hr;
  308. }
  309. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  310. //
  311. // get the current state
  312. //
  313. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  314. STDMETHODIMP
  315. CCallHub::get_State(
  316. CALLHUB_STATE * pState
  317. )
  318. {
  319. HRESULT hr = S_OK;
  320. if ( TAPIIsBadWritePtr( pState, sizeof (CALLHUB_STATE) ) )
  321. {
  322. LOG((TL_ERROR, "get_State - invalid pointer"));
  323. return E_POINTER;
  324. }
  325. Lock();
  326. *pState = m_State;
  327. Unlock();
  328. return hr;
  329. }
  330. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  331. //
  332. // release the object
  333. //
  334. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  335. BOOL
  336. CCallHub::ExternalFinalRelease()
  337. {
  338. HRESULT hr;
  339. int iCount;
  340. LOG((TL_TRACE, "CCallHub - FinalRelease - enter - this %p - hCallHub - %lx", this, m_hCallHub));
  341. Lock();
  342. #if DBG
  343. /*NikhilB: To avoid a hang*/
  344. if( m_pDebug != NULL )
  345. {
  346. ClientFree( m_pDebug );
  347. m_pDebug = NULL;
  348. }
  349. #endif
  350. m_pTAPI->RemoveCallHub( this );
  351. m_pTAPI->Release();
  352. for (iCount = 0; iCount < m_CallArray.GetSize(); iCount++ )
  353. {
  354. CCall * pCCall;
  355. pCCall = dynamic_cast<CCall *>(m_CallArray[iCount]);
  356. if ( NULL != pCCall )
  357. {
  358. pCCall->SetCallHub(NULL);
  359. }
  360. }
  361. m_CallArray.Shutdown();
  362. if ( NULL != m_pPrivate )
  363. {
  364. m_pPrivate->Release();
  365. }
  366. Unlock();
  367. LOG((TL_TRACE, "CCallHub - FinalRelease - exit"));
  368. return TRUE;
  369. }
  370. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  371. //
  372. // FindExistingTapisrvCallhubCalls
  373. //
  374. // internal function
  375. //
  376. // this is called when creating a 'tapisrv' callhub. this function
  377. // will call lineGetHubRelatedCalls, and add any already existing calls
  378. // to this callhub
  379. //
  380. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  381. HRESULT
  382. CCallHub::FindExistingTapisrvCallhubCalls()
  383. {
  384. LINECALLLIST * pCallHubList;
  385. HCALL * phCalls;
  386. DWORD dwCount;
  387. HRESULT hr;
  388. //
  389. // get the list of hcalls
  390. // related to this call
  391. //
  392. hr = LineGetHubRelatedCalls(
  393. m_hCallHub,
  394. 0,
  395. &pCallHubList
  396. );
  397. if ( !SUCCEEDED(hr) )
  398. {
  399. LOG((TL_ERROR, "FindExistingCalls - LineGetHubRelatedCalls "
  400. "failed %lx", hr));
  401. return hr;
  402. }
  403. //
  404. // get to the list of calls
  405. //
  406. phCalls = (HCALL *)(((LPBYTE)pCallHubList) + pCallHubList->dwCallsOffset);
  407. //
  408. // the first call is actually the callhub
  409. // that makes sense...
  410. //
  411. if (m_hCallHub != (HCALLHUB)(phCalls[0]))
  412. {
  413. LOG((TL_ERROR, "FindExistingCalls - callhub doesn't match"));
  414. _ASSERTE(0);
  415. ClientFree( pCallHubList );
  416. return E_FAIL;
  417. }
  418. //
  419. // go through the call handles and try to find the
  420. // objects
  421. //
  422. // phCalls[0] is the callhub, so skip it
  423. //
  424. for (dwCount = 1; dwCount < pCallHubList->dwCallsNumEntries; dwCount++)
  425. {
  426. CCall * pCall;
  427. ITCallInfo * pCallInfo;
  428. //
  429. // get the tapi3 call object
  430. //
  431. if (!FindCallObject(
  432. phCalls[dwCount],
  433. &pCall
  434. ))
  435. {
  436. LOG((TL_INFO, "FindExistingCalls - call handle %lx "
  437. "does not current exist", phCalls[dwCount]));
  438. continue;
  439. }
  440. //
  441. // tell the call
  442. //
  443. pCall->SetCallHub( this );
  444. if ( NULL == m_pAddress )
  445. {
  446. m_pAddress = pCall->GetCAddress();
  447. }
  448. //
  449. // get the callinfo interface
  450. //
  451. hr = pCall->QueryInterface(
  452. IID_ITCallInfo,
  453. (void **)&pCallInfo
  454. );
  455. //
  456. // findcallobject addrefs
  457. //
  458. pCall->Release();
  459. if ( !SUCCEEDED(hr) )
  460. {
  461. LOG((TL_ERROR, "FindExistingCalls - can't get callinfo interface"));
  462. _ASSERTE(0);
  463. continue;
  464. }
  465. //
  466. // save the call
  467. //
  468. m_CallArray.Add(pCallInfo);
  469. //
  470. // don't save a reference
  471. //
  472. pCallInfo->Release();
  473. }
  474. ClientFree( pCallHubList );
  475. return S_OK;
  476. }
  477. HRESULT
  478. CCallHub::FindCallsDisconnected(
  479. BOOL * fAllCallsDisconnected
  480. )
  481. {
  482. LINECALLLIST * pCallHubList;
  483. HCALL * phCalls;
  484. DWORD dwCount;
  485. HRESULT hr;
  486. CALL_STATE callState = CS_IDLE;
  487. *fAllCallsDisconnected = TRUE;
  488. Lock();
  489. //
  490. // get the list of hcalls
  491. // related to this call
  492. //
  493. hr = LineGetHubRelatedCalls(
  494. m_hCallHub,
  495. 0,
  496. &pCallHubList
  497. );
  498. if ( !SUCCEEDED(hr) )
  499. {
  500. LOG((TL_ERROR, "FindExistingCalls - LineGetHubRelatedCalls "
  501. "failed %lx", hr));
  502. Unlock();
  503. return hr;
  504. }
  505. //
  506. // get to the list of calls
  507. //
  508. phCalls = (HCALL *)(((LPBYTE)pCallHubList) + pCallHubList->dwCallsOffset);
  509. //
  510. // the first call is actually the callhub
  511. // that makes sense...
  512. //
  513. if (m_hCallHub != (HCALLHUB)(phCalls[0]))
  514. {
  515. LOG((TL_ERROR, "FindExistingCalls - callhub doesn't match"));
  516. _ASSERTE(0);
  517. ClientFree( pCallHubList );
  518. Unlock();
  519. return E_FAIL;
  520. }
  521. //
  522. // go through the call handles and try to find the
  523. // objects
  524. //
  525. // phCalls[0] is the callhub, so skip it
  526. //
  527. for (dwCount = 1; dwCount < pCallHubList->dwCallsNumEntries; dwCount++)
  528. {
  529. CCall * pCall;
  530. //
  531. // get the tapi3 call object
  532. //
  533. if (!FindCallObject(
  534. phCalls[dwCount],
  535. &pCall
  536. ))
  537. {
  538. LOG((TL_INFO, "FindExistingCalls - call handle %lx "
  539. "does not current exist", phCalls[dwCount]));
  540. continue;
  541. }
  542. pCall->get_CallState(&callState);
  543. //
  544. // findcallobject addrefs
  545. //
  546. pCall->Release();
  547. if( callState != CS_DISCONNECTED )
  548. {
  549. *fAllCallsDisconnected = FALSE;
  550. break;
  551. }
  552. }
  553. ClientFree( pCallHubList );
  554. Unlock();
  555. return S_OK;
  556. }
  557. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  558. //
  559. // CreateTapisrvCallHub
  560. //
  561. // Creates a callhub that is handled by tapisrv.
  562. //
  563. // pTAPI - owning tapi object
  564. //
  565. // hCallHub - tapi's handle for the call hub.
  566. //
  567. // ppCallHub - returned call hub with ref count of 1
  568. //
  569. //
  570. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  571. HRESULT
  572. CCallHub::CreateTapisrvCallHub(
  573. CTAPI * pTAPI,
  574. HCALLHUB hCallHub,
  575. CCallHub ** ppCallHub
  576. )
  577. {
  578. HRESULT hr;
  579. // CTAPIComObjectWithExtraRef<CCallHub> * p;
  580. CComObject<CCallHub> * p;
  581. STATICLOG((TL_TRACE, "CreateTapisrvCallHub - enter"));
  582. STATICLOG((TL_INFO, " hCallHub ---> %lx", hCallHub));
  583. //
  584. // create the object
  585. //
  586. //p = new CTAPIComObjectWithExtraRef<CCallHub>;
  587. hr = CComObject<CCallHub>::CreateInstance( &p );
  588. if (NULL == p)
  589. {
  590. STATICLOG((TL_INFO, "CreateTapisrvCallHub - createinstance failed"));
  591. return E_OUTOFMEMORY;
  592. }
  593. //
  594. // initialize it
  595. //
  596. p->Initialize(
  597. pTAPI,
  598. hCallHub,
  599. CALLHUBTYPE_CALLHUB
  600. );
  601. //
  602. // return object
  603. // NOTE:initialize addrefs for us!
  604. //
  605. *ppCallHub = p;
  606. STATICLOG((TL_TRACE, "CreateTapisrvCallHub - exit"));
  607. return S_OK;
  608. }
  609. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  610. //
  611. // CreateOrFakeCallHub
  612. //
  613. // creates a fake callhub
  614. //
  615. // pTAPI - owning TAPI object
  616. // pCall - call
  617. // ppCallHub - return new callhub object - ref count of 1
  618. //
  619. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  620. HRESULT
  621. CCallHub::CreateFakeCallHub(
  622. CTAPI * pTAPI,
  623. CCall * pCall,
  624. CCallHub ** ppCallHub
  625. )
  626. {
  627. HRESULT hr;
  628. CComObject<CCallHub> * p;
  629. STATICLOG((TL_TRACE, "CreateFakeCallHub - enter"));
  630. //
  631. // create the object
  632. //
  633. //p = new CTAPIComObjectWithExtraRef<CCallHub>;
  634. try
  635. {
  636. //
  637. // inside try in case critical section fails to be allocated
  638. //
  639. hr = CComObject<CCallHub>::CreateInstance( &p );
  640. }
  641. catch(...)
  642. {
  643. STATICLOG((TL_ERROR, "CreateFakeCallHub - failed to create a callhub -- exception"));
  644. p = NULL;
  645. }
  646. if (NULL == p)
  647. {
  648. STATICLOG((TL_INFO, "CreateFakeCallHub - createinstance failed"));
  649. return E_OUTOFMEMORY;
  650. }
  651. if ( (NULL == pTAPI) || (NULL == pCall) )
  652. {
  653. STATICLOG((TL_ERROR, "CreateFakeCallHub - invalid param"));
  654. _ASSERTE(0);
  655. delete p;
  656. return E_UNEXPECTED;
  657. }
  658. //
  659. // initialized
  660. //
  661. p->Initialize(
  662. pTAPI,
  663. NULL,
  664. CALLHUBTYPE_NONE
  665. );
  666. //
  667. // ZoltanS fix 11-12-98
  668. // Add the call to the fake callhub.
  669. // This in turn calls CCall::SetCallHub, which sets and addrefs the call's
  670. // member callhub pointer. When we return from here we will set the
  671. // callhub pointer again, and the reference that's released on
  672. // ExternalFinalRelease is in effect the initial reference from Initialize.
  673. // So we need to release here in order to avoid keeping an extra reference
  674. // to the callhub.
  675. //
  676. p->AddCall(pCall);
  677. ((CCallHub *) p)->Release();
  678. //
  679. // return object
  680. // NOTE: Initialize addrefs for us!
  681. //
  682. *ppCallHub = p;
  683. STATICLOG((TL_TRACE, "CreateFakeCallHub - exit"));
  684. return S_OK;
  685. }
  686. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  687. //
  688. // Remove Call
  689. //
  690. // remove a call object from the callhub's list
  691. //
  692. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  693. void
  694. CCallHub::RemoveCall(
  695. CCall * pCall
  696. )
  697. {
  698. HRESULT hr = S_OK;
  699. ITCallInfo * pCallInfo;
  700. hr = pCall->QueryInterface(
  701. IID_ITCallInfo,
  702. (void**)&pCallInfo
  703. );
  704. if ( !SUCCEEDED(hr) )
  705. {
  706. return;
  707. }
  708. Lock();
  709. m_CallArray.Remove( pCallInfo );
  710. Unlock();
  711. pCallInfo->Release();
  712. }
  713. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  714. //
  715. // CheckForIdle()
  716. //
  717. // internal function
  718. //
  719. // checks the state of the calls in the hub to see if it is idle
  720. //
  721. // so, we go through all the objects that are call objects, and
  722. // see if they are disconnected. if they all are, then the
  723. // hub is idle
  724. //
  725. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  726. void
  727. CCallHub::CheckForIdle()
  728. {
  729. HRESULT hr;
  730. int iCount;
  731. LOG((TL_ERROR, "CCallHub::CheckForIdle -Entered :%p", this ));
  732. Lock();
  733. //
  734. // go through the call list
  735. //
  736. for (iCount = 0; iCount < m_CallArray.GetSize() ; iCount++ )
  737. {
  738. CALL_STATE cs;
  739. //
  740. // get the callstate
  741. //
  742. (m_CallArray[iCount])->get_CallState( &cs );
  743. //
  744. // if anything is not disconnected, then
  745. // it's not idle
  746. //
  747. if ( CS_DISCONNECTED != cs )
  748. {
  749. Unlock();
  750. return;
  751. }
  752. }
  753. Unlock();
  754. //
  755. // if we haven't returned yet, the callhub is
  756. // idle
  757. //
  758. SetState(CHS_IDLE);
  759. LOG((TL_ERROR, "CCallHub::CheckForIdle -Exited :%p", this ));
  760. }
  761. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  762. //
  763. // CCallHub::SetState
  764. //
  765. // sets the state of the object. fires an event if necessary
  766. //
  767. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  768. void
  769. CCallHub::SetState(
  770. CALLHUB_STATE chs
  771. )
  772. {
  773. BOOL bEvent = FALSE;
  774. LOG((TL_ERROR, "CCallHub::SetState -Entered :%p", this ));
  775. Lock();
  776. if ( m_State != chs )
  777. {
  778. bEvent = TRUE;
  779. m_State = chs;
  780. }
  781. Unlock();
  782. if ( bEvent )
  783. {
  784. CALLHUB_EVENT che;
  785. if ( CHS_IDLE == chs )
  786. {
  787. che = CHE_CALLHUBIDLE;
  788. }
  789. else
  790. {
  791. che = CHE_CALLHUBNEW;
  792. }
  793. CCallHubEvent::FireEvent(
  794. che,
  795. this,
  796. NULL,
  797. m_pTAPI
  798. );
  799. LOG((TL_ERROR, "CCallHub::SetState -Exited :%p", this ));
  800. }
  801. }
  802. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  803. //
  804. // CCallHubEvent::FireEvent
  805. //
  806. // create and fire a callhub event
  807. //
  808. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  809. HRESULT
  810. CCallHubEvent::FireEvent(
  811. CALLHUB_EVENT Event,
  812. ITCallHub * pCallHub,
  813. ITCallInfo * pCall,
  814. CTAPI * pTapi
  815. )
  816. {
  817. CComObject<CCallHubEvent> * p;
  818. IDispatch * pDisp;
  819. HRESULT hr = S_OK;
  820. //
  821. // Check the event filter mask
  822. // This event is not filtered by TapiSrv because is
  823. // related with TE_CALLSTATE.
  824. //
  825. CCall* pCCall = (CCall*)pCall;
  826. if( pCCall )
  827. {
  828. DWORD dwEventFilterMask = 0;
  829. dwEventFilterMask = pCCall->GetSubEventsMask( TE_CALLHUB );
  830. if( !( dwEventFilterMask & GET_SUBEVENT_FLAG(Event)))
  831. {
  832. STATICLOG((TL_WARN, "FireEvent - filtering out this event [%lx]", Event));
  833. return S_OK;
  834. }
  835. }
  836. else
  837. {
  838. // Try with pTapi
  839. if( pTapi == NULL )
  840. {
  841. STATICLOG((TL_WARN, "FireEvent - filtering out this event [%lx]", Event));
  842. return S_OK;
  843. }
  844. long nEventMask = 0;
  845. pTapi->get_EventFilter( &nEventMask );
  846. if( (nEventMask & TE_CALLHUB) == 0)
  847. {
  848. STATICLOG((TL_WARN, "FireEvent - filtering out this event [%lx]", Event));
  849. return S_OK;
  850. }
  851. }
  852. //
  853. // create object
  854. //
  855. CComObject<CCallHubEvent>::CreateInstance( &p );
  856. if ( NULL == p )
  857. {
  858. STATICLOG((TL_ERROR, "CallHubEvent - could not create object"));
  859. return E_OUTOFMEMORY;
  860. }
  861. //
  862. // initialize
  863. //
  864. p->m_Event = Event;
  865. p->m_pCallHub = pCallHub;
  866. p->m_pCall = pCall;
  867. #if DBG
  868. p->m_pDebug = (PWSTR) ClientAlloc( 1 );
  869. #endif
  870. //
  871. // addref objects if valid
  872. //
  873. if ( NULL != pCallHub )
  874. {
  875. pCallHub->AddRef();
  876. }
  877. if ( NULL != pCall )
  878. {
  879. pCall->AddRef();
  880. }
  881. //
  882. // get the dispatch interface
  883. //
  884. hr = p->_InternalQueryInterface(
  885. IID_IDispatch,
  886. (void **)&pDisp
  887. );
  888. if (!SUCCEEDED(hr))
  889. {
  890. STATICLOG((TL_ERROR, "CallHubEvent - could not get dispatch interface"));
  891. delete p;
  892. return hr;
  893. }
  894. //
  895. // fire the event
  896. //
  897. pTapi->Event( TE_CALLHUB, pDisp );
  898. //
  899. // release our reference
  900. //
  901. pDisp->Release();
  902. return S_OK;
  903. }
  904. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  905. //
  906. // get_Event
  907. //
  908. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  909. STDMETHODIMP
  910. CCallHubEvent::get_Event(
  911. CALLHUB_EVENT * pEvent
  912. )
  913. {
  914. HRESULT hr = S_OK;
  915. if ( TAPIIsBadWritePtr( pEvent, sizeof (CALLHUB_EVENT) ) )
  916. {
  917. LOG((TL_ERROR, "get_Event - bad pointer"));
  918. return E_POINTER;
  919. }
  920. *pEvent = m_Event;
  921. return hr;
  922. }
  923. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  924. //
  925. // get_CallHub
  926. //
  927. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  928. STDMETHODIMP
  929. CCallHubEvent::get_CallHub(
  930. ITCallHub ** ppCallHub
  931. )
  932. {
  933. HRESULT hr = S_OK;
  934. if ( TAPIIsBadWritePtr( ppCallHub, sizeof (ITCallHub *) ) )
  935. {
  936. LOG((TL_ERROR, "get_CallHub - bad pointer"));
  937. return E_POINTER;
  938. }
  939. hr = m_pCallHub->QueryInterface(
  940. IID_ITCallHub,
  941. (void **)ppCallHub
  942. );
  943. return hr;
  944. }
  945. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  946. //
  947. // get_Call
  948. //
  949. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  950. STDMETHODIMP
  951. CCallHubEvent::get_Call(
  952. ITCallInfo ** ppCall
  953. )
  954. {
  955. HRESULT hr = S_OK;
  956. if ( TAPIIsBadWritePtr( ppCall, sizeof(ITCallInfo *) ) )
  957. {
  958. LOG((TL_ERROR, "get_Call - bad pointer"));
  959. return E_POINTER;
  960. }
  961. *ppCall = NULL;
  962. //
  963. // the call can be NULL
  964. //
  965. if ( NULL == m_pCall )
  966. {
  967. return S_FALSE;
  968. }
  969. hr = m_pCall->QueryInterface(
  970. IID_ITCallInfo,
  971. (void **)ppCall
  972. );
  973. return hr;
  974. }
  975. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  976. //
  977. //
  978. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  979. void
  980. CCallHubEvent::FinalRelease()
  981. {
  982. m_pCallHub->Release();
  983. if ( NULL != m_pCall )
  984. {
  985. m_pCall->Release();
  986. }
  987. #if DBG
  988. ClientFree( m_pDebug );
  989. #endif
  990. }
  991. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  992. //
  993. // HandleCallHubClose
  994. //
  995. // handle LINE_CALLHUBCLOSE message - find the callhub object
  996. // and clear the callhub handle from it
  997. //
  998. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  999. void
  1000. HandleCallHubClose( PASYNCEVENTMSG pParams )
  1001. {
  1002. CCallHub * pCallHub;
  1003. LOG((TL_INFO, "HandleCallHubClose %lx", pParams->Param1));
  1004. if ( FindCallHubObject(
  1005. (HCALLHUB)pParams->Param1,
  1006. &pCallHub
  1007. ) )
  1008. {
  1009. pCallHub->ClearCallHub();
  1010. pCallHub->Release();
  1011. }
  1012. }
  1013. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1014. //
  1015. // ClearCallHub
  1016. //
  1017. // clears the callhub handle in the object and removes the object
  1018. // from the callhub hash table
  1019. //
  1020. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1021. void
  1022. CCallHub::ClearCallHub()
  1023. {
  1024. HRESULT hr;
  1025. Lock();
  1026. gpCallHubHashTable->Lock();
  1027. hr = gpCallHubHashTable->Remove( (UINT_PTR) m_hCallHub );
  1028. m_hCallHub = NULL;
  1029. gpCallHubHashTable->Unlock();
  1030. Unlock();
  1031. }
  1032. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1033. //
  1034. // FindCallByHandle
  1035. //
  1036. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1037. CCall * CCallHub::FindCallByHandle(HCALL hCall)
  1038. {
  1039. ITBasicCallControl * pCall;
  1040. CCall * pCCall;
  1041. HRESULT hr;
  1042. int iCount;
  1043. Lock();
  1044. //
  1045. // go through the call list
  1046. //
  1047. for ( iCount = 0; iCount < m_CallArray.GetSize(); iCount++ )
  1048. {
  1049. //
  1050. // try to get to the basic call control interface
  1051. //
  1052. hr = (m_CallArray[iCount])->QueryInterface(
  1053. IID_ITBasicCallControl,
  1054. (void **)&pCall
  1055. );
  1056. if (SUCCEEDED(hr))
  1057. {
  1058. pCCall = dynamic_cast<CCall *>((ITBasicCallControl *)(pCall));
  1059. if ( NULL != pCCall )
  1060. {
  1061. //
  1062. // does this match?
  1063. //
  1064. if ( pCCall->GetHCall() == hCall )
  1065. {
  1066. Unlock();
  1067. return pCCall;
  1068. }
  1069. else
  1070. {
  1071. pCCall->Release();
  1072. }
  1073. }
  1074. }
  1075. }
  1076. Unlock();
  1077. //
  1078. // didn't find it
  1079. //
  1080. return NULL;
  1081. }
  1082. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1083. //
  1084. // CreateConferenceControllerCall
  1085. //
  1086. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1087. HRESULT CCallHub::CreateConferenceControllerCall(HCALL hCall, CAddress * pAddress )
  1088. {
  1089. HRESULT hr = S_OK;
  1090. CCall * pConferenceControllerCall;
  1091. LOG((TL_TRACE, "CreateConferenceController - enter"));
  1092. //
  1093. // create & initialize
  1094. //
  1095. hr = pAddress->InternalCreateCall(
  1096. NULL,
  1097. 0,
  1098. 0,
  1099. CP_OWNER,
  1100. FALSE,
  1101. hCall,
  1102. FALSE,
  1103. &pConferenceControllerCall
  1104. );
  1105. if ( SUCCEEDED(hr) )
  1106. {
  1107. pConferenceControllerCall->SetCallHub( this );
  1108. //
  1109. // save the call
  1110. //
  1111. Lock();
  1112. m_pConferenceControllerCall = pConferenceControllerCall;
  1113. Unlock();
  1114. }
  1115. else
  1116. {
  1117. LOG((TL_ERROR, "CreateConferenceController - could not create call instance"));
  1118. }
  1119. LOG((TL_TRACE, hr, "CreateConferenceController - exit"));
  1120. return hr;
  1121. }
  1122. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1123. //
  1124. // AddCall
  1125. //
  1126. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1127. void CCallHub::AddCall(CCall * pCall)
  1128. {
  1129. ITCallInfo * pCallInfo;
  1130. HRESULT hr = S_OK;
  1131. Lock();
  1132. //
  1133. // tell the call
  1134. //
  1135. pCall->SetCallHub( this );
  1136. if ( NULL == m_pAddress )
  1137. {
  1138. m_pAddress = pCall->GetCAddress();
  1139. }
  1140. //
  1141. // get the CallInfo interface
  1142. //
  1143. hr = pCall->QueryInterface(
  1144. IID_ITCallInfo,
  1145. (void **)&pCallInfo
  1146. );
  1147. if ( !SUCCEEDED(hr) )
  1148. {
  1149. _ASSERTE(0);
  1150. }
  1151. //
  1152. // save the Call
  1153. //
  1154. m_CallArray.Add( pCallInfo );
  1155. //
  1156. // don't save a reference
  1157. //
  1158. pCallInfo->Release();
  1159. Unlock();
  1160. CCallHubEvent::FireEvent(
  1161. CHE_CALLJOIN,
  1162. this,
  1163. pCallInfo,
  1164. m_pTAPI
  1165. );
  1166. }
  1167. CCall *
  1168. CCallHub::GetConferenceControllerCall()
  1169. {
  1170. CCall * pCall;
  1171. Lock();
  1172. pCall = m_pConferenceControllerCall;
  1173. Unlock();
  1174. return pCall;
  1175. }