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.

8499 lines
197 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. call.cpp
  5. Abstract:
  6. Implements helper functions for call object
  7. Author:
  8. mquinton - 4/17/97
  9. Notes:
  10. optional-notes
  11. Revision History:
  12. --*/
  13. #include "stdafx.h"
  14. #include "tapievt.h"
  15. extern ULONG_PTR GenerateHandleAndAddToHashTable( ULONG_PTR Element);
  16. extern void RemoveHandleFromHashTable(ULONG_PTR Handle);
  17. extern CHashTable * gpCallHubHashTable;
  18. extern CHashTable * gpCallHashTable;
  19. extern CHashTable * gpHandleHashTable;
  20. extern HANDLE ghAsyncRetryQueueEvent;
  21. DWORD gdwWaitForConnectSleepTime = 100;
  22. DWORD gdwWaitForConnectWaitIntervals = 600;
  23. char *callStateName(CALL_STATE callState);
  24. HRESULT
  25. ProcessNewCallPrivilege(
  26. DWORD dwPrivilege,
  27. CALL_PRIVILEGE * pCP
  28. );
  29. HRESULT
  30. ProcessNewCallState(
  31. DWORD dwCallState,
  32. DWORD dwDetail,
  33. CALL_STATE CurrentCallState,
  34. CALL_STATE * pCallState,
  35. CALL_STATE_EVENT_CAUSE * pCallStateCause
  36. );
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CCall
  39. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  40. //
  41. // Initialize the call object
  42. //
  43. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  44. HRESULT
  45. CCall::Initialize(
  46. CAddress * pAddress,
  47. PWSTR pszDestAddress,
  48. long lAddressType,
  49. long lMediaType,
  50. CALL_PRIVILEGE cp,
  51. BOOL bNeedToNotify,
  52. BOOL bExpose,
  53. HCALL hCall,
  54. CEventMasks* pEventMasks
  55. )
  56. {
  57. HRESULT hr = S_OK;
  58. IUnknown * pUnk = NULL;
  59. LOG((TL_TRACE,"Initialize - enter" ));
  60. LOG((TL_TRACE," pAddress ---------> %p", pAddress ));
  61. LOG((TL_TRACE," pszDestAddress ---> %p", pszDestAddress ));
  62. LOG((TL_TRACE," DestAddress is ---> %ls", pszDestAddress ));
  63. LOG((TL_TRACE," CallPrivilege ----> %d", cp ));
  64. LOG((TL_TRACE," bNeedToNotify ----> %d", bNeedToNotify ));
  65. LOG((TL_TRACE," hCall ------------> %lx", hCall ));
  66. //
  67. // good address object?
  68. //
  69. if (IsBadReadPtr(pAddress, sizeof(CAddress)))
  70. {
  71. LOG((TL_ERROR, "Initialize - - bad address pointer"));
  72. return E_INVALIDARG;
  73. }
  74. //
  75. // copy the destination address
  76. //
  77. if (NULL != pszDestAddress)
  78. {
  79. m_szDestAddress = (PWSTR) ClientAlloc(
  80. (lstrlenW(pszDestAddress) + 1) * sizeof (WCHAR)
  81. );
  82. if (NULL == m_szDestAddress)
  83. {
  84. LOG((TL_ERROR, E_OUTOFMEMORY,"Initialize - exit" ));
  85. return E_OUTOFMEMORY;
  86. }
  87. lstrcpyW(
  88. m_szDestAddress,
  89. pszDestAddress
  90. );
  91. }
  92. m_pCallParams = (LINECALLPARAMS *)ClientAlloc( sizeof(LINECALLPARAMS) + 1000 );
  93. if ( NULL == m_pCallParams )
  94. {
  95. ClientFree( m_szDestAddress );
  96. m_szDestAddress = NULL;
  97. LOG((TL_ERROR, E_OUTOFMEMORY,"Initialize - exit" ));
  98. return E_OUTOFMEMORY;
  99. }
  100. m_pCallParams->dwTotalSize = sizeof(LINECALLPARAMS) + 1000;
  101. m_dwCallParamsUsedSize = sizeof(LINECALLPARAMS);
  102. //
  103. // set original state
  104. //
  105. m_t3Call.hCall = hCall;
  106. m_t3Call.pCall = this;
  107. m_hAdditionalCall = NULL;
  108. m_CallPrivilege = cp;
  109. m_pAddress = pAddress;
  110. m_pAddress->AddRef();
  111. if( m_pAddress->GetAPIVersion() >= TAPI_VERSION3_0 )
  112. {
  113. m_pCallParams->dwAddressType = lAddressType;
  114. }
  115. m_dwMediaMode = lMediaType;
  116. //
  117. // Read the subevent mask from the
  118. // address parent object
  119. //
  120. pEventMasks->CopyEventMasks( &m_EventMasks);
  121. if (bNeedToNotify)
  122. {
  123. m_dwCallFlags |= CALLFLAG_NEEDTONOTIFY;
  124. }
  125. if (!bExpose)
  126. {
  127. m_dwCallFlags |= CALLFLAG_DONTEXPOSE;
  128. }
  129. //
  130. // keep 1 reference for the global hash table
  131. //
  132. if ( bNeedToNotify )
  133. {
  134. m_dwRef = 3;
  135. }
  136. else
  137. {
  138. m_dwRef = 2;
  139. }
  140. //
  141. // if we are the owner of the call, and the address has msp, attempt to
  142. // create msp call
  143. //
  144. if ( (CP_OWNER == m_CallPrivilege) && m_pAddress->HasMSP() )
  145. {
  146. hr = CreateMSPCall( lMediaType );
  147. if ( FAILED (hr) )
  148. {
  149. // If we fail to create an MSP call we can still use the call
  150. // for non media call control
  151. LOG((TL_ERROR, hr, "Initialize - CreateMSPCall failed"));
  152. }
  153. }
  154. //
  155. // put in global hash table
  156. //
  157. if ( NULL != m_t3Call.hCall )
  158. {
  159. AddCallToHashTable();
  160. }
  161. LOG((TL_TRACE,S_OK,"Initialize - exit" ));
  162. return S_OK;
  163. }
  164. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  165. //
  166. // ExternalFinalRelease
  167. // Clean up call object
  168. //
  169. // we have this special finalrelease because we keep our own reference
  170. // to the call. right before the ref count goes to 1 inside of release,
  171. // we call this. It is possible that the call's ref count could go up
  172. // again because of a message from tapisrv. So, we lock the hashtable,
  173. // then verify the refcount again. If we did process a message from
  174. // tapisrv for the call,the refcount will be increased, and we won't
  175. // do this finalrelease.
  176. //
  177. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  178. BOOL
  179. CCall::ExternalFinalRelease()
  180. {
  181. HRESULT hr = S_OK;
  182. CCallHub * pCallHub = NULL;
  183. LOG((TL_TRACE, "ExternalFinalRelease - enter" ));
  184. Lock();
  185. //
  186. // NikhilB: Call object has a reference to Callhub object so its safe to
  187. // lock the callhub object before locking the call. This is to avoid a
  188. // deadlock that happens dur to locking the call and the callhub in reverse
  189. // orders in different functions.
  190. //
  191. if( m_pCallHub != NULL )
  192. {
  193. m_pCallHub->AddRef();
  194. pCallHub = m_pCallHub;
  195. Unlock();
  196. // lock the callhub object before locking the call
  197. pCallHub->Lock();
  198. Lock();
  199. pCallHub->Release();
  200. }
  201. //
  202. // Check extra t3call used in conference legs
  203. //
  204. if (NULL != m_hAdditionalCall)
  205. {
  206. LOG((TL_INFO,"ExternalFinalRelease: Deallocating Addditional call"));
  207. LineDeallocateCall( m_hAdditionalCall );
  208. m_hAdditionalCall = NULL;
  209. }
  210. if (NULL != m_t3Call.hCall)
  211. {
  212. //
  213. // dealloc call
  214. //
  215. LOG((TL_INFO,"Deallocating call"));
  216. hr = LineDeallocateCall( m_t3Call.hCall );
  217. if (FAILED(hr))
  218. {
  219. LOG((TL_ERROR, hr, "ExternalFinalRelease - LineDeallocateCall failed" ));
  220. }
  221. m_t3Call.hCall = NULL;
  222. }
  223. //
  224. // clean up & release the callhub
  225. //
  226. if (NULL != pCallHub)
  227. {
  228. pCallHub->RemoveCall( this );
  229. Unlock();
  230. //
  231. // checkforidle will lock the callhub and then every call that belongs
  232. // to it. make this call outside call's lock to prevent deadlocks with
  233. // other threads that can possibly lock a call (which belongs to this
  234. // callhub) while trying to lock this callhub
  235. //
  236. pCallHub->CheckForIdle();
  237. Lock();
  238. pCallHub->Unlock();
  239. pCallHub = NULL;
  240. //release the refcount that call object has to the callhub.
  241. if(m_pCallHub != NULL)
  242. {
  243. m_pCallHub->Release();
  244. m_pCallHub = NULL;
  245. }
  246. }
  247. //
  248. // close the associated line
  249. //
  250. if ( ! ( m_dwCallFlags & CALLFLAG_NOTMYLINE ) )
  251. {
  252. m_pAddress->MaybeCloseALine( &m_pAddressLine );
  253. }
  254. //
  255. // remove the call from the address's list
  256. //
  257. m_pAddress->RemoveCall( (ITCallInfo *) this );
  258. //
  259. // free the dest address string
  260. //
  261. ClientFree(m_szDestAddress);
  262. m_szDestAddress = NULL;
  263. if ( NULL != m_pCallInfo )
  264. {
  265. ClientFree( m_pCallInfo );
  266. m_pCallInfo = NULL;
  267. m_dwCallFlags |= CALLFLAG_CALLINFODIRTY;
  268. }
  269. //
  270. // tell the msp the call is going away
  271. //
  272. if ( NULL != m_pMSPCall )
  273. {
  274. m_pAddress->ShutdownMSPCall( m_pMSPCall );
  275. m_pMSPCall->Release();
  276. }
  277. //
  278. // release the address
  279. //
  280. m_pAddress->Release();
  281. //
  282. // release the private object
  283. //
  284. if (NULL != m_pPrivate)
  285. {
  286. m_pPrivate->Release();
  287. }
  288. //
  289. //NikhilB:If this was a consultation call and is being dropped before
  290. //calling Finish on it then we should release the reference it holds to
  291. //the primary call object through m_pRelatedCall
  292. //
  293. if( NULL != m_pRelatedCall )
  294. {
  295. m_pRelatedCall->Release();
  296. m_pRelatedCall = NULL;
  297. m_dwCallFlags &= ~CALLFLAG_CONSULTCALL;
  298. }
  299. //
  300. // free any call params
  301. //
  302. if ( NULL != m_pCallParams )
  303. {
  304. ClientFree( m_pCallParams );
  305. m_pCallParams = NULL;
  306. }
  307. //
  308. // clean up the gather digits queue
  309. //
  310. m_GatherDigitsQueue.Shutdown();
  311. Unlock();
  312. LOG((TL_TRACE, "ExternalFinalRelease - exit" ));
  313. return TRUE;
  314. }
  315. //////////////////////////////////////////////////////////////////////////////
  316. void CCall::CallOnTapiShutdown()
  317. {
  318. LOG((TL_TRACE, "CallOnTapiShutdown - enter" ));
  319. //
  320. // we need to remove the call from the handle hash table to avoid duplicate
  321. // entries with the calls that are created later with the same call handle
  322. // (in case _this_ call object is still referenced by the app and is
  323. // still around
  324. //
  325. gpCallHashTable->Lock();
  326. gpCallHashTable->Remove( (ULONG_PTR)(m_t3Call.hCall) );
  327. gpCallHashTable->Unlock();
  328. LOG((TL_TRACE, "CallOnTapiShutdown - exit" ));
  329. }
  330. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  331. //
  332. // MyBasicCallControlQI
  333. // don't give out the basiccallcontrol interface
  334. // if the application does not own the call
  335. //
  336. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  337. HRESULT
  338. WINAPI
  339. MyBasicCallControlQI(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw)
  340. {
  341. LOG((TL_TRACE,"MyBasicCallControlQI - enter"));
  342. CALL_PRIVILEGE cp;
  343. ((CCall *)pv)->get_Privilege( &cp );
  344. if (CP_OWNER != cp)
  345. {
  346. LOG((TL_WARN,"The application is not the owner of this call"));
  347. LOG((TL_WARN,"so it cannot access the BCC interface"));
  348. return E_NOINTERFACE;
  349. }
  350. //
  351. // S_FALSE tells atl to continue querying for the interface
  352. //
  353. LOG((TL_INFO,"The application owns this call, so it can access the BCC interface"));
  354. LOG((TL_TRACE, "MyBasicCallControlQI - exit"));
  355. return S_FALSE;
  356. }
  357. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  358. //
  359. // TryToFindACallHub
  360. //
  361. // for an incoming call, tries to find an existing callhub.
  362. // the order of events (LINE_APPNEWCALL and LINE_APPNEWCALLHUB) is
  363. // not guaranteed.
  364. //
  365. // must be called in a Lock()
  366. //
  367. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  368. HRESULT
  369. CCall::TryToFindACallHub()
  370. {
  371. HRESULT hr;
  372. HCALLHUB hCallHub;
  373. CCallHub * pCallHub;
  374. //
  375. // do we already have a callhub?
  376. //
  377. if ( ( NULL == m_pCallHub ) && (NULL != m_t3Call.hCall ) )
  378. {
  379. //
  380. // no. Ask tapisrv for the hCallHub
  381. //
  382. hr = LineGetCallHub(
  383. m_t3Call.hCall,
  384. &hCallHub
  385. );
  386. //
  387. // if it fails, there is no hCallHub,
  388. // so try to create a fake one
  389. //
  390. if (!SUCCEEDED(hr))
  391. {
  392. hr = CheckAndCreateFakeCallHub();
  393. return hr;
  394. }
  395. //
  396. // if there is, find the correponding CallHub object
  397. //
  398. if (FindCallHubObject(
  399. hCallHub,
  400. &pCallHub
  401. ))
  402. {
  403. //
  404. // save it in the call
  405. //
  406. SetCallHub( pCallHub );
  407. //
  408. // tell it about this call
  409. // ZoltanS note: the following calls CCall::SetCallHub as well,
  410. // but this no longer results in an extra reference to the callhub
  411. // as we now check for that in CCall::SetCallHub.
  412. //
  413. pCallHub->AddCall( this );
  414. //
  415. // FindCallHubObject addrefs
  416. //
  417. pCallHub->Release();
  418. }
  419. }
  420. return S_OK;
  421. }
  422. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  423. //
  424. // SetRelatedCall
  425. //
  426. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  427. void CCall::SetRelatedCall(CCall * pCall, DWORD callFlags)
  428. {
  429. Lock();
  430. //
  431. // keep a reference to the related call
  432. //
  433. pCall->AddRef();
  434. //
  435. // save it
  436. //
  437. m_pRelatedCall = pCall;
  438. //
  439. // save the relavant call flags
  440. //
  441. m_dwCallFlags |= callFlags;
  442. Unlock();
  443. }
  444. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  445. //
  446. // ResetRelatedCall
  447. //
  448. // clear out the relate call stuff
  449. //
  450. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  451. void CCall::ResetRelatedCall()
  452. {
  453. Lock();
  454. //
  455. // release ref
  456. //
  457. if( m_pRelatedCall != NULL )
  458. {
  459. m_pRelatedCall->Release();
  460. m_pRelatedCall = NULL;
  461. }
  462. m_dwCallFlags &= ~(CALLFLAG_CONSULTCALL | CALLFLAG_CONFCONSULT | CALLFLAG_TRANSFCONSULT );
  463. Unlock();
  464. }
  465. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  466. //
  467. // CreateMSPCall
  468. //
  469. // tell the msp to create a call based on the give mediatype
  470. //
  471. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  472. HRESULT
  473. CCall::CreateMSPCall(
  474. long lMediaType
  475. )
  476. {
  477. HRESULT hr;
  478. IUnknown * pUnk;
  479. LOG((TL_TRACE,"CreateMSPCall - enter"));
  480. Lock();
  481. hr = _InternalQueryInterface( IID_IUnknown, (void**) &pUnk );
  482. if ( !SUCCEEDED(hr) )
  483. {
  484. LOG((TL_ERROR, "CreateMSPCall - cant get IUnk - %lx", hr));
  485. Unlock();
  486. return hr;
  487. }
  488. // Create a context handle to give the MSPCall object & associate it with
  489. //this object in the global handle hash table
  490. m_MSPCallHandle = (MSP_HANDLE) GenerateHandleAndAddToHashTable((ULONG_PTR)this);
  491. //
  492. // create a MSPCall - the address actually calls
  493. // into the msp for us.
  494. //
  495. hr = m_pAddress->CreateMSPCall(
  496. m_MSPCallHandle,
  497. 0,
  498. lMediaType,
  499. pUnk,
  500. &m_pMSPCall
  501. );
  502. pUnk->Release();
  503. Unlock();
  504. if (!SUCCEEDED(hr))
  505. {
  506. LOG((TL_ERROR, "CreateMSPCall failed, %x", hr ));
  507. }
  508. LOG((TL_TRACE,"CreateMSPCall - exit - returning %lx", hr));
  509. return hr;
  510. }
  511. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  512. //
  513. // DialConsultCall
  514. //
  515. // bSync - same as connect - should we wait to return until
  516. // the call is connected or disconnected?
  517. //
  518. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  519. HRESULT CCall::DialConsultCall(BOOL bSync)
  520. {
  521. HRESULT hr = S_OK;
  522. HANDLE hEvent;
  523. LOG((TL_TRACE, "DialConsultCall - enter" ));
  524. LOG((TL_TRACE, " bSync ---> %d", bSync ));
  525. Lock();
  526. // make sure they have selected media terminals
  527. //
  528. hr = m_pAddress->FindOrOpenALine(
  529. m_dwMediaMode,
  530. &m_pAddressLine
  531. );
  532. if (S_OK != hr)
  533. {
  534. Unlock();
  535. LOG((
  536. TL_ERROR,
  537. "DialConsultCall - FindOrOpenALine failed - %lx",
  538. hr
  539. ));
  540. return hr;
  541. }
  542. //
  543. // dial the call
  544. //
  545. hr = LineDial(
  546. m_t3Call.hCall,
  547. m_szDestAddress,
  548. m_dwCountryCode
  549. );
  550. if ( SUCCEEDED(hr) )
  551. {
  552. if (bSync)
  553. {
  554. hEvent = CreateConnectedEvent();
  555. }
  556. Unlock();
  557. //
  558. // wait for an async reply
  559. //
  560. hr = WaitForReply( hr );
  561. Lock();
  562. }
  563. if ( FAILED(hr) )
  564. {
  565. LOG((TL_ERROR, "DialConsultCall - LineDial failed - %lx", hr ));
  566. ClearConnectedEvent();
  567. m_CallState = CS_DISCONNECTED;
  568. m_pAddress->MaybeCloseALine( &m_pAddressLine );
  569. Unlock();
  570. return hr;
  571. }
  572. Unlock();
  573. if (bSync)
  574. {
  575. return SyncWait( hEvent );
  576. }
  577. LOG((TL_TRACE, "DialConsultCall - exit - return SUCCESS"));
  578. return S_OK;
  579. }
  580. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  581. //
  582. // OnDisconnect
  583. //
  584. // called when the call transitions into the disconnected state
  585. //
  586. // called in lock
  587. //
  588. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  589. HRESULT
  590. CCall::OnDisconnect()
  591. {
  592. CCallHub * pCallHub = NULL;
  593. LOG((TL_ERROR, "OnDisconnect - enter"));
  594. Lock();
  595. //
  596. // set the connected event if necessary
  597. //
  598. if ( NULL != m_hConnectedEvent )
  599. {
  600. SetEvent( m_hConnectedEvent );
  601. }
  602. //
  603. // special case for wavemsp
  604. //
  605. if ( OnWaveMSPCall() )
  606. {
  607. StopWaveMSPStream();
  608. }
  609. #ifdef USE_PHONEMSP
  610. else if ( OnPhoneMSPCall() )
  611. {
  612. StopPhoneMSPStream();
  613. }
  614. #endif USE_PHONEMSP
  615. //
  616. // check to see if the callhub
  617. // is idle
  618. //
  619. pCallHub = m_pCallHub;
  620. if ( NULL != pCallHub )
  621. {
  622. pCallHub->AddRef();
  623. Unlock();
  624. //
  625. // unlock the call before calling checkfor idle to prevent deadlocks
  626. //
  627. pCallHub->CheckForIdle();
  628. pCallHub->Release();
  629. }
  630. else
  631. {
  632. Unlock();
  633. }
  634. LOG((TL_ERROR, "OnDisconnect - finish"));
  635. return S_OK;
  636. }
  637. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  638. //
  639. // CCall::StartWaveMSPStream
  640. //
  641. // need to give it the waveID info and
  642. // tell it to start streaming
  643. //
  644. // the format of the blob given to the wave msp is:
  645. //
  646. // First DWORD = Command Second DWORD Third DWORD
  647. // ------------- ------- ------------ -----------
  648. // 0 Set wave IDs WaveIn ID WaveOut ID
  649. // 1 Start streaming <ignored> <ignored>
  650. // 2 Stop streaming <ignored> <ignored>
  651. // 3 <per-address, not per-call>
  652. // 4 <per-address, not per-call>
  653. // 5 Suspend streaming <ignored> <ignored>
  654. // 6 Resume streaming <ignored> <ignored>
  655. // 7 Wave IDs unavailable <ignored> <ignored>
  656. //
  657. //
  658. // called in lock()
  659. //
  660. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  661. HRESULT
  662. CCall::StartWaveMSPStream()
  663. {
  664. //
  665. // Get the stream control interface.
  666. //
  667. DWORD adwInfo[3];
  668. ITStreamControl * pStreamControl;
  669. pStreamControl = GetStreamControl();
  670. if ( NULL == pStreamControl )
  671. {
  672. return E_FAIL;
  673. }
  674. //
  675. // Get the per-call waveids, and report the results to the wavemsp.
  676. //
  677. HRESULT hr;
  678. hr = CreateWaveInfo(
  679. NULL,
  680. 0,
  681. m_t3Call.hCall,
  682. LINECALLSELECT_CALL,
  683. m_pAddress->HasFullDuplexWaveDevice(),
  684. adwInfo
  685. );
  686. if ( SUCCEEDED(hr) )
  687. {
  688. // 0 = set waveids
  689. adwInfo[0] = 0;
  690. // waveids filled in above
  691. }
  692. else
  693. {
  694. // 7: per-call waveids unavailable
  695. adwInfo[0] = 7;
  696. adwInfo[1] = 0;
  697. adwInfo[2] = 0;
  698. }
  699. m_pAddress->ReceiveTSPData(
  700. pStreamControl,
  701. (LPBYTE)adwInfo,
  702. sizeof(adwInfo)
  703. );
  704. //
  705. // now tell it to start streaming
  706. //
  707. adwInfo[0] = 1;
  708. adwInfo[1] = 0;
  709. adwInfo[2] = 0;
  710. m_pAddress->ReceiveTSPData(
  711. pStreamControl,
  712. (LPBYTE)adwInfo,
  713. sizeof(adwInfo)
  714. );
  715. pStreamControl->Release();
  716. return S_OK;
  717. }
  718. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  719. //
  720. // CCall::StopWaveMSPStream
  721. //
  722. // called in lock
  723. //
  724. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  725. HRESULT
  726. CCall::StopWaveMSPStream()
  727. {
  728. DWORD adwInfo[3];
  729. ITStreamControl * pStreamControl;
  730. adwInfo[0] = 2;
  731. pStreamControl = GetStreamControl();
  732. if ( NULL == pStreamControl )
  733. {
  734. return E_FAIL;
  735. }
  736. m_pAddress->ReceiveTSPData(
  737. pStreamControl,
  738. (LPBYTE)adwInfo,
  739. sizeof(adwInfo)
  740. );
  741. pStreamControl->Release();
  742. return S_OK;
  743. }
  744. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  745. //
  746. // CCall::SuspendWaveMSPStream
  747. //
  748. // called in lock
  749. //
  750. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  751. HRESULT
  752. CCall::SuspendWaveMSPStream()
  753. {
  754. DWORD adwInfo[3];
  755. ITStreamControl * pStreamControl;
  756. adwInfo[0] = 5;
  757. pStreamControl = GetStreamControl();
  758. if ( NULL == pStreamControl )
  759. {
  760. return E_FAIL;
  761. }
  762. m_pAddress->ReceiveTSPData(
  763. pStreamControl,
  764. (LPBYTE)adwInfo,
  765. sizeof(adwInfo)
  766. );
  767. pStreamControl->Release();
  768. return S_OK;
  769. }
  770. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  771. //
  772. // CCall::ResumeWaveMSPStream
  773. //
  774. // called in lock
  775. //
  776. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  777. HRESULT
  778. CCall::ResumeWaveMSPStream()
  779. {
  780. DWORD adwInfo[3];
  781. ITStreamControl * pStreamControl;
  782. adwInfo[0] = 6;
  783. pStreamControl = GetStreamControl();
  784. if ( NULL == pStreamControl )
  785. {
  786. return E_FAIL;
  787. }
  788. m_pAddress->ReceiveTSPData(
  789. pStreamControl,
  790. (LPBYTE)adwInfo,
  791. sizeof(adwInfo)
  792. );
  793. pStreamControl->Release();
  794. return S_OK;
  795. }
  796. #ifdef USE_PHONEMSP
  797. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  798. //
  799. // CCall::StartPhoneMSPStream
  800. //
  801. // called in lock
  802. //
  803. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  804. HRESULT
  805. CCall::StartPhoneMSPStream()
  806. {
  807. ITStreamControl * pStreamControl;
  808. DWORD dwControl = 0;
  809. pStreamControl = GetStreamControl();
  810. if ( NULL == pStreamControl )
  811. {
  812. return E_FAIL;
  813. }
  814. m_pAddress->ReceiveTSPData(
  815. pStreamControl,
  816. (LPBYTE)&dwControl,
  817. sizeof(DWORD)
  818. );
  819. pStreamControl->Release();
  820. return S_OK;
  821. }
  822. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  823. //
  824. // CCall::StopPhoneMSPStream
  825. //
  826. // called in lock
  827. //
  828. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  829. HRESULT
  830. CCall::StopPhoneMSPStream()
  831. {
  832. ITStreamControl * pStreamControl;
  833. DWORD dwControl = 1;
  834. pStreamControl = GetStreamControl();
  835. if ( NULL == pStreamControl )
  836. {
  837. return E_FAIL;
  838. }
  839. m_pAddress->ReceiveTSPData(
  840. pStreamControl,
  841. (LPBYTE)&dwControl,
  842. sizeof(DWORD)
  843. );
  844. pStreamControl->Release();
  845. return S_OK;
  846. }
  847. #endif USE_PHONEMSP
  848. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  849. //
  850. // OnConnect
  851. //
  852. // called when the call transitions to the connected state
  853. //
  854. // called in lock
  855. //
  856. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  857. HRESULT
  858. CCall::OnConnect()
  859. {
  860. HRESULT hr = S_OK;
  861. //
  862. // set connected event if it exists
  863. //
  864. if ( NULL != m_hConnectedEvent )
  865. {
  866. SetEvent( m_hConnectedEvent );
  867. }
  868. //
  869. // special cases
  870. //
  871. if (OnWaveMSPCall())
  872. {
  873. StartWaveMSPStream();
  874. }
  875. #ifdef USE_PHONEMSP
  876. else if ( OnPhoneMSPCall() )
  877. {
  878. StartPhoneMSPStream();
  879. }
  880. #endif USE_PHONEMSP
  881. return S_OK;
  882. }
  883. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  884. // Class : CCall
  885. // Method : CreateConference
  886. //
  887. //
  888. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  889. HRESULT
  890. CCall::CreateConference(
  891. CCall * pConsultationCall,
  892. VARIANT_BOOL bSync
  893. )
  894. {
  895. HRESULT hr = S_OK;
  896. HCALL hConfCall;
  897. HCALL hConsultCall;
  898. DWORD dwCallFeatures;
  899. CALL_STATE consultationCallState = CS_IDLE;
  900. LOG((TL_TRACE, "CreateConference - enter"));
  901. Lock();
  902. //
  903. // we must have a hub
  904. //
  905. if (m_pCallHub == NULL)
  906. {
  907. //
  908. // if this is happening, we have a bug. debug.
  909. //
  910. LOG((TL_ERROR, "CreateConference - no call hub. returning E_UNEXPECTED"));
  911. _ASSERTE(FALSE);
  912. Unlock();
  913. return E_UNEXPECTED;
  914. }
  915. //
  916. // Get Call Status to determine what features we can use
  917. //
  918. LPLINECALLSTATUS pCallStatus = NULL;
  919. hr = LineGetCallStatus( m_t3Call.hCall, &pCallStatus );
  920. if (!SUCCEEDED(hr))
  921. {
  922. LOG((TL_ERROR, "CreateConference - LineGetCallStatus failed %lx", hr));
  923. Unlock();
  924. return hr;
  925. }
  926. dwCallFeatures = pCallStatus->dwCallFeatures;
  927. ClientFree( pCallStatus );
  928. #if CHECKCALLSTATUS
  929. //
  930. // Do we support the required call features ?
  931. //
  932. if ( !( (dwCallFeatures & LINECALLFEATURE_SETUPCONF) &&
  933. (dwCallFeatures & LINECALLFEATURE_ADDTOCONF) ) )
  934. {
  935. LOG((TL_ERROR, "CreateConference - LineGetCallStatus reports Conference not supported"));
  936. Unlock();
  937. return E_FAIL;
  938. }
  939. #endif
  940. //
  941. // we support it, so try the Conference
  942. // Setup & dial the consultation Call
  943. //
  944. LOG((TL_INFO, "CreateConference - Trying to setupConference" ));
  945. pConsultationCall->Lock();
  946. pConsultationCall->FinishCallParams();
  947. hr = LineSetupConference(
  948. m_t3Call.hCall,
  949. &(m_pAddressLine->t3Line),
  950. &hConfCall,
  951. &hConsultCall,
  952. 3,
  953. m_pCallParams
  954. );
  955. Unlock();
  956. pConsultationCall->Unlock();
  957. if ( SUCCEEDED(hr) )
  958. {
  959. //
  960. // wait for async reply
  961. //
  962. hr = WaitForReply( hr );
  963. }
  964. if ( FAILED(hr) )
  965. {
  966. LOG((TL_INFO, "CreateConference - LineSetupConference failed - %lx", hr));
  967. return hr;
  968. }
  969. LOG((TL_INFO, "CreateConference - LineSetupConference completed OK"));
  970. //Check if the call is in connected state.
  971. pConsultationCall->Lock();
  972. pConsultationCall->get_CallState(&consultationCallState);
  973. if ( (consultationCallState == CS_CONNECTED) || (consultationCallState == CS_HOLD) )
  974. {
  975. //
  976. // the existing call is in a connected stae so we just need to deallocate
  977. // hConsultcall and do a finish() to call down to LineAddToConference()
  978. //
  979. if ( NULL != hConsultCall )
  980. {
  981. HRESULT hr2;
  982. hr2 = LineDrop( hConsultCall, NULL, 0 );
  983. if ( ((long)hr2) > 0 )
  984. {
  985. hr2 = WaitForReply( hr2 ) ;
  986. }
  987. hr = LineDeallocateCall( hConsultCall );
  988. hConsultCall = NULL;
  989. }
  990. if ( FAILED(hr) )
  991. {
  992. LOG((TL_INFO, "CreateConference - lineDeallocateCall failed - %lx", hr));
  993. }
  994. else
  995. {
  996. pConsultationCall->SetRelatedCall(
  997. this,
  998. CALLFLAG_CONFCONSULT|CALLFLAG_CONSULTCALL
  999. );
  1000. hr = S_OK;
  1001. }
  1002. pConsultationCall->Unlock();
  1003. Lock();
  1004. //
  1005. // Store the confcontroller in the callhub object
  1006. //
  1007. if (m_pCallHub != NULL)
  1008. {
  1009. m_pCallHub->CreateConferenceControllerCall(
  1010. hConfCall,
  1011. m_pAddress
  1012. );
  1013. }
  1014. else
  1015. {
  1016. //
  1017. // we made sure we had the hub when we entered the function
  1018. //
  1019. LOG((TL_INFO, "CreateConference - No CallHub"));
  1020. _ASSERTE(FALSE);
  1021. }
  1022. Unlock();
  1023. }
  1024. else
  1025. {
  1026. pConsultationCall->FinishSettingUpCall( hConsultCall );
  1027. pConsultationCall->Unlock();
  1028. Lock();
  1029. //
  1030. // Store the confcontroller in the callhub object
  1031. //
  1032. if (m_pCallHub != NULL)
  1033. {
  1034. m_pCallHub->CreateConferenceControllerCall(
  1035. hConfCall,
  1036. m_pAddress
  1037. );
  1038. }
  1039. else
  1040. {
  1041. LOG((TL_ERROR, "CreateConference - No CallHub"));
  1042. _ASSERTE(FALSE);
  1043. }
  1044. Unlock();
  1045. //
  1046. // now do the consulation call
  1047. //
  1048. hr = pConsultationCall->DialAsConsultationCall( this, dwCallFeatures, TRUE, bSync );
  1049. }
  1050. LOG((TL_TRACE, hr, "CreateConference - exit"));
  1051. return hr;
  1052. }
  1053. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1054. // Class : CCall
  1055. // Method : AddToConference
  1056. //
  1057. //
  1058. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1059. HRESULT
  1060. CCall::AddToConference(
  1061. CCall * pConsultationCall,
  1062. VARIANT_BOOL bSync
  1063. )
  1064. {
  1065. HRESULT hr = S_OK;
  1066. CCall * pConfContCall = NULL;
  1067. HCALL hConfContCall = NULL;
  1068. HCALL hConsultCall = NULL;
  1069. CALL_STATE consultationCallState = CS_IDLE;
  1070. DWORD dwCallFeatures;
  1071. LOG((TL_TRACE, "AddToConference - enter"));
  1072. Lock();
  1073. //
  1074. // we must have a hub
  1075. //
  1076. if (m_pCallHub == NULL)
  1077. {
  1078. //
  1079. // if this is happening, we have a bug. debug.
  1080. //
  1081. LOG((TL_ERROR,
  1082. "AddToConference - no call hub. returning E_UNEXPECTED"));
  1083. _ASSERTE(FALSE);
  1084. Unlock();
  1085. return E_UNEXPECTED;
  1086. }
  1087. {
  1088. //
  1089. // NikhilB: Call object has a reference to Callhub object so its safe to
  1090. // lock the callhub object before locking the call. This is to avoid a
  1091. // deadlock that happens dur to locking the call and the callhub in reverse
  1092. // orders in different functions.
  1093. //
  1094. m_pCallHub->AddRef();
  1095. AddRef();
  1096. Unlock();
  1097. // lock the callhub object before locking the call
  1098. m_pCallHub->Lock();
  1099. Lock();
  1100. Release();
  1101. m_pCallHub->Release();
  1102. }
  1103. //
  1104. // we must have conference controller
  1105. //
  1106. pConfContCall = m_pCallHub->GetConferenceControllerCall();
  1107. m_pCallHub->Unlock();
  1108. if (NULL == pConfContCall)
  1109. {
  1110. //
  1111. // if we get here, we have a bug. debug.
  1112. //
  1113. LOG((TL_ERROR,
  1114. "AddToConference - the callhub does not have a conference controller. E_UNEXPECTED"));
  1115. _ASSERTE(FALSE);
  1116. Unlock();
  1117. return E_UNEXPECTED;
  1118. }
  1119. //
  1120. // ask conference call controller for a conference call handle
  1121. //
  1122. hConfContCall = pConfContCall->GetHCall();
  1123. if (NULL == hConfContCall)
  1124. {
  1125. LOG((TL_ERROR,
  1126. "AddToConference - conf controller does not have a valid conf call handle. E_UNEXPECTED"));
  1127. _ASSERTE(FALSE);
  1128. Unlock();
  1129. return E_UNEXPECTED;
  1130. }
  1131. //
  1132. // Get Call Status to determine what features we can use
  1133. //
  1134. LPLINECALLSTATUS pCallStatus = NULL;
  1135. hr = LineGetCallStatus( m_t3Call.hCall, &pCallStatus );
  1136. if ( !SUCCEEDED(hr) )
  1137. {
  1138. LOG((TL_ERROR, "AddToConference - LineGetCallStatus failed %lx", hr));
  1139. Unlock();
  1140. return hr;
  1141. }
  1142. dwCallFeatures = pCallStatus->dwCallFeatures;
  1143. ClientFree( pCallStatus );
  1144. #if CHECKCALLSTATUS
  1145. //
  1146. // Do we support the required call features ?
  1147. //
  1148. if ( !( ( dwCallFeatures & LINECALLFEATURE_PREPAREADDCONF ) &&
  1149. ( dwCallFeatures & LINECALLFEATURE_ADDTOCONF ) ) )
  1150. {
  1151. LOG((TL_ERROR, "AddToConference - LineGetCallStatus reports Conference not supported"));
  1152. Unlock();
  1153. return E_FAIL;
  1154. }
  1155. #endif
  1156. //
  1157. // we support it, so try the Conference
  1158. //
  1159. pConsultationCall->get_CallState(&consultationCallState);
  1160. if ( (consultationCallState == CS_CONNECTED) || (consultationCallState == CS_HOLD) )
  1161. {
  1162. //
  1163. // the existing call is in a connected stae so we just need to to do a finish()
  1164. // to call down to LineAddToConference()
  1165. //
  1166. pConsultationCall->SetRelatedCall(
  1167. this,
  1168. CALLFLAG_CONFCONSULT|CALLFLAG_CONSULTCALL
  1169. );
  1170. Unlock();
  1171. return S_OK;
  1172. }
  1173. //
  1174. // We need to Setup & dial the consultation Call
  1175. //
  1176. //Lock();
  1177. pConsultationCall->Lock();
  1178. pConsultationCall->FinishCallParams();
  1179. hr = LinePrepareAddToConference(
  1180. hConfContCall,
  1181. &hConsultCall,
  1182. m_pCallParams
  1183. );
  1184. pConsultationCall->Unlock();
  1185. Unlock();
  1186. if ( SUCCEEDED(hr) )
  1187. {
  1188. //
  1189. // wait for async reply
  1190. //
  1191. hr = WaitForReply( hr );
  1192. if ( SUCCEEDED(hr) )
  1193. {
  1194. LONG lCap;
  1195. LOG((TL_INFO, "AddToConference - LinePrepareAddToConference completed OK"));
  1196. //
  1197. // Update handles in consult call object & insert it in the hash table
  1198. // note - we can miss messages if something comes in between the time time
  1199. // we get the reply, and the time we insert the call
  1200. //
  1201. pConsultationCall->Lock();
  1202. pConsultationCall->FinishSettingUpCall( hConsultCall );
  1203. pConsultationCall->Unlock();
  1204. //
  1205. // now do the consulation call
  1206. //
  1207. hr = pConsultationCall->DialAsConsultationCall( this, dwCallFeatures, TRUE, bSync );
  1208. }
  1209. else // AddToConference async reply failed
  1210. {
  1211. LOG((TL_ERROR, "AddToConference - LinePrepareAddToConference failed async" ));
  1212. }
  1213. }
  1214. else // AddToConference failed
  1215. {
  1216. LOG((TL_ERROR, "AddToConference - LinePrepareAddToConference failed" ));
  1217. }
  1218. LOG((TL_TRACE, hr, "AddToConference - exit"));
  1219. return hr;
  1220. }
  1221. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1222. // Class : CCall
  1223. // Method : WaitForCallState
  1224. //
  1225. //
  1226. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1227. HRESULT CCall::WaitForCallState( CALL_STATE requiredCS )
  1228. {
  1229. DWORD gdwWaitIntervals = 0;
  1230. HRESULT hr = E_FAIL;
  1231. LOG((TL_TRACE, "WaitForCallState - enter"));
  1232. while (
  1233. ( requiredCS != m_CallState ) &&
  1234. ( CS_DISCONNECTED != m_CallState ) &&
  1235. ( gdwWaitIntervals < gdwWaitForConnectWaitIntervals )
  1236. )
  1237. {
  1238. LOG((TL_INFO, "WaitForCallState - Waiting for state %d", requiredCS));
  1239. LOG((TL_INFO, " state is currently %d for call %p", m_CallState, this));
  1240. Sleep( gdwWaitForConnectSleepTime );
  1241. gdwWaitIntervals++;
  1242. }
  1243. if (m_CallState == requiredCS)
  1244. {
  1245. LOG((TL_INFO, "WaitForCallState - Reached required state"));
  1246. hr = S_OK;
  1247. }
  1248. else
  1249. {
  1250. LOG((TL_INFO, "WaitForCallState - Did not reach required state"));
  1251. }
  1252. LOG((TL_TRACE, hr, "WaitForCallState - exit"));
  1253. return(hr);
  1254. }
  1255. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1256. // Class : CCall
  1257. // Method : OneStepTransfer
  1258. //
  1259. //
  1260. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1261. HRESULT
  1262. CCall::OneStepTransfer(
  1263. CCall * pConsultationCall,
  1264. VARIANT_BOOL bSync
  1265. )
  1266. {
  1267. HRESULT hr = S_OK;
  1268. LPLINECALLPARAMS pCallParams;
  1269. DWORD dwDestAddrSize;
  1270. HCALL hCall;
  1271. HANDLE hEvent;
  1272. LOG((TL_TRACE, "OneStepTransfer - enter"));
  1273. //
  1274. // Setup call params structure for a one step transfer Consultation call
  1275. //
  1276. pConsultationCall->Lock();
  1277. dwDestAddrSize = (lstrlenW(pConsultationCall->m_szDestAddress) * sizeof(WCHAR)) + sizeof(WCHAR);
  1278. Lock();
  1279. hr = ResizeCallParams(dwDestAddrSize);
  1280. if( !SUCCEEDED(hr) )
  1281. {
  1282. pConsultationCall->Unlock();
  1283. Unlock();
  1284. LOG((TL_ERROR, "OneStepTransfer - resizecallparams failed %lx", hr));
  1285. return hr;
  1286. }
  1287. //
  1288. // Copy the string & set the size, offset etc
  1289. //
  1290. lstrcpyW((PWSTR)(((PBYTE)m_pCallParams) + m_dwCallParamsUsedSize),
  1291. pConsultationCall->m_szDestAddress);
  1292. if ( m_pAddress->GetAPIVersion() >= TAPI_VERSION2_0 )
  1293. {
  1294. m_pCallParams->dwTargetAddressSize = dwDestAddrSize;
  1295. m_pCallParams->dwTargetAddressOffset = m_dwCallParamsUsedSize;
  1296. }
  1297. m_dwCallParamsUsedSize += dwDestAddrSize;
  1298. //
  1299. // Set the one step bit flag
  1300. //
  1301. m_pCallParams->dwCallParamFlags |= LINECALLPARAMFLAGS_ONESTEPTRANSFER ;
  1302. FinishCallParams();
  1303. //
  1304. // Do the transfer
  1305. //
  1306. hr = LineSetupTransfer(
  1307. m_t3Call.hCall,
  1308. &hCall,
  1309. m_pCallParams
  1310. );
  1311. Unlock();
  1312. if ( SUCCEEDED(hr) )
  1313. {
  1314. hEvent = pConsultationCall->CreateConnectedEvent();
  1315. pConsultationCall->Unlock();
  1316. //
  1317. // wait for async reply
  1318. //
  1319. hr = WaitForReply( hr );
  1320. pConsultationCall->Lock();
  1321. }
  1322. if ( FAILED(hr) )
  1323. {
  1324. ClearConnectedEvent();
  1325. pConsultationCall->Unlock();
  1326. return hr;
  1327. }
  1328. LOG((TL_INFO, "OneStepTransfer - LineSetupTransfer completed OK"));
  1329. pConsultationCall->FinishSettingUpCall( hCall );
  1330. pConsultationCall->SetRelatedCall(
  1331. this,
  1332. CALLFLAG_TRANSFCONSULT|CALLFLAG_CONSULTCALL
  1333. );
  1334. pConsultationCall->Unlock();
  1335. if(bSync)
  1336. {
  1337. //
  1338. // Wait for connect on on our consultation call
  1339. //
  1340. hr = pConsultationCall->SyncWait( hEvent );
  1341. if( S_OK == hr )
  1342. {
  1343. LOG((TL_INFO, "OneStepTransfer - Consultation call connected" ));
  1344. }
  1345. else
  1346. {
  1347. LOG((TL_ERROR, "OneStepTransfer - Consultation call failed to connect" ));
  1348. hr = TAPI_E_OPERATIONFAILED;
  1349. }
  1350. }
  1351. LOG((TL_TRACE, hr, "OneStepTransfer - exit"));
  1352. return hr;
  1353. }
  1354. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1355. //
  1356. // UpdateStateAndPrivilege
  1357. //
  1358. // update the call state and privilege of this call
  1359. // this method is used when a call shows up in Unpark or Pickup
  1360. // and needs to have the correct state and priv
  1361. //
  1362. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1363. HRESULT
  1364. CCall::UpdateStateAndPrivilege()
  1365. {
  1366. HRESULT hr = S_OK;
  1367. LINECALLSTATUS * pCallStatus;
  1368. HCALL hCall;
  1369. Lock();
  1370. hCall = m_t3Call.hCall;
  1371. hr = LineGetCallStatus(
  1372. hCall,
  1373. &pCallStatus
  1374. );
  1375. if ( SUCCEEDED(hr) )
  1376. {
  1377. CALL_STATE cs;
  1378. CALL_STATE_EVENT_CAUSE csc;
  1379. CALL_PRIVILEGE cp;
  1380. hr = ProcessNewCallState(
  1381. pCallStatus->dwCallState,
  1382. 0,
  1383. m_CallState,
  1384. &cs,
  1385. &csc
  1386. );
  1387. SetCallState( cs );
  1388. hr = ProcessNewCallPrivilege(
  1389. pCallStatus->dwCallPrivilege,
  1390. &cp
  1391. );
  1392. m_CallPrivilege = cp;
  1393. ClientFree(pCallStatus);
  1394. }
  1395. Unlock();
  1396. return hr;
  1397. }
  1398. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1399. //
  1400. // ProcessNewCallState
  1401. // given a call state message (dwCallState, dwDetail, dwPriv)
  1402. // create a new tapi 3.0 callstate
  1403. //
  1404. // return S_OK if a new call state was created
  1405. // return S_FALSE if the message can be ignored (duplicate
  1406. // return E_? if bad error
  1407. //
  1408. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1409. HRESULT
  1410. CCall::ProcessNewCallState(
  1411. DWORD dwCallState,
  1412. DWORD dwDetail,
  1413. CALL_STATE CurrentCallState,
  1414. CALL_STATE * pCallState,
  1415. CALL_STATE_EVENT_CAUSE * pCallStateCause
  1416. )
  1417. {
  1418. HRESULT hr = S_OK;
  1419. CALL_STATE NewCallState = CurrentCallState;
  1420. LOG((TL_INFO, "ProcessNewCallState"));
  1421. LOG((TL_INFO, " dwCallState----->%lx", dwCallState));
  1422. LOG((TL_INFO, " dwDetail-------->%lx", dwDetail));
  1423. LOG((TL_INFO, " pCallState------>%p", pCallState));
  1424. LOG((TL_INFO, " pCallStateCause->%p", pCallStateCause));
  1425. *pCallStateCause = CEC_NONE;
  1426. switch (dwCallState)
  1427. {
  1428. case LINECALLSTATE_BUSY:
  1429. dwDetail = LINEDISCONNECTMODE_BUSY;
  1430. // fall through
  1431. case LINECALLSTATE_DISCONNECTED:
  1432. case LINECALLSTATE_IDLE:
  1433. {
  1434. NewCallState = CS_DISCONNECTED;
  1435. switch (dwDetail)
  1436. {
  1437. case LINEDISCONNECTMODE_REJECT:
  1438. *pCallStateCause = CEC_DISCONNECT_REJECTED;
  1439. break;
  1440. case LINEDISCONNECTMODE_BUSY:
  1441. *pCallStateCause = CEC_DISCONNECT_BUSY;
  1442. break;
  1443. case LINEDISCONNECTMODE_NOANSWER:
  1444. *pCallStateCause = CEC_DISCONNECT_NOANSWER;
  1445. break;
  1446. case LINEDISCONNECTMODE_BLOCKED:
  1447. *pCallStateCause = CEC_DISCONNECT_BLOCKED;
  1448. break;
  1449. case LINEDISCONNECTMODE_CONGESTION:
  1450. case LINEDISCONNECTMODE_INCOMPATIBLE:
  1451. case LINEDISCONNECTMODE_NODIALTONE:
  1452. case LINEDISCONNECTMODE_UNAVAIL:
  1453. case LINEDISCONNECTMODE_NUMBERCHANGED:
  1454. case LINEDISCONNECTMODE_OUTOFORDER:
  1455. case LINEDISCONNECTMODE_TEMPFAILURE:
  1456. case LINEDISCONNECTMODE_QOSUNAVAIL:
  1457. case LINEDISCONNECTMODE_DONOTDISTURB:
  1458. case LINEDISCONNECTMODE_CANCELLED:
  1459. *pCallStateCause = CEC_DISCONNECT_FAILED;
  1460. break;
  1461. case LINEDISCONNECTMODE_UNREACHABLE:
  1462. case LINEDISCONNECTMODE_BADADDRESS:
  1463. *pCallStateCause = CEC_DISCONNECT_BADADDRESS;
  1464. break;
  1465. case LINEDISCONNECTMODE_PICKUP:
  1466. case LINEDISCONNECTMODE_FORWARDED:
  1467. case LINEDISCONNECTMODE_NORMAL:
  1468. case LINEDISCONNECTMODE_UNKNOWN:
  1469. default:
  1470. *pCallStateCause = CEC_DISCONNECT_NORMAL;
  1471. break;
  1472. }
  1473. break;
  1474. }
  1475. case LINECALLSTATE_OFFERING:
  1476. {
  1477. switch (CurrentCallState)
  1478. {
  1479. case CS_IDLE:
  1480. if ( ! ( CALLFLAG_ACCEPTTOALERT & m_dwCallFlags ) )
  1481. {
  1482. NewCallState = CS_OFFERING;
  1483. }
  1484. else
  1485. {
  1486. LOG((TL_INFO, "ProcessNewCallState - ignoring LINECALLSTATE_OFFERING message as this is ISDN & needs a lineAccept"));
  1487. hr = S_FALSE;
  1488. }
  1489. break;
  1490. default:
  1491. LOG((TL_ERROR, "ProcessNewCallState - trying to go to OFFERING from bad state"));
  1492. hr = S_FALSE;
  1493. break;
  1494. }
  1495. break;
  1496. }
  1497. case LINECALLSTATE_ACCEPTED:
  1498. {
  1499. switch (CurrentCallState)
  1500. {
  1501. case CS_IDLE:
  1502. if ( CALLFLAG_ACCEPTTOALERT & m_dwCallFlags )
  1503. {
  1504. NewCallState = CS_OFFERING;
  1505. }
  1506. else
  1507. {
  1508. LOG((TL_INFO, "ProcessNewCallState - ignoring LINECALLSTATE_ACCEPTED message "));
  1509. hr = S_FALSE;
  1510. }
  1511. break;
  1512. default:
  1513. LOG((TL_ERROR, "ProcessNewCallState - trying to go to OFFERING from bad state"));
  1514. hr = S_FALSE;
  1515. break;
  1516. }
  1517. break;
  1518. }
  1519. case LINECALLSTATE_PROCEEDING:
  1520. case LINECALLSTATE_RINGBACK:
  1521. case LINECALLSTATE_DIALING:
  1522. case LINECALLSTATE_DIALTONE:
  1523. {
  1524. switch(CurrentCallState)
  1525. {
  1526. case CS_IDLE:
  1527. NewCallState = CS_INPROGRESS;
  1528. break;
  1529. case CS_INPROGRESS:
  1530. break;
  1531. default:
  1532. LOG((TL_ERROR, "ProcessNewCallState - trying to go to INPROGRESS from bad state"));
  1533. hr = S_FALSE;
  1534. break;
  1535. }
  1536. break;
  1537. }
  1538. case LINECALLSTATE_CONFERENCED:
  1539. case LINECALLSTATE_CONNECTED:
  1540. {
  1541. if ( CurrentCallState == CS_DISCONNECTED )
  1542. {
  1543. LOG((TL_ERROR, "ProcessNewCallState - invalid state going to CONNECTED"));
  1544. hr = S_FALSE;
  1545. }
  1546. else
  1547. {
  1548. NewCallState = CS_CONNECTED;
  1549. }
  1550. break;
  1551. }
  1552. case LINECALLSTATE_ONHOLDPENDCONF:
  1553. case LINECALLSTATE_ONHOLD:
  1554. case LINECALLSTATE_ONHOLDPENDTRANSFER:
  1555. {
  1556. switch(CurrentCallState)
  1557. {
  1558. case CS_HOLD:
  1559. break;
  1560. default:
  1561. NewCallState = CS_HOLD;
  1562. break;
  1563. }
  1564. break;
  1565. }
  1566. case LINECALLSTATE_SPECIALINFO:
  1567. {
  1568. LOG((TL_INFO, "ProcessNewCallState - ignoring message"));
  1569. hr = S_FALSE;
  1570. break;
  1571. }
  1572. case LINECALLSTATE_UNKNOWN:
  1573. {
  1574. LOG((TL_INFO, "ProcessNewCallState - LINECALLSTATE_UNKNOWN, so ignoring message"));
  1575. //return a failure as we don't want to processs this further
  1576. hr = E_FAIL;
  1577. break;
  1578. }
  1579. default:
  1580. break;
  1581. } // End switch(dwCallState)
  1582. if (NewCallState == CurrentCallState)
  1583. {
  1584. #if DBG
  1585. LOG((TL_INFO, "ProcessNewCallState - No State Change - still in %s",
  1586. callStateName(NewCallState) ));
  1587. #endif
  1588. hr = S_FALSE;
  1589. }
  1590. else // Valid change so update & return S_OK
  1591. {
  1592. #if DBG
  1593. LOG((TL_INFO, "ProcessNewCallState - State Transition %s -> %s",
  1594. callStateName(CurrentCallState),
  1595. callStateName(NewCallState) ));
  1596. #endif
  1597. *pCallState = NewCallState;
  1598. hr = S_OK;
  1599. }
  1600. LOG((TL_TRACE, "ProcessNewCallState - exit"));
  1601. LOG((TL_INFO, " *pCallState------->%lx", *pCallState));
  1602. LOG((TL_INFO, " *pCallStateCause-->%lx", *pCallStateCause));
  1603. return hr;
  1604. }
  1605. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1606. //
  1607. // GetOtherParty()
  1608. //
  1609. // Used to find the other party in a call ie,
  1610. // ___
  1611. // / \
  1612. // [A1]--hCall1--(this)--| CH1 |--(OtherCall)--hCall3--[A2]
  1613. // \___/
  1614. //
  1615. // AddRefs returned call
  1616. //
  1617. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1618. CCall* CCall::GetOtherParty()
  1619. {
  1620. LINECALLLIST * pCallHubList = NULL;
  1621. HCALL * phCalls;
  1622. HRESULT hr;
  1623. CCall * pCall = NULL;
  1624. //
  1625. // get the list of hcalls
  1626. // related to this call
  1627. //
  1628. hr = LineGetHubRelatedCalls(
  1629. 0,
  1630. m_t3Call.hCall,
  1631. &pCallHubList
  1632. );
  1633. if ( SUCCEEDED(hr) )
  1634. {
  1635. if (pCallHubList->dwCallsNumEntries >= 3)
  1636. {
  1637. //
  1638. // get to the list of calls
  1639. //
  1640. phCalls = (HCALL *)(((LPBYTE)pCallHubList) + pCallHubList->dwCallsOffset);
  1641. //
  1642. // the first call is the callhub, we want the third
  1643. //
  1644. FindCallObject(phCalls[2], &pCall);
  1645. }
  1646. }
  1647. if (pCallHubList)
  1648. {
  1649. ClientFree( pCallHubList );
  1650. }
  1651. return pCall;
  1652. }
  1653. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1654. //
  1655. // FindConferenceControllerCall()
  1656. //
  1657. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1658. CCall * CCall::FindConferenceControllerCall()
  1659. {
  1660. LINECALLLIST * pCallList;
  1661. HCALL * phCalls;
  1662. CCall * pCall = NULL;
  1663. HRESULT hr;
  1664. hr = LineGetConfRelatedCalls(
  1665. m_t3Call.hCall,
  1666. &pCallList
  1667. );
  1668. if ( SUCCEEDED(hr) )
  1669. {
  1670. //
  1671. // get to the list of calls
  1672. //
  1673. phCalls = (HCALL *)(((LPBYTE)pCallList) + pCallList->dwCallsOffset);
  1674. //
  1675. // The first call is the conf controller
  1676. // get its tapi3 call object
  1677. //
  1678. if (FindCallObject(phCalls[0], &pCall))
  1679. {
  1680. LOG((TL_INFO, "FindConferenceControllerCall - controller is %p "
  1681. ,pCall));
  1682. }
  1683. else
  1684. {
  1685. pCall = NULL;
  1686. LOG((TL_INFO, "FindConferenceControllerCall - call handle %lx "
  1687. "does not currently exist", phCalls[0]));
  1688. }
  1689. if(pCallList)
  1690. {
  1691. ClientFree( pCallList );
  1692. }
  1693. }
  1694. else
  1695. {
  1696. LOG((TL_ERROR, "FindExistingCalls - LineGetConfRelatedCalls failed "));
  1697. }
  1698. return pCall;
  1699. }
  1700. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1701. //
  1702. // AddCallToHashTable()
  1703. //
  1704. //
  1705. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1706. void CCall::AddCallToHashTable()
  1707. {
  1708. //
  1709. // put in global hash table
  1710. //
  1711. CTAPI *pTapi = m_pAddress->GetTapi();
  1712. if ( NULL != m_t3Call.hCall )
  1713. {
  1714. gpCallHashTable->Lock();
  1715. gpCallHashTable->Insert( (ULONG_PTR)(m_t3Call.hCall), (ULONG_PTR)this, pTapi );
  1716. gpCallHashTable->Unlock();
  1717. }
  1718. //
  1719. // Signal the asyncEventThread to wake up & process the retry queue
  1720. // since events may have come in for this call before it
  1721. // was in the hash table
  1722. //
  1723. SetEvent(ghAsyncRetryQueueEvent);
  1724. }
  1725. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1726. //
  1727. // OnConference()
  1728. //
  1729. // called in lock()
  1730. //
  1731. // called when call goes into conferenced state.
  1732. //
  1733. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1734. HRESULT
  1735. CCall::OnConference()
  1736. {
  1737. HRESULT hr = S_FALSE;
  1738. CCall * pCall = NULL;
  1739. CCall * pConfControllerCall = NULL;
  1740. CCall * pCallOtherParty = NULL;
  1741. CCallHub * pConferenceCallHub = NULL;
  1742. pConfControllerCall = FindConferenceControllerCall();
  1743. if (pConfControllerCall != NULL)
  1744. {
  1745. pConferenceCallHub = pConfControllerCall->GetCallHub();
  1746. //
  1747. // try & find this call in the callhub
  1748. //
  1749. if (pConferenceCallHub != NULL)
  1750. {
  1751. pCall = pConferenceCallHub->FindCallByHandle(m_t3Call.hCall);
  1752. if (pCall == NULL)
  1753. {
  1754. // Not in the same hub so this is the consultation call being added in
  1755. // see if there's a call object for the other party
  1756. //
  1757. // (ConfControllerCall)___
  1758. // \_________________
  1759. // / \
  1760. // [A1]--hCall1--(RelatedCall)--| ConferenceCallHub |--
  1761. // | \_________________/
  1762. // |
  1763. // | ___
  1764. // | / \
  1765. // --hCall2--(this)--| CH1 |--(CallOtherParty)--hCall3--[A3]
  1766. // \___/
  1767. //
  1768. LOG((TL_INFO, "OnConference - This is the consult call being conferenced " ));
  1769. /*
  1770. if ( NULL != (pCallOtherParty = GetOtherParty()) )
  1771. {
  1772. //
  1773. // Yes there is, so we're going to take this call out of the hash table
  1774. // & give the other call our hCall Handle;
  1775. //
  1776. LOG((TL_INFO, "OnConference - We have the other party , so give him our hCall %x", m_t3Call.hCall));
  1777. RemoveCallFromHashTable();
  1778. // release the callhub
  1779. //
  1780. if (NULL != m_pCallHub)
  1781. {
  1782. m_pCallHub->RemoveCall( this );
  1783. // m_pCallHub->Release();
  1784. }
  1785. pCallOtherParty->Lock();
  1786. pCallOtherParty->m_hAdditionalCall = m_t3Call.hCall;
  1787. pCallOtherParty->Unlock();
  1788. m_t3Call.hCall = NULL;
  1789. hr = S_OK;
  1790. }
  1791. */
  1792. }
  1793. else
  1794. {
  1795. LOG((TL_INFO, "OnConference - This is the initial call being conferenced " ));
  1796. pCall->Release(); // FindCallByHandle addRefs
  1797. }
  1798. }
  1799. else
  1800. {
  1801. LOG((TL_INFO, "OnConference - Couldn't find conference CallHub " ));
  1802. }
  1803. pConfControllerCall->Release(); // FindConferenceControllerCall addrefs
  1804. }
  1805. else
  1806. {
  1807. LOG((TL_ERROR, "OnConference - Couldn't find conference controller " ));
  1808. }
  1809. return hr;
  1810. }
  1811. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1812. //
  1813. // ProcessNewCallPrivilege
  1814. //
  1815. // converts a tapi2 callpriv to a tapi3 call priv.
  1816. //
  1817. // returns S_OK if there was a priv
  1818. // returns S_FALSE if priv was 0 (indicating there was no change)
  1819. // returns E_UNEXPECTED if the priv wasn't recognized
  1820. //
  1821. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1822. HRESULT
  1823. ProcessNewCallPrivilege(
  1824. DWORD dwPrivilege,
  1825. CALL_PRIVILEGE * pCP
  1826. )
  1827. {
  1828. if ( 0 == dwPrivilege )
  1829. {
  1830. return S_FALSE;
  1831. }
  1832. if ( LINECALLPRIVILEGE_OWNER == dwPrivilege )
  1833. {
  1834. *pCP = CP_OWNER;
  1835. return S_OK;
  1836. }
  1837. if ( LINECALLPRIVILEGE_MONITOR == dwPrivilege )
  1838. {
  1839. *pCP = CP_MONITOR;
  1840. S_OK;
  1841. }
  1842. return E_UNEXPECTED;
  1843. }
  1844. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1845. //
  1846. // CallStateEvent
  1847. // process call state events, and queue an event to the app
  1848. // if necessary
  1849. //
  1850. //
  1851. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1852. HRESULT
  1853. CCall::CallStateEvent(
  1854. PASYNCEVENTMSG pParams
  1855. )
  1856. {
  1857. HRESULT hr = S_OK;
  1858. HRESULT hrCallStateEvent;
  1859. HRESULT hrCallPrivilege;
  1860. BOOL bNeedToNotify;
  1861. CONNECTDATA cd;
  1862. AddressLineStruct * pLine;
  1863. CALL_STATE CallState;
  1864. CALL_STATE_EVENT_CAUSE CallStateCause;
  1865. CALL_PRIVILEGE newCP;
  1866. LOG((TL_INFO, "CallStateEvent - enter hCall %lx", m_t3Call.hCall));
  1867. //
  1868. // pParams->OpenContext is the 32-bit handle for AddressLineStruct
  1869. //
  1870. LOG((TL_INFO, "CallStateEvent: pParams->OpenContext %p", pParams->OpenContext ));
  1871. //
  1872. // recover the ptr value of AddressLineStruct from the 32-bit handle
  1873. //
  1874. pLine = GetAddRefAddressLine(pParams->OpenContext);
  1875. if ( NULL == pLine )
  1876. {
  1877. //
  1878. // pLine is NULL, the line must have already been closed before we got this event.
  1879. //
  1880. LOG((TL_WARN, "CallStateEvent - pLine is NULL"));
  1881. return S_OK;
  1882. }
  1883. LOG((TL_INFO, "CallStateEvent: pLine %p", pLine));
  1884. Lock();
  1885. if ( NULL == m_pAddressLine )
  1886. {
  1887. m_pAddressLine = pLine;
  1888. m_dwCallFlags |= CALLFLAG_NOTMYLINE;
  1889. }
  1890. //
  1891. // keep callback instance for this line
  1892. //
  1893. long lCallbackInstance = pLine->lCallbackInstance;
  1894. //
  1895. // no longer need address line itself
  1896. //
  1897. // (this needs to be done outside call lock)
  1898. Unlock();
  1899. ReleaseAddressLine(pLine);
  1900. pLine = NULL;
  1901. Lock();
  1902. if (pParams->Param1 == LINECALLSTATE_OFFERING)
  1903. {
  1904. OnOffering();
  1905. }
  1906. else if (pParams->Param1 == LINECALLSTATE_CONFERENCED)
  1907. {
  1908. if( OnConference() == S_OK)
  1909. {
  1910. pParams->Param1 = LINECALLSTATE_IDLE;
  1911. pParams->Param2 = LINEDISCONNECTMODE_UNKNOWN;
  1912. }
  1913. }
  1914. else if (pParams->Param1 == LINECALLSTATE_ONHOLDPENDCONF)
  1915. {
  1916. //
  1917. // This is a cnf controller call so hide it
  1918. //
  1919. LOG((TL_INFO, "CallStateEvent - This is a conference controller call, so hide it"));
  1920. m_dwCallFlags |= CALLFLAG_DONTEXPOSE;
  1921. m_dwCallFlags &= ~CALLFLAG_NEEDTONOTIFY;
  1922. }
  1923. bNeedToNotify = m_dwCallFlags & CALLFLAG_NEEDTONOTIFY;
  1924. //
  1925. // verify and get the new state
  1926. //
  1927. hrCallStateEvent = ProcessNewCallState(
  1928. pParams->Param1,
  1929. pParams->Param2,
  1930. m_CallState,
  1931. &CallState,
  1932. &CallStateCause
  1933. );
  1934. hrCallPrivilege = ProcessNewCallPrivilege(
  1935. pParams->Param3,
  1936. &newCP
  1937. );
  1938. if ( S_OK == hrCallPrivilege )
  1939. {
  1940. if ( m_CallPrivilege != newCP )
  1941. {
  1942. if ( !bNeedToNotify )
  1943. {
  1944. //
  1945. // callpriv changed. send a new call notification event
  1946. //
  1947. m_CallPrivilege = newCP;
  1948. CAddress *pAddress = m_pAddress;
  1949. pAddress->AddRef();
  1950. Unlock();
  1951. CCallInfoChangeEvent::FireEvent(
  1952. this,
  1953. CIC_PRIVILEGE,
  1954. pAddress->GetTapi(),
  1955. lCallbackInstance
  1956. );
  1957. Lock();
  1958. pAddress->Release();
  1959. pAddress = NULL;
  1960. }
  1961. }
  1962. }
  1963. if ( FAILED(hrCallStateEvent) ||
  1964. FAILED(hrCallPrivilege) )
  1965. {
  1966. //
  1967. // bad failure
  1968. // We get here if we had LINECALLSTATE_UNKNOWN
  1969. //
  1970. Unlock();
  1971. return S_OK;
  1972. }
  1973. //
  1974. // if it's s_ok, then the callstate
  1975. // changed, so do relevant stuff
  1976. //
  1977. else if (S_OK == hrCallStateEvent)
  1978. {
  1979. LOG((TL_ERROR, "CCall::Changing call state :%p", this ));
  1980. //
  1981. // save the callstate
  1982. //
  1983. SetCallState( CallState );
  1984. //
  1985. // do relevant processing on call
  1986. //
  1987. if (CS_CONNECTED == m_CallState)
  1988. {
  1989. OnConnect();
  1990. }
  1991. else if (CS_DISCONNECTED == m_CallState)
  1992. {
  1993. LOG((TL_ERROR, "CCall::Changing call state to disconnect:%p", this ));
  1994. Unlock();
  1995. //
  1996. // do not hold call's lock while calling disconnect , to prevent deadlocks with callhub
  1997. //
  1998. OnDisconnect();
  1999. Lock();
  2000. }
  2001. }
  2002. else
  2003. {
  2004. //
  2005. // if we are here, ProcessNewCallState returned
  2006. // S_FALSE, indicating we are already in the
  2007. // correct callstate
  2008. // if we don't need to notify the app of the call
  2009. // then we can return right here
  2010. //
  2011. if ( !bNeedToNotify )
  2012. {
  2013. LOG((TL_TRACE, "CallStateEvent - ProcessNewCallState returned %lx - ignoring message", hr ));
  2014. Unlock();
  2015. return S_OK;
  2016. }
  2017. }
  2018. //
  2019. // if this is a new call
  2020. // find out the mediamode
  2021. // and tell the app about the
  2022. // new call
  2023. //
  2024. if ( bNeedToNotify )
  2025. {
  2026. LPLINECALLINFO pCallInfo = NULL;
  2027. TryToFindACallHub();
  2028. hr = LineGetCallInfo(
  2029. m_t3Call.hCall,
  2030. &pCallInfo
  2031. );
  2032. if (S_OK != hr)
  2033. {
  2034. if (NULL != pCallInfo)
  2035. {
  2036. ClientFree( pCallInfo );
  2037. }
  2038. LOG((TL_ERROR, "CallStateEvent - LineGetCallInfo returned %lx", hr ));
  2039. LOG((TL_ERROR, "CallStateEvent - can't set new mediamode"));
  2040. //
  2041. // since we could not get media mode, keep media mode that we
  2042. // received on initalization
  2043. //
  2044. }
  2045. else
  2046. {
  2047. SetMediaMode( pCallInfo->dwMediaMode );
  2048. {
  2049. // get rid of unknown bit
  2050. SetMediaMode( m_dwMediaMode & ~LINEMEDIAMODE_UNKNOWN );
  2051. }
  2052. LOG((TL_INFO, "CallStateEvent - new call media modes is %lx", m_dwMediaMode ));
  2053. ClientFree(pCallInfo);
  2054. }
  2055. LOG((TL_INFO, "Notifying app of call" ));
  2056. //
  2057. // now, create and fire the callnotification event
  2058. //
  2059. CAddress *pAddress = m_pAddress;
  2060. pAddress->AddRef();
  2061. CALL_NOTIFICATION_EVENT Priveledge = (m_CallPrivilege == CP_OWNER) ? CNE_OWNER : CNE_MONITOR;
  2062. Unlock();
  2063. hr = CCallNotificationEvent::FireEvent(
  2064. (ITCallInfo *)this,
  2065. Priveledge,
  2066. pAddress->GetTapi(),
  2067. lCallbackInstance
  2068. );
  2069. Lock();
  2070. pAddress->Release();
  2071. pAddress = NULL;
  2072. if (!SUCCEEDED(hr))
  2073. {
  2074. LOG((TL_ERROR, "CallNotificationEvent failed %lx", hr));
  2075. }
  2076. //
  2077. // if it was needtonotify, we had an extra ref
  2078. // count, so get rid of it now
  2079. //
  2080. Release();
  2081. //
  2082. // just notify of existence once
  2083. //
  2084. m_dwCallFlags = m_dwCallFlags & ~CALLFLAG_NEEDTONOTIFY;
  2085. }
  2086. if ( S_OK == hrCallStateEvent )
  2087. {
  2088. //
  2089. // create the call state event object
  2090. //
  2091. LOG((TL_INFO, "Firing CallStateEvent"));
  2092. CAddress *pAddress = m_pAddress;
  2093. pAddress->AddRef();
  2094. Unlock();
  2095. hr = CCallStateEvent::FireEvent(
  2096. (ITCallInfo *)this,
  2097. CallState,
  2098. CallStateCause,
  2099. pAddress->GetTapi(),
  2100. lCallbackInstance
  2101. );
  2102. if (!SUCCEEDED(hr))
  2103. {
  2104. LOG((TL_ERROR, "CallStateEvent - fire event failed %lx", hr));
  2105. }
  2106. //
  2107. // Go through the phones and call our event hooks
  2108. //
  2109. ITPhone * pPhone;
  2110. CPhone * pCPhone;
  2111. int iPhoneCount;
  2112. PhoneArray PhoneArray;
  2113. //
  2114. // Get a copy of the phone array from tapi. This copy will contain
  2115. // references to all the phone objects.
  2116. //
  2117. pAddress->GetTapi()->GetPhoneArray( &PhoneArray );
  2118. pAddress->Release();
  2119. pAddress = NULL;
  2120. //
  2121. // stay unlocked while we are messing with the phone objects, otherwise
  2122. // we risk deadlock if a phone object would try to access call methods.
  2123. //
  2124. for(iPhoneCount = 0; iPhoneCount < PhoneArray.GetSize(); iPhoneCount++)
  2125. {
  2126. pPhone = PhoneArray[iPhoneCount];
  2127. pCPhone = dynamic_cast<CPhone *>(pPhone);
  2128. pCPhone->Automation_CallState( (ITCallInfo *)this, CallState, CallStateCause );
  2129. }
  2130. //
  2131. // Release all the phone objects.
  2132. //
  2133. PhoneArray.Shutdown();
  2134. Lock();
  2135. }
  2136. LOG((TL_TRACE, "CallStateEvent - exit - return SUCCESS" ));
  2137. Unlock();
  2138. return S_OK;
  2139. }
  2140. //////////////////////////////////////////////////////////////////////////////
  2141. AddressLineStruct *CCall::GetAddRefMyAddressLine()
  2142. {
  2143. LOG((TL_INFO, "GetAddRefMyAddressLine - enter."));
  2144. Lock();
  2145. //
  2146. // have address line?
  2147. //
  2148. if ( NULL == m_pAddressLine )
  2149. {
  2150. LOG((TL_WARN, "GetAddRefMyAddressLine - no address line"));
  2151. Unlock();
  2152. return NULL;
  2153. }
  2154. //
  2155. // get address
  2156. //
  2157. if (NULL == m_pAddress)
  2158. {
  2159. LOG((TL_ERROR, "GetAddRefMyAddressLine - no address"));
  2160. Unlock();
  2161. return NULL;
  2162. }
  2163. //
  2164. // get the address line
  2165. //
  2166. AddressLineStruct *pLine = m_pAddressLine;
  2167. //
  2168. // keep a reference to the address for after we unlock the call
  2169. //
  2170. CAddress *pAddress = m_pAddress;
  2171. pAddress->AddRef();
  2172. //
  2173. // unlock
  2174. //
  2175. Unlock();
  2176. //
  2177. // lock the address (so address line does not go away before we addref it)
  2178. //
  2179. pAddress->Lock();
  2180. //
  2181. // does our address manage this line? if so, get a refcount on that line.
  2182. //
  2183. if (!pAddress->IsValidAddressLine(pLine, TRUE))
  2184. {
  2185. LOG((TL_ERROR, "GetAddRefMyAddressLine - not one of the address' lines"));
  2186. //
  2187. // assume this line is plain bad. in which case there is no need to
  2188. // undo the addref (we cannot do it anyway, since we don't have the
  2189. // address which the line belongs to so we cannot maybeclosealine it.)
  2190. //
  2191. //
  2192. // unlock and release the address
  2193. //
  2194. pAddress->Unlock();
  2195. pAddress->Release();
  2196. return NULL;
  2197. }
  2198. //
  2199. // unlock the address
  2200. //
  2201. pAddress->Unlock();
  2202. //
  2203. // no need to keep the reference to the address anymore
  2204. //
  2205. pAddress->Release();
  2206. //
  2207. // all done. return pLine.
  2208. //
  2209. LOG((TL_INFO, "GetAddRefMyAddressLine - finish. pLine = %p", pLine));
  2210. return pLine;
  2211. }
  2212. //////////////////////////////////////////////////////////////////////////////
  2213. //
  2214. // CCall::GetAddRefAddressLine()
  2215. //
  2216. // this function returns a pointer to an addreff'ed address line on success
  2217. // or NULL on failure
  2218. //
  2219. // this function should be called OUTSIDE call lock to prevent deadlocks
  2220. //
  2221. AddressLineStruct *CCall::GetAddRefAddressLine(DWORD dwAddressLineHandle)
  2222. {
  2223. LOG((TL_INFO, "GetAddRefAddressLine - enter. dwAddressLineHandle[0x%lx]",
  2224. dwAddressLineHandle));
  2225. Lock();
  2226. //
  2227. // get address
  2228. //
  2229. if (NULL == m_pAddress)
  2230. {
  2231. LOG((TL_ERROR, "GetAddRefAddressLine - no address"));
  2232. Unlock();
  2233. return NULL;
  2234. }
  2235. //
  2236. // keep a reference to the address for after we unlock the call
  2237. //
  2238. CAddress *pAddress = m_pAddress;
  2239. pAddress->AddRef();
  2240. //
  2241. // unlock
  2242. //
  2243. Unlock();
  2244. //
  2245. // lock the address (so address line does not go away before we addref it)
  2246. //
  2247. pAddress->Lock();
  2248. //
  2249. // get address line
  2250. //
  2251. AddressLineStruct *pLine =
  2252. (AddressLineStruct *)GetHandleTableEntry(dwAddressLineHandle);
  2253. //
  2254. // handle table entry exists?
  2255. //
  2256. if (NULL == pLine)
  2257. {
  2258. LOG((TL_ERROR, "GetAddRefAddressLine - no address line"));
  2259. //
  2260. // unlock and release the address
  2261. //
  2262. pAddress->Unlock();
  2263. pAddress->Release();
  2264. return NULL;
  2265. }
  2266. //
  2267. // does our address manage this line?
  2268. //
  2269. if (!pAddress->IsValidAddressLine(pLine, TRUE))
  2270. {
  2271. LOG((TL_ERROR, "GetAddRefAddressLine - not one of the address' lines"));
  2272. //
  2273. // so there is no confusion in the future, remove this so-called "line"
  2274. // from handle table
  2275. //
  2276. DeleteHandleTableEntry(dwAddressLineHandle);
  2277. //
  2278. // unlock and release the address
  2279. //
  2280. pAddress->Unlock();
  2281. pAddress->Release();
  2282. return NULL;
  2283. }
  2284. //
  2285. // unlock the address
  2286. //
  2287. pAddress->Unlock();
  2288. //
  2289. // no need to keep the reference to the address anymore
  2290. //
  2291. pAddress->Release();
  2292. //
  2293. // all done. return pLine.
  2294. //
  2295. LOG((TL_INFO, "GetAddRefAddressLine - finish. pLine = %p", pLine));
  2296. return pLine;
  2297. }
  2298. //////////////////////////////////////////////////////////////////////////////
  2299. //
  2300. // CCall::ReleaseAddressLine()
  2301. //
  2302. // this function takes a pointer to an line and attempts to free it if needed
  2303. //
  2304. // this function should be called OUTSIDE call lock to prevent deadlocks
  2305. //
  2306. HRESULT CCall::ReleaseAddressLine(AddressLineStruct *pLine)
  2307. {
  2308. LOG((TL_INFO, "ReleaseAddressLine - enter. pLine[%p]", pLine));
  2309. //
  2310. // lock
  2311. //
  2312. Lock();
  2313. //
  2314. // get address
  2315. //
  2316. if (NULL == m_pAddress)
  2317. {
  2318. LOG((TL_ERROR, "ReleaseAddressLine - no address"));
  2319. Unlock();
  2320. return E_FAIL;
  2321. }
  2322. //
  2323. // keep a reference to the address for after we unlock the call
  2324. //
  2325. CAddress *pAddress = m_pAddress;
  2326. pAddress->AddRef();
  2327. //
  2328. // unlock
  2329. //
  2330. Unlock();
  2331. //
  2332. // close address line
  2333. //
  2334. AddressLineStruct *pAddressLine = pLine;
  2335. HRESULT hr = pAddress->MaybeCloseALine(&pAddressLine);
  2336. if (FAILED(hr))
  2337. {
  2338. LOG((TL_ERROR, "ReleaseAddressLine - MaybeCloseALine failed. hr = %lx", hr));
  2339. }
  2340. //
  2341. // no need to keep the reference to the address anymore
  2342. //
  2343. pAddress->Release();
  2344. //
  2345. // all done.
  2346. //
  2347. LOG((TL_INFO, "ReleaseAddressLine - finish. hr = %lx", hr));
  2348. return hr;
  2349. }
  2350. ///////////////////////////////////////////////////////////////////////////////
  2351. //
  2352. // CCall::GetCallBackInstance
  2353. //
  2354. // return lCallbackInstance from the address line referred to by the handle
  2355. //
  2356. HRESULT
  2357. CCall::GetCallBackInstance(IN DWORD dwAddressLineHandle,
  2358. OUT long *plCallbackInstance)
  2359. {
  2360. LOG((TL_INFO, "GetCallBackInstance - enter. dwAddressLineHandle = 0x%lx",
  2361. dwAddressLineHandle));
  2362. //
  2363. // got a good pointer?
  2364. //
  2365. if (IsBadWritePtr(plCallbackInstance, sizeof(long) ) )
  2366. {
  2367. LOG((TL_ERROR, "GetCallBackInstance - bad pointer[%p]",
  2368. plCallbackInstance));
  2369. _ASSERTE(FALSE);
  2370. return E_POINTER;
  2371. }
  2372. //
  2373. // get an address line from the handle
  2374. //
  2375. AddressLineStruct *pLine = GetAddRefAddressLine(dwAddressLineHandle);
  2376. if ( NULL == pLine )
  2377. {
  2378. //
  2379. // pLine is NULL, the line must have already been closed before we got this event.
  2380. //
  2381. LOG((TL_WARN, "HandleMonitorToneMessage - pLine is NULL"));
  2382. return E_FAIL;
  2383. }
  2384. LOG((TL_INFO, "HandleMonitorToneMessage: pLine %p", pLine));
  2385. //
  2386. // try to get callbackinstance from pline
  2387. //
  2388. long lCBInstance = 0;
  2389. try
  2390. {
  2391. lCBInstance = pLine->lCallbackInstance;
  2392. }
  2393. catch(...)
  2394. {
  2395. LOG((TL_ERROR,
  2396. "HandleMonitorToneMessage - exception while accessing pLine[%p]",
  2397. pLine));
  2398. //
  2399. // pline memory got released somehow. this should not happen so debug to see why
  2400. //
  2401. _ASSERTE(FALSE);
  2402. }
  2403. //
  2404. // release address line
  2405. //
  2406. HRESULT hr = ReleaseAddressLine(pLine);
  2407. if (FAILED(hr))
  2408. {
  2409. LOG((TL_ERROR,
  2410. "HandleMonitorToneMessage - ReleaseAddressLine failed. hr = %lx",
  2411. hr));
  2412. }
  2413. *plCallbackInstance = lCBInstance;
  2414. LOG((TL_INFO, "ReleaseAddressLine - finish. lCallbackInstance[0x%lx]", *plCallbackInstance));
  2415. return S_OK;
  2416. }
  2417. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2418. //
  2419. // MediaModeEvent
  2420. //
  2421. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2422. HRESULT
  2423. CCall::MediaModeEvent(
  2424. PASYNCEVENTMSG pParams
  2425. )
  2426. {
  2427. LOG((TL_INFO, "MediaModeEvent - enter. pParams->OpenContext %lx", pParams->OpenContext ));
  2428. //
  2429. // pParams->OpenContext is the 32-bit handle for AddressLineStruct
  2430. //
  2431. //
  2432. // get the callback instance thatcorresponds to this address line structure
  2433. //
  2434. long lCallBackInstance = 0;
  2435. HRESULT hr = GetCallBackInstance(pParams->OpenContext, &lCallBackInstance);
  2436. if ( FAILED(hr) )
  2437. {
  2438. //
  2439. // failed to get callback instance
  2440. //
  2441. LOG((TL_WARN, "MediaModeEvent - GetCallBackInstance failed. hr = %lx", hr));
  2442. return S_OK;
  2443. }
  2444. Lock(); // using m_pAddress below -- therefore need to lock?
  2445. //
  2446. // fire the event
  2447. //
  2448. CCallInfoChangeEvent::FireEvent(
  2449. this,
  2450. CIC_MEDIATYPE,
  2451. m_pAddress->GetTapi(),
  2452. lCallBackInstance
  2453. );
  2454. Unlock();
  2455. LOG((TL_INFO, "MediaModeEvent - exit. hr = %lx", hr));
  2456. return hr;
  2457. }
  2458. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2459. //
  2460. // CheckAndCreateFakeCallHub
  2461. //
  2462. // we need to create a fake callhub object if the address doesn't support
  2463. // call hubs.
  2464. //
  2465. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2466. HRESULT
  2467. CCall::CheckAndCreateFakeCallHub()
  2468. {
  2469. Lock();
  2470. if (NULL == m_pCallHub)
  2471. {
  2472. DWORD dwRet;
  2473. HRESULT hr;
  2474. //
  2475. // if it doesn't support callhubs, then
  2476. // create one
  2477. //
  2478. // if it does, then we should get notified from
  2479. // tapisrv, and the callhub will be filled in during
  2480. // the LINE_APPNEWCALLHUB handling
  2481. //
  2482. dwRet = m_pAddress->DoesThisAddressSupportCallHubs( this );
  2483. if ( CALLHUBSUPPORT_NONE == dwRet )
  2484. {
  2485. hr = CCallHub::CreateFakeCallHub(
  2486. m_pAddress->GetTapi(),
  2487. this,
  2488. &m_pCallHub
  2489. );
  2490. if (!SUCCEEDED(hr))
  2491. {
  2492. LOG((TL_ERROR, "CheckAndCreateFakeCallHub - "
  2493. "could not creat callhub %lx", hr));
  2494. Unlock();
  2495. return hr;
  2496. }
  2497. }
  2498. else
  2499. {
  2500. Unlock();
  2501. return E_PENDING;
  2502. }
  2503. }
  2504. LOG((TL_ERROR, "CCall::m_pCallHub -created:%p:%p", this, m_pCallHub ));
  2505. Unlock();
  2506. return S_OK;
  2507. }
  2508. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2509. //
  2510. // SetCallHub
  2511. //
  2512. // sets the callhub member
  2513. //
  2514. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2515. void
  2516. CCall::SetCallHub(
  2517. CCallHub * pCallHub
  2518. )
  2519. {
  2520. CCallHub* temp_pCallHub;
  2521. Lock();
  2522. LOG((TL_ERROR, "CCall::SetCallhub:%p:%p", this, pCallHub ));
  2523. // only process if they've changed 3/3/1999 - bug 300914
  2524. if (pCallHub != m_pCallHub)
  2525. {
  2526. //NikhilB: These cahnges are to solve a hang and an AV.
  2527. temp_pCallHub = m_pCallHub; //store the old value
  2528. m_pCallHub = pCallHub; //assign the new value
  2529. LOG((TL_ERROR, "CCall::m_pCallHub -set:%p:%p", this, m_pCallHub ));
  2530. if (temp_pCallHub != NULL) //release the old reference
  2531. {
  2532. LOG((TL_INFO, "SetCallHub - call %p changing hub from %p to %p"
  2533. , this, temp_pCallHub, pCallHub));
  2534. //NikhilB:remove this Call from previous CallHub's m_CallArray otherwise
  2535. //this call will be present in two call hubs.
  2536. temp_pCallHub->RemoveCall( this );
  2537. temp_pCallHub->Release(); // ZoltanS fix 11-12-98
  2538. }
  2539. //addref to the new reference
  2540. if ( NULL != pCallHub )
  2541. {
  2542. pCallHub->AddRef();
  2543. }
  2544. }
  2545. Unlock();
  2546. }
  2547. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2548. //
  2549. // LINE_CALLSTATE handler
  2550. //
  2551. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2552. HRESULT HandleCallStateMessage( PASYNCEVENTMSG pParams )
  2553. {
  2554. CCall * pCall;
  2555. BOOL bSuccess;
  2556. HRESULT hr = E_FAIL;
  2557. bSuccess = FindCallObject(
  2558. (HCALL)(pParams->hDevice),
  2559. &pCall
  2560. );
  2561. if (bSuccess)
  2562. {
  2563. // fire the event
  2564. pCall->CallStateEvent(
  2565. pParams
  2566. );
  2567. // find call object addrefs the
  2568. // call, so release it
  2569. pCall->Release();
  2570. hr = S_OK;
  2571. }
  2572. else
  2573. {
  2574. LOG((TL_INFO, "HandleCallStateMessage - failed to find Call Object %lx", pParams->hDevice));
  2575. hr = E_FAIL;
  2576. }
  2577. return hr;
  2578. }
  2579. HRESULT
  2580. HandleCallIDChange(
  2581. PASYNCEVENTMSG pParams,
  2582. CCall * pCall
  2583. )
  2584. {
  2585. LINECALLLIST * pCallHubList;
  2586. HCALL * phCalls;
  2587. HCALLHUB hNewCallHub = 0;
  2588. HCALLHUB hCurrentCallHub = 0;
  2589. CCallHub * pCallHub = NULL;
  2590. HRESULT hr;
  2591. //
  2592. // find the current callhub handle
  2593. //
  2594. pCallHub = pCall->GetCallHub();
  2595. if(pCallHub != NULL)
  2596. {
  2597. hCurrentCallHub = pCallHub->GetCallHub();
  2598. }
  2599. //
  2600. // Now get the callhub handle from TAPI (based on hCall)
  2601. //
  2602. hr = LineGetHubRelatedCalls(
  2603. 0,
  2604. (HCALL)(pParams->hDevice),
  2605. &pCallHubList
  2606. );
  2607. if ( SUCCEEDED(hr) )
  2608. {
  2609. // get to the list of calls
  2610. phCalls = (HCALL *)(((LPBYTE)pCallHubList) + pCallHubList->dwCallsOffset);
  2611. // the first handle is the callhub
  2612. hNewCallHub = (HCALLHUB)(phCalls[0]);
  2613. // have they changed ?
  2614. if (hNewCallHub != hCurrentCallHub )
  2615. {
  2616. //
  2617. // Yes so we've moved hubs
  2618. //
  2619. LOG((TL_INFO, "HandleCallInfoMessage - LINECALLINFOSTATE_CALLID callhub change"));
  2620. LOG((TL_INFO, "HandleCallInfoMessage - Call %p > old Hub handle:%lx > new handle:%lx",
  2621. pCall, hCurrentCallHub, hNewCallHub ));
  2622. // remove call from current hub.
  2623. if(pCallHub != NULL)
  2624. {
  2625. pCallHub->RemoveCall(pCall);
  2626. pCallHub->CheckForIdle();
  2627. }
  2628. // Add it to new hub.
  2629. if(FindCallHubObject(hNewCallHub, &pCallHub) )
  2630. {
  2631. pCallHub->AddCall(pCall);
  2632. // FindCallHubObject AddRefs, so release
  2633. pCallHub->Release();
  2634. }
  2635. }
  2636. else
  2637. {
  2638. LOG((TL_ERROR, "HandleCallInfoMessage - LINECALLINFOSTATE_CALLID callhub not changed"));
  2639. }
  2640. ClientFree( pCallHubList );
  2641. }
  2642. else
  2643. {
  2644. LOG((TL_ERROR, "HandleCallInfoMessage - LINECALLINFOSTATE_CALLID LineGetHubRelatedCalls "
  2645. "failed %lx", hr));
  2646. }
  2647. pCall->CallInfoChangeEvent( CIC_CALLID );
  2648. return S_OK;
  2649. }
  2650. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2651. //
  2652. // LINE_CALLINFO handler
  2653. //
  2654. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2655. HRESULT HandleCallInfoMessage( PASYNCEVENTMSG pParams )
  2656. {
  2657. BOOL bSuccess;
  2658. HRESULT hr = S_OK;
  2659. CALLINFOCHANGE_CAUSE cic;
  2660. CCall * pCall;
  2661. DWORD dw;
  2662. bSuccess = FindCallObject(
  2663. (HCALL)(pParams->hDevice),
  2664. &pCall
  2665. );
  2666. if ( !bSuccess )
  2667. {
  2668. LOG((TL_INFO, "HandleCallInfoMessage - failed to find Call Object %lx", pParams->hDevice));
  2669. return E_FAIL;
  2670. }
  2671. pCall->SetCallInfoDirty();
  2672. dw = pParams->Param1;
  2673. if (dw & LINECALLINFOSTATE_MEDIAMODE)
  2674. {
  2675. pCall->MediaModeEvent(pParams);
  2676. }
  2677. if (dw & LINECALLINFOSTATE_CALLID)
  2678. {
  2679. HandleCallIDChange( pParams, pCall );
  2680. }
  2681. if (dw & LINECALLINFOSTATE_OTHER)
  2682. pCall->CallInfoChangeEvent( CIC_OTHER );
  2683. if (dw & LINECALLINFOSTATE_DEVSPECIFIC)
  2684. pCall->CallInfoChangeEvent( CIC_DEVSPECIFIC );
  2685. if (dw & LINECALLINFOSTATE_BEARERMODE)
  2686. pCall->CallInfoChangeEvent( CIC_BEARERMODE );
  2687. if (dw & LINECALLINFOSTATE_RATE)
  2688. pCall->CallInfoChangeEvent( CIC_RATE );
  2689. if (dw & LINECALLINFOSTATE_APPSPECIFIC)
  2690. pCall->CallInfoChangeEvent( CIC_APPSPECIFIC );
  2691. if (dw & LINECALLINFOSTATE_RELATEDCALLID)
  2692. pCall->CallInfoChangeEvent( CIC_RELATEDCALLID );
  2693. if (dw & LINECALLINFOSTATE_ORIGIN)
  2694. pCall->CallInfoChangeEvent( CIC_ORIGIN );
  2695. if (dw & LINECALLINFOSTATE_REASON)
  2696. pCall->CallInfoChangeEvent( CIC_REASON );
  2697. if (dw & LINECALLINFOSTATE_COMPLETIONID)
  2698. pCall->CallInfoChangeEvent( CIC_COMPLETIONID );
  2699. if (dw & LINECALLINFOSTATE_NUMOWNERINCR)
  2700. pCall->CallInfoChangeEvent( CIC_NUMOWNERINCR );
  2701. if (dw & LINECALLINFOSTATE_NUMOWNERDECR)
  2702. pCall->CallInfoChangeEvent( CIC_NUMOWNERDECR );
  2703. if (dw & LINECALLINFOSTATE_NUMMONITORS)
  2704. pCall->CallInfoChangeEvent( CIC_NUMMONITORS );
  2705. if (dw & LINECALLINFOSTATE_TRUNK)
  2706. pCall->CallInfoChangeEvent( CIC_TRUNK );
  2707. if (dw & LINECALLINFOSTATE_CALLERID)
  2708. pCall->CallInfoChangeEvent( CIC_CALLERID );
  2709. if (dw & LINECALLINFOSTATE_CALLEDID)
  2710. pCall->CallInfoChangeEvent( CIC_CALLEDID );
  2711. if (dw & LINECALLINFOSTATE_CONNECTEDID)
  2712. pCall->CallInfoChangeEvent( CIC_CONNECTEDID );
  2713. if (dw & LINECALLINFOSTATE_REDIRECTIONID)
  2714. pCall->CallInfoChangeEvent( CIC_REDIRECTIONID );
  2715. if (dw & LINECALLINFOSTATE_REDIRECTINGID)
  2716. pCall->CallInfoChangeEvent( CIC_REDIRECTINGID );
  2717. if (dw & LINECALLINFOSTATE_USERUSERINFO)
  2718. pCall->CallInfoChangeEvent( CIC_USERUSERINFO );
  2719. if (dw & LINECALLINFOSTATE_HIGHLEVELCOMP)
  2720. pCall->CallInfoChangeEvent( CIC_HIGHLEVELCOMP );
  2721. if (dw & LINECALLINFOSTATE_LOWLEVELCOMP)
  2722. pCall->CallInfoChangeEvent( CIC_LOWLEVELCOMP );
  2723. if (dw & LINECALLINFOSTATE_CHARGINGINFO)
  2724. pCall->CallInfoChangeEvent( CIC_CHARGINGINFO );
  2725. if (dw & LINECALLINFOSTATE_TREATMENT)
  2726. pCall->CallInfoChangeEvent( CIC_TREATMENT );
  2727. if (dw & LINECALLINFOSTATE_CALLDATA)
  2728. pCall->CallInfoChangeEvent( CIC_CALLDATA );
  2729. if (dw & LINECALLINFOSTATE_QOS)
  2730. {
  2731. LOG((TL_WARN, "Unhandled LINECALLINFOSTATE_QOS message"));
  2732. }
  2733. if (dw & LINECALLINFOSTATE_MONITORMODES)
  2734. {
  2735. LOG((TL_WARN, "Unhandled LINECALLINFOSTATE_MONITORMODES message"));
  2736. }
  2737. if (dw & LINECALLINFOSTATE_DIALPARAMS)
  2738. {
  2739. LOG((TL_WARN, "Unhandled LINECALLINFOSTATE_DIALPARAMS message"));
  2740. }
  2741. if (dw & LINECALLINFOSTATE_TERMINAL)
  2742. {
  2743. LOG((TL_WARN, "Unhandled LINECALLINFOSTATE_TERMINAL message"));
  2744. }
  2745. if (dw & LINECALLINFOSTATE_DISPLAY)
  2746. {
  2747. LOG((TL_WARN, "Unhandled LINECALLINFOSTATE_DISPLAY message"));
  2748. }
  2749. // find call object addrefs the call
  2750. // so release it.
  2751. pCall->Release();
  2752. return S_OK;
  2753. }
  2754. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2755. //
  2756. // LINE_MONITORDIGIT handler
  2757. //
  2758. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2759. HRESULT HandleMonitorDigitsMessage( PASYNCEVENTMSG pParams )
  2760. {
  2761. LOG((TL_INFO, "HandleMonitorDigitsMessage - enter"));
  2762. BOOL bSuccess;
  2763. CCall * pCall = NULL;
  2764. HRESULT hr = S_OK;
  2765. //
  2766. // get the call object
  2767. //
  2768. bSuccess = FindCallObject(
  2769. (HCALL)(pParams->hDevice),
  2770. &pCall
  2771. );
  2772. if (bSuccess)
  2773. {
  2774. AddressLineStruct * pLine;
  2775. CAddress * pAddress;
  2776. pAddress = pCall->GetCAddress();
  2777. //
  2778. // pParams->OpenContext is the 32-bit handle for AddressLineStruct
  2779. //
  2780. LOG((TL_INFO, "HandleMonitorDigitsMessage: pParams->OpenContext %lx", pParams->OpenContext ));
  2781. //
  2782. // recover the callback instance value corresponding to this AddressLineStruct
  2783. //
  2784. long lCallbackInstance = 0;
  2785. hr = pCall->GetCallBackInstance(pParams->OpenContext, &lCallbackInstance);
  2786. if ( FAILED(hr) )
  2787. {
  2788. //
  2789. // failed to get callback instance
  2790. //
  2791. LOG((TL_WARN, "HandleMonitorDigitsMessage - GetCallBackInstance failed. hr = %lx", hr));
  2792. pCall->Release();
  2793. return S_OK;
  2794. }
  2795. LOG((TL_INFO, "HandleMonitorDigitsMessage - callbackinstance[%lx]", lCallbackInstance));
  2796. //
  2797. // fire the event
  2798. //
  2799. CDigitDetectionEvent::FireEvent(
  2800. pCall,
  2801. (long)(pParams->Param1),
  2802. (TAPI_DIGITMODE)(pParams->Param2),
  2803. (long)(pParams->Param3),
  2804. pAddress->GetTapi(),
  2805. lCallbackInstance
  2806. );
  2807. //
  2808. // release the call
  2809. //
  2810. pCall->Release();
  2811. hr = S_OK;
  2812. }
  2813. else
  2814. {
  2815. LOG((TL_INFO, "HandleMonitorDigitsMessage - failed to find Call Object %lx", pParams->hDevice));
  2816. hr = E_FAIL;
  2817. }
  2818. return hr;
  2819. }
  2820. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2821. //
  2822. // LINE_MONITORTONE handler
  2823. //
  2824. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2825. HRESULT HandleMonitorToneMessage( PASYNCEVENTMSG pParams )
  2826. {
  2827. BOOL bSuccess;
  2828. CCall * pCall;
  2829. HRESULT hr = S_OK;
  2830. //
  2831. // get the call object
  2832. //
  2833. bSuccess = FindCallObject(
  2834. (HCALL)(pParams->hDevice),
  2835. &pCall
  2836. );
  2837. if (bSuccess)
  2838. {
  2839. AddressLineStruct * pLine;
  2840. CAddress * pAddress;
  2841. pAddress = pCall->GetCAddress();
  2842. //
  2843. // pParams->OpenContext is the 32-bit handle for AddressLineStruct
  2844. //
  2845. LOG((TL_INFO, "HandleMonitorToneMessage: pParams->OpenContext %lx", pParams->OpenContext ));
  2846. //
  2847. // recover the callback instance corresponding to this AddressLineStruct
  2848. //
  2849. long lCallbackInstance = 0;
  2850. hr = pCall->GetCallBackInstance(pParams->OpenContext, &lCallbackInstance);
  2851. if ( FAILED(hr) )
  2852. {
  2853. LOG((TL_WARN, "HandleMonitorToneMessage - GetCallBackInstance failed. hr = %lx", hr));
  2854. pCall->Release();
  2855. return S_OK;
  2856. }
  2857. LOG((TL_INFO, "HandleMonitorToneMessage - lCallbackInstance 0x%lx", lCallbackInstance));
  2858. //
  2859. // fire the event
  2860. //
  2861. CToneDetectionEvent::FireEvent(
  2862. pCall,
  2863. (long)(pParams->Param1),
  2864. (long)(pParams->Param3),
  2865. lCallbackInstance,
  2866. pAddress->GetTapi()
  2867. );
  2868. //
  2869. // release the call
  2870. //
  2871. pCall->Release();
  2872. hr = S_OK;
  2873. }
  2874. else
  2875. {
  2876. LOG((TL_INFO, "HandleMonitorDigitsMessage - failed to find Call Object %lx", pParams->hDevice));
  2877. hr = E_FAIL;
  2878. }
  2879. return hr;
  2880. }
  2881. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2882. //
  2883. // LINE_MONITORMEDIA handler
  2884. //
  2885. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2886. void HandleMonitorMediaMessage( PASYNCEVENTMSG pParams )
  2887. {
  2888. BOOL bSuccess;
  2889. CCall * pCall;
  2890. //
  2891. // get the call object
  2892. //
  2893. bSuccess = FindCallObject(
  2894. (HCALL)(pParams->hDevice),
  2895. &pCall
  2896. );
  2897. if (bSuccess)
  2898. {
  2899. //
  2900. // Retrieve relevant info about the event:
  2901. //
  2902. // (long) (pParams->Param1) is the media type
  2903. // (DWORD?) (pParams->Param3) is the tick count (which we ignore)
  2904. //
  2905. long lMediaType = (long) (pParams->Param1);
  2906. HRESULT hr;
  2907. //
  2908. // This event means the TSP signaled a new media type that it
  2909. // detected. Try to set this on the call. The setting will
  2910. // trigger another event (LINE_CALLINFO) to inform the app
  2911. // that the media type actually changed, and that we will
  2912. // propagate to the app.
  2913. //
  2914. hr = pCall->SetMediaType( lMediaType );
  2915. if ( FAILED(hr) )
  2916. {
  2917. LOG((TL_INFO, "HandleMonitorMediaMessage - "
  2918. "failed SetMediaType 0x%08x", hr));
  2919. }
  2920. //
  2921. // release the call because FindCallObject AddRefed it
  2922. //
  2923. pCall->Release();
  2924. }
  2925. else
  2926. {
  2927. LOG((TL_INFO, "HandleMonitorMediaMessage - "
  2928. "failed to find Call Object %lx", pParams->hDevice));
  2929. }
  2930. return;
  2931. }
  2932. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2933. //
  2934. // HandleLineGenerateMessage
  2935. //
  2936. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2937. HRESULT HandleLineGenerateMessage( PASYNCEVENTMSG pParams )
  2938. {
  2939. BOOL bSuccess;
  2940. CCall * pCall;
  2941. HRESULT hr = S_OK;
  2942. //
  2943. // get the call object
  2944. //
  2945. bSuccess = FindCallObject(
  2946. (HCALL)(pParams->hDevice),
  2947. &pCall
  2948. );
  2949. if (bSuccess)
  2950. {
  2951. //
  2952. // get call's address
  2953. //
  2954. CAddress *pAddress = pCall->GetCAddress();
  2955. //
  2956. // pParams->OpenContext is the 32-bit handle for AddressLineStruct
  2957. //
  2958. LOG((TL_INFO, "HandleLineGenerateMessage: pParams->OpenContext %lx", pParams->OpenContext ));
  2959. //
  2960. // get the callback instance corresponding to this AddressLineStruct handle
  2961. //
  2962. long lCallbackInstance = 0;
  2963. hr = pCall->GetCallBackInstance(pParams->OpenContext, &lCallbackInstance);
  2964. if ( FAILED(hr) )
  2965. {
  2966. //
  2967. // it is possible the line had been closed before we got this event.
  2968. //
  2969. LOG((TL_WARN, "HandleLineGenerateMessage - GetCallBackInstance failed. hr = %lx", hr));
  2970. pCall->Release();
  2971. return S_OK;
  2972. }
  2973. LOG((TL_INFO, "HandleLineGenerateMessage - lCallbackInstance %lx", lCallbackInstance ));
  2974. //
  2975. // fire the event
  2976. //
  2977. CDigitGenerationEvent::FireEvent(
  2978. pCall,
  2979. (long)(pParams->Param1),
  2980. (long)(pParams->Param3),
  2981. lCallbackInstance,
  2982. pAddress->GetTapi()
  2983. );
  2984. //
  2985. // special case for wavemsp
  2986. // LineGenerateDigits or LineGenerateTones has completed, so we are
  2987. // now ready to resume...
  2988. // resume the stream so the wave devices are reopened after the
  2989. // tapi function has completed
  2990. //
  2991. // param1 is LINEGENERATETERM_DONE or LINEGENERATETERM_CANCEL
  2992. // (either way we need to resume the stream)
  2993. //
  2994. if ( pCall->OnWaveMSPCall() )
  2995. {
  2996. pCall->ResumeWaveMSPStream();
  2997. }
  2998. //
  2999. // release the call
  3000. //
  3001. pCall->Release();
  3002. hr = S_OK;
  3003. }
  3004. else
  3005. {
  3006. LOG((TL_INFO, "HandleLineGenerateMessage - failed to find Call Object %lx", pParams->hDevice));
  3007. hr = E_FAIL;
  3008. }
  3009. return hr;
  3010. }
  3011. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3012. //
  3013. // LINE_GATHERDIGIT handler
  3014. //
  3015. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3016. HRESULT HandleGatherDigitsMessage( PASYNCEVENTMSG pParams )
  3017. {
  3018. BOOL bSuccess;
  3019. CCall * pCall;
  3020. HRESULT hr = S_OK;
  3021. //
  3022. // get the call object
  3023. //
  3024. bSuccess = FindCallObject(
  3025. (HCALL)(pParams->hDevice),
  3026. &pCall
  3027. );
  3028. if (bSuccess)
  3029. {
  3030. pCall->GatherDigitsEvent( pParams );
  3031. //
  3032. // release the call
  3033. //
  3034. pCall->Release();
  3035. hr = S_OK;
  3036. }
  3037. else
  3038. {
  3039. LOG((TL_INFO, "HandleGatherDigitsMessage - failed to find Call Object %lx", pParams->hDevice));
  3040. hr = E_FAIL;
  3041. }
  3042. return hr;
  3043. }
  3044. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3045. //
  3046. // GatherDigitsEvent
  3047. //
  3048. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3049. HRESULT CCall::GatherDigitsEvent( PASYNCEVENTMSG pParams )
  3050. {
  3051. LOG((TL_INFO, "GatherDigitsEvent - enter. pParams->OpenContext[%lx]",
  3052. pParams->OpenContext ));
  3053. //
  3054. // pParams->OpenContext is the 32-bit handle for AddressLineStruct
  3055. //
  3056. //
  3057. // recover the callback instance associated with thisAddressLineStruct
  3058. //
  3059. long lCallbackInstance = 0;
  3060. HRESULT hr = GetCallBackInstance(pParams->OpenContext, &lCallbackInstance);
  3061. if ( FAILED(hr) )
  3062. {
  3063. LOG((TL_WARN, "GatherDigitsEvent - failed to get callback instance"));
  3064. return S_OK;
  3065. }
  3066. LOG((TL_INFO, "GatherDigitsEvent - lCallbackInstance %lx", lCallbackInstance));
  3067. Lock();
  3068. //
  3069. // Check to make sure the queue isn't empty
  3070. //
  3071. if ( m_GatherDigitsQueue.GetSize() == 0 )
  3072. {
  3073. LOG((TL_ERROR, "GatherDigitsEvent - GatherDigitsQueue is empty"));
  3074. Unlock();
  3075. return E_FAIL;
  3076. }
  3077. LPWSTR pDigits;
  3078. BSTR bstrDigits;
  3079. //
  3080. // Get the digit string from the queue
  3081. //
  3082. pDigits = m_GatherDigitsQueue[0];
  3083. m_GatherDigitsQueue.RemoveAt(0);
  3084. if ( IsBadStringPtrW(pDigits, -1) )
  3085. {
  3086. LOG((TL_ERROR, "GatherDigitsEvent - bad digits string"));
  3087. Unlock();
  3088. return S_OK;
  3089. }
  3090. bstrDigits = SysAllocString(pDigits);
  3091. ClientFree(pDigits);
  3092. pDigits = NULL;
  3093. //
  3094. // fire the event
  3095. //
  3096. CDigitsGatheredEvent::FireEvent(
  3097. this,
  3098. bstrDigits,
  3099. (TAPI_GATHERTERM)(pParams->Param1),
  3100. (long)(pParams->Param3),
  3101. lCallbackInstance,
  3102. m_pAddress->GetTapi()
  3103. );
  3104. Unlock();
  3105. return S_OK;
  3106. }
  3107. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3108. //
  3109. // RefreshCallInfo
  3110. //
  3111. // Assume called in lock
  3112. //
  3113. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3114. HRESULT
  3115. CCall::RefreshCallInfo()
  3116. {
  3117. LINECALLINFO * pCallInfo;
  3118. HRESULT hr = S_OK;
  3119. //
  3120. // do we need to update?
  3121. //
  3122. if ( CS_IDLE == m_CallState )
  3123. {
  3124. LOG((TL_ERROR, "Can't get callinfo while in idle state"));
  3125. return TAPI_E_INVALCALLSTATE;
  3126. }
  3127. if ( CALLFLAG_CALLINFODIRTY & m_dwCallFlags )
  3128. {
  3129. hr = LineGetCallInfo(
  3130. m_t3Call.hCall,
  3131. &pCallInfo
  3132. );
  3133. if ( !SUCCEEDED(hr) )
  3134. {
  3135. LOG((TL_ERROR, "RefreshCallInfo - linegetcallinfo failed - %lx", hr));
  3136. if ( NULL != m_pCallInfo )
  3137. {
  3138. //
  3139. // use cached struct
  3140. //
  3141. // don't clear bit
  3142. //
  3143. return S_FALSE;
  3144. }
  3145. else
  3146. {
  3147. return hr;
  3148. }
  3149. }
  3150. //
  3151. // clear bit
  3152. //
  3153. m_dwCallFlags &= ~CALLFLAG_CALLINFODIRTY;
  3154. //
  3155. // free
  3156. //
  3157. if ( NULL != m_pCallInfo )
  3158. {
  3159. ClientFree( m_pCallInfo );
  3160. }
  3161. //
  3162. // save
  3163. //
  3164. m_pCallInfo = pCallInfo;
  3165. }
  3166. if( NULL == m_pCallInfo )
  3167. {
  3168. return E_POINTER;
  3169. }
  3170. return S_OK;
  3171. }
  3172. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3173. //
  3174. // CCall::FinishCallParams()
  3175. //
  3176. // called in lock
  3177. //
  3178. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3179. void
  3180. CCall::FinishCallParams()
  3181. {
  3182. if(m_pCallParams != NULL)
  3183. {
  3184. Lock();
  3185. m_pCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
  3186. m_pCallParams->dwAddressID = m_pAddress->GetAddressID();
  3187. if (m_dwMediaMode & AUDIOMEDIAMODES)
  3188. {
  3189. m_dwMediaMode &= ~AUDIOMEDIAMODES;
  3190. m_dwMediaMode |= (AUDIOMEDIAMODES & m_pAddress->GetMediaModes());
  3191. }
  3192. //
  3193. // if we're < tapi3, multiple media modes can't be handled
  3194. //
  3195. if ( m_pAddress->GetAPIVersion() < TAPI_VERSION3_0 )
  3196. {
  3197. if ( (m_dwMediaMode & AUDIOMEDIAMODES) == AUDIOMEDIAMODES )
  3198. {
  3199. m_dwMediaMode &= ~LINEMEDIAMODE_INTERACTIVEVOICE;
  3200. }
  3201. }
  3202. m_pCallParams->dwMediaMode = m_dwMediaMode;
  3203. Unlock();
  3204. }
  3205. }
  3206. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3207. //
  3208. // ResizeCallParams
  3209. //
  3210. // assumed called in lock
  3211. //
  3212. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3213. HRESULT
  3214. CCall::ResizeCallParams( DWORD dwSize )
  3215. {
  3216. LOG((TL_TRACE, "ResizeCallParams - enter"));
  3217. DWORD dwNewSize;
  3218. LINECALLPARAMS * pCallParams;
  3219. if ( NULL == m_pCallParams )
  3220. {
  3221. LOG((TL_WARN,
  3222. "ResizeCallParams - finish. no call params. invalid state for this function call"));
  3223. return TAPI_E_INVALCALLSTATE;
  3224. }
  3225. dwSize += m_dwCallParamsUsedSize;
  3226. if ( dwSize <= m_pCallParams->dwTotalSize )
  3227. {
  3228. LOG((TL_TRACE, "ResizeCallParams - finish. sufficient size"));
  3229. return S_OK;
  3230. }
  3231. dwNewSize = m_pCallParams->dwTotalSize;
  3232. while ( dwNewSize < dwSize )
  3233. {
  3234. dwNewSize *= 2;
  3235. }
  3236. pCallParams = (LINECALLPARAMS *) ClientAlloc (dwNewSize);
  3237. if ( NULL == pCallParams )
  3238. {
  3239. LOG((TL_ERROR, "ResizeCallParams - alloc failed"));
  3240. return E_OUTOFMEMORY;
  3241. }
  3242. CopyMemory(
  3243. pCallParams,
  3244. m_pCallParams,
  3245. m_dwCallParamsUsedSize
  3246. );
  3247. ClientFree( m_pCallParams );
  3248. m_pCallParams = pCallParams;
  3249. m_pCallParams->dwTotalSize = dwNewSize;
  3250. LOG((TL_TRACE, "ResizeCallParams - finish."));
  3251. return S_OK;
  3252. }
  3253. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3254. //
  3255. // SendUserUserInfo
  3256. //
  3257. // Not called in lock
  3258. //
  3259. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3260. HRESULT
  3261. CCall::SendUserUserInfo(
  3262. HCALL hCall,
  3263. long lSize,
  3264. BYTE * pBuffer
  3265. )
  3266. {
  3267. HRESULT hr = S_OK;
  3268. if ( IsBadReadPtr( pBuffer, lSize ) )
  3269. {
  3270. LOG((TL_ERROR, "SendUserUserInfo - invalid buffer"));
  3271. hr = E_POINTER;
  3272. }
  3273. else
  3274. {
  3275. hr = LineSendUserUserInfo(
  3276. hCall,
  3277. (LPCSTR)pBuffer,
  3278. lSize
  3279. );
  3280. if (((LONG)hr) < 0)
  3281. {
  3282. LOG((TL_ERROR, "LineSendUserUserInfo failed - %lx", hr));
  3283. return hr;
  3284. }
  3285. hr = WaitForReply( hr );
  3286. }
  3287. return hr;
  3288. }
  3289. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3290. //
  3291. // SaveUserUserInfo
  3292. //
  3293. // called in Lock()
  3294. //
  3295. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3296. HRESULT
  3297. CCall::SaveUserUserInfo(
  3298. long lSize,
  3299. BYTE * pBuffer
  3300. )
  3301. {
  3302. HRESULT hr;
  3303. if ( IsBadReadPtr( pBuffer, lSize ) )
  3304. {
  3305. LOG((TL_ERROR, "SaveUserUserInfo - invalid buffer"));
  3306. return E_POINTER;
  3307. }
  3308. hr = ResizeCallParams( lSize );
  3309. if ( !SUCCEEDED(hr) )
  3310. {
  3311. LOG((TL_ERROR, "SaveUserUserInfo - can't resize call params - %lx", hr));
  3312. return hr;
  3313. }
  3314. CopyMemory(
  3315. ((PBYTE)m_pCallParams) + m_dwCallParamsUsedSize,
  3316. pBuffer,
  3317. lSize
  3318. );
  3319. m_pCallParams->dwUserUserInfoSize = lSize;
  3320. m_pCallParams->dwUserUserInfoOffset = m_dwCallParamsUsedSize;
  3321. m_dwCallParamsUsedSize += lSize;
  3322. return S_OK;
  3323. }
  3324. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3325. //
  3326. // MakeBufferFromVariant
  3327. //
  3328. // this function copies the data from a VARIANT with a safearray
  3329. // of bytes to a byte buffer. the caller must clientfee the
  3330. // buffer allocated.
  3331. //
  3332. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3333. HRESULT
  3334. MakeBufferFromVariant(
  3335. VARIANT var,
  3336. DWORD * pdwSize,
  3337. BYTE ** ppBuffer
  3338. )
  3339. {
  3340. long lDims;
  3341. long lUpper;
  3342. long lLower;
  3343. BYTE * pArray;
  3344. HRESULT hr = S_OK;
  3345. DWORD dwSize;
  3346. if ( ( ! (var.vt & VT_ARRAY) ) ||
  3347. ( ! (var.vt & VT_UI1) ) )
  3348. {
  3349. LOG((TL_ERROR, "MakeBufferFromVariant - Variant not array or not byte"));
  3350. return E_INVALIDARG;
  3351. }
  3352. lDims = SafeArrayGetDim( var.parray );
  3353. if ( 1 != lDims )
  3354. {
  3355. LOG((TL_ERROR, "MakeBufferFromVariant - Variant dims != 1 - %d", lDims));
  3356. return E_INVALIDARG;
  3357. }
  3358. if ( !(SUCCEEDED(SafeArrayGetLBound(var.parray, 1, &lLower)) ) ||
  3359. !(SUCCEEDED(SafeArrayGetUBound(var.parray, 1, &lUpper)) ) )
  3360. {
  3361. LOG((TL_ERROR, "MakeBufferFromVariant - get bound failed"));
  3362. return E_INVALIDARG;
  3363. }
  3364. if ( lLower >= lUpper )
  3365. {
  3366. LOG((TL_ERROR, "MakeBufferFromVariant - bounds invalid"));
  3367. return E_INVALIDARG;
  3368. }
  3369. dwSize = lUpper - lLower + 1;
  3370. *ppBuffer = (BYTE *)ClientAlloc( dwSize );
  3371. if ( NULL == *ppBuffer )
  3372. {
  3373. LOG((TL_ERROR, "MakeBufferFromVariant - Alloc failed"));
  3374. return E_OUTOFMEMORY;
  3375. }
  3376. SafeArrayAccessData( var.parray, (void**)&pArray );
  3377. CopyMemory(
  3378. *ppBuffer,
  3379. pArray,
  3380. dwSize
  3381. );
  3382. SafeArrayUnaccessData( var.parray );
  3383. *pdwSize = dwSize;
  3384. return S_OK;
  3385. }
  3386. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3387. //
  3388. // FillVariantFromBuffer
  3389. //
  3390. // create a safearray of bytes, copy the buffer into the safearray,
  3391. // and save the safearray in the variant
  3392. //
  3393. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3394. HRESULT
  3395. FillVariantFromBuffer(
  3396. DWORD dw,
  3397. BYTE * pBuffer,
  3398. VARIANT * pVar
  3399. )
  3400. {
  3401. SAFEARRAY * psa;
  3402. SAFEARRAYBOUND sabound[1];
  3403. BYTE * pArray;
  3404. sabound[0].lLbound = 0;
  3405. sabound[0].cElements = dw;
  3406. psa = SafeArrayCreate(VT_UI1, 1, sabound);
  3407. if ( NULL == psa )
  3408. {
  3409. LOG((TL_ERROR, "FillVariantFromBuffer - failed to allocate safearray"));
  3410. return E_OUTOFMEMORY;
  3411. }
  3412. if ( 0 != dw )
  3413. {
  3414. SafeArrayAccessData( psa, (void **) &pArray );
  3415. CopyMemory(
  3416. pArray,
  3417. pBuffer,
  3418. dw
  3419. );
  3420. SafeArrayUnaccessData( psa );
  3421. }
  3422. pVar->vt = VT_ARRAY | VT_UI1;
  3423. pVar->parray = psa;
  3424. return S_OK;
  3425. }
  3426. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3427. //
  3428. // HandleLineQOSInfoMessage
  3429. //
  3430. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3431. HRESULT HandleLineQOSInfoMessage(
  3432. PASYNCEVENTMSG pParams
  3433. )
  3434. {
  3435. CCall * pCall;
  3436. BOOL bSuccess;
  3437. HRESULT hr = S_OK;
  3438. bSuccess = FindCallObject(
  3439. (HCALL)(pParams->hDevice),
  3440. &pCall
  3441. );
  3442. if (bSuccess)
  3443. {
  3444. ITCallHub * pCallHub;
  3445. CCallHub * pCCallHub;
  3446. hr = pCall->get_CallHub( &pCallHub );
  3447. if (SUCCEEDED(hr))
  3448. {
  3449. pCCallHub = dynamic_cast<CCallHub *>(pCallHub);
  3450. CQOSEvent::FireEvent(
  3451. pCall,
  3452. (QOS_EVENT)pParams->Param1,
  3453. (long)pParams->Param2,
  3454. pCCallHub->GetTapi() // no addref
  3455. );
  3456. hr = S_OK;
  3457. }
  3458. //
  3459. // release the call
  3460. //
  3461. pCall->Release();
  3462. }
  3463. else
  3464. {
  3465. LOG((TL_INFO, "HandleLineQOSInfoMessage - failed to find Call Object %lx", pParams->hDevice));
  3466. hr = E_FAIL;
  3467. }
  3468. return hr;
  3469. }
  3470. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3471. //
  3472. //
  3473. //
  3474. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3475. AddressLineStruct *
  3476. CCall::GetPAddressLine()
  3477. {
  3478. AddressLineStruct * pAddressLine;
  3479. Lock();
  3480. pAddressLine = m_pAddressLine;
  3481. Unlock();
  3482. return pAddressLine;
  3483. }
  3484. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3485. //
  3486. //
  3487. //
  3488. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3489. HCALL
  3490. CCall::GetHCall()
  3491. {
  3492. HCALL hCall;
  3493. Lock();
  3494. hCall = m_t3Call.hCall;
  3495. Unlock();
  3496. return hCall;
  3497. }
  3498. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3499. //
  3500. //
  3501. //
  3502. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3503. BOOL
  3504. CCall::DontExpose()
  3505. {
  3506. BOOL bReturn;
  3507. Lock();
  3508. bReturn = (m_dwCallFlags & CALLFLAG_DONTEXPOSE)?TRUE:FALSE;
  3509. Unlock();
  3510. return bReturn;
  3511. }
  3512. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3513. //
  3514. //
  3515. //
  3516. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3517. CCallHub *
  3518. CCall::GetCallHub()
  3519. {
  3520. CCallHub * pCallHub;
  3521. Lock();
  3522. pCallHub = m_pCallHub;
  3523. Unlock();
  3524. return pCallHub;
  3525. }
  3526. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3527. //
  3528. // called in lock
  3529. //
  3530. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3531. void
  3532. CCall::ResetCallParams()
  3533. {
  3534. LOG((TL_TRACE, "ResetCallParams - enter."));
  3535. ClientFree( m_pCallParams );
  3536. m_pCallParams = NULL;
  3537. m_dwCallParamsUsedSize = 0;
  3538. LOG((TL_TRACE, "ResetCallParams - finish."));
  3539. }
  3540. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3541. //
  3542. // called in lock
  3543. //
  3544. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3545. void
  3546. CCall::FinishSettingUpCall( HCALL hCall )
  3547. {
  3548. LOG((TL_TRACE, "FinishSettingUpCall - enter"));
  3549. if(m_t3Call.hCall != NULL)
  3550. {
  3551. LOG((TL_ERROR, "FinishSettingUpCall - m_t3Call.hCall != NULL"));
  3552. #ifdef DBG
  3553. DebugBreak();
  3554. #endif
  3555. }
  3556. m_t3Call.hCall = hCall;
  3557. //
  3558. // Set filter events for this call
  3559. //
  3560. m_EventMasks.SetTapiSrvCallEventMask( m_t3Call.hCall );
  3561. //
  3562. // note - we can miss messages if something comes in between the time time
  3563. // we get the reply, and the time we insert the call
  3564. //
  3565. AddCallToHashTable();
  3566. CheckAndCreateFakeCallHub();
  3567. ResetCallParams();
  3568. LOG((TL_TRACE, "FinishSettingUpCall - finish"));
  3569. }
  3570. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3571. //
  3572. // not called in Lock()
  3573. //
  3574. // returns S_OK if gets to connected
  3575. // S_FALSE otherwise
  3576. //
  3577. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3578. HRESULT
  3579. CCall::SyncWait( HANDLE hEvent )
  3580. {
  3581. HRESULT hr = S_OK;
  3582. //
  3583. // wait for connected event
  3584. //
  3585. extern DWORD gdwTapi3SyncWaitTimeOut;
  3586. WaitForSingleObject(
  3587. hEvent,
  3588. gdwTapi3SyncWaitTimeOut
  3589. );
  3590. Lock();
  3591. //
  3592. // get rid of event
  3593. //
  3594. ClearConnectedEvent();
  3595. //
  3596. // it it is connected
  3597. // return S_OK
  3598. //
  3599. if (m_CallState == CS_CONNECTED)
  3600. {
  3601. LOG((TL_INFO, "Connect - reached connected state"));
  3602. Unlock();
  3603. LOG((TL_TRACE, "Connect - exit bSync - return SUCCESS"));
  3604. hr = S_OK;
  3605. }
  3606. //
  3607. // if it is disconnect or times out
  3608. // return S_FALSE;
  3609. //
  3610. else
  3611. {
  3612. LOG((TL_ERROR, "Connect - did not reach connected state"));
  3613. //
  3614. // if it isn't disconnected (it timed out), make it disconnect
  3615. //
  3616. if (m_CallState != CS_DISCONNECTED)
  3617. {
  3618. if ( m_t3Call.hCall != NULL )
  3619. {
  3620. LONG lResult;
  3621. lResult = LineDrop(
  3622. m_t3Call.hCall,
  3623. NULL,
  3624. 0
  3625. );
  3626. if ( lResult < 0 )
  3627. {
  3628. LOG((TL_ERROR, "Connect - LineDrop failed %lx", lResult ));
  3629. m_CallState = CS_DISCONNECTED;
  3630. }
  3631. }
  3632. }
  3633. Unlock();
  3634. LOG((TL_TRACE, "Connect - exit bSync - return S_FALSE"));
  3635. hr = S_FALSE;
  3636. }
  3637. return hr;
  3638. }
  3639. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3640. //
  3641. // this must be created inside the same
  3642. // Lock() as the call to tapisrv
  3643. // otherwise, the connected message
  3644. // may appear before the event
  3645. // exists
  3646. //
  3647. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3648. HANDLE
  3649. CCall::CreateConnectedEvent()
  3650. {
  3651. m_hConnectedEvent = CreateEvent(
  3652. NULL,
  3653. FALSE,
  3654. FALSE,
  3655. NULL
  3656. );
  3657. return m_hConnectedEvent;
  3658. }
  3659. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3660. //
  3661. // ClearConnectedEvent
  3662. // called in Lock()
  3663. //
  3664. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3665. void
  3666. CCall::ClearConnectedEvent()
  3667. {
  3668. if ( NULL != m_hConnectedEvent )
  3669. {
  3670. CloseHandle( m_hConnectedEvent );
  3671. m_hConnectedEvent = NULL;
  3672. }
  3673. }
  3674. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3675. //
  3676. // DialAsConsultationCall
  3677. //
  3678. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3679. HRESULT
  3680. CCall::DialAsConsultationCall(
  3681. CCall * pRelatedCall,
  3682. DWORD dwCallFeatures,
  3683. BOOL bConference,
  3684. BOOL bSync
  3685. )
  3686. {
  3687. //
  3688. // do we support Linedial or makeCall for creating our consultation call ?
  3689. //
  3690. LONG lCap;
  3691. BOOL bCap;
  3692. DWORD dwConsultFlags;
  3693. HRESULT hr = S_OK;
  3694. m_pAddress->get_AddressCapability( AC_ADDRESSCAPFLAGS, &lCap );
  3695. if (bConference)
  3696. {
  3697. bCap = lCap & LINEADDRCAPFLAGS_CONFERENCEMAKE;
  3698. dwConsultFlags = CALLFLAG_CONFCONSULT|CALLFLAG_CONSULTCALL;
  3699. }
  3700. else
  3701. {
  3702. bCap = lCap & LINEADDRCAPFLAGS_TRANSFERMAKE;
  3703. dwConsultFlags = CALLFLAG_TRANSFCONSULT|CALLFLAG_CONSULTCALL;
  3704. }
  3705. if ( !(dwCallFeatures & LINECALLFEATURE_DIAL) &&
  3706. (bCap) )
  3707. {
  3708. //
  3709. // We need to do a makecall to create a consultation call
  3710. // lose the consulation call handle created by lineSetupConference
  3711. //
  3712. hr = Disconnect(DC_NORMAL);
  3713. //
  3714. // Make the new call
  3715. //
  3716. hr = Connect((BOOL)bSync);
  3717. if(SUCCEEDED(hr) )
  3718. {
  3719. SetRelatedCall(
  3720. pRelatedCall,
  3721. dwConsultFlags
  3722. );
  3723. }
  3724. else
  3725. {
  3726. LOG((TL_INFO, "DialAsConsultationCall - Consultation makeCall failed"));
  3727. }
  3728. }
  3729. else // We can linedial our consultaion call
  3730. {
  3731. //
  3732. // Wait for dialtone or equivalent
  3733. //
  3734. hr = WaitForCallState(CS_INPROGRESS);
  3735. if(SUCCEEDED(hr) )
  3736. {
  3737. hr = DialConsultCall(bSync);
  3738. if(SUCCEEDED(hr) )
  3739. {
  3740. SetRelatedCall(
  3741. pRelatedCall,
  3742. dwConsultFlags
  3743. );
  3744. }
  3745. else // LineDial failed
  3746. {
  3747. LOG((TL_ERROR, "DialAsConsultationCall - DialConsultCall failed" ));
  3748. }
  3749. }
  3750. else
  3751. {
  3752. LOG((TL_ERROR, "DialAsConsultationCall - Failed to get to CS_INPROGRESS (dialtone) on consult call"));
  3753. }
  3754. } // Endif - Linedial or make call for consultation ?
  3755. return hr;
  3756. }
  3757. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3758. //
  3759. // SetCallInfoDirty
  3760. //
  3761. // not called in lock
  3762. //
  3763. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3764. void
  3765. CCall::SetCallInfoDirty()
  3766. {
  3767. Lock();
  3768. m_dwCallFlags |= CALLFLAG_CALLINFODIRTY;
  3769. Unlock();
  3770. }
  3771. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3772. //
  3773. // SetMediaMode
  3774. //
  3775. // called in lock
  3776. //
  3777. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3778. void
  3779. CCall::SetMediaMode( DWORD dwMediaMode )
  3780. {
  3781. m_dwMediaMode = dwMediaMode;
  3782. }
  3783. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3784. //
  3785. // SetCallState
  3786. //
  3787. // called in lock
  3788. //
  3789. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3790. void
  3791. CCall::SetCallState( CALL_STATE cs )
  3792. {
  3793. m_CallState = cs;
  3794. if ( CS_OFFERING == cs )
  3795. {
  3796. m_dwCallFlags |= CALLFLAG_INCOMING;
  3797. }
  3798. }
  3799. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3800. //
  3801. // OnWaveMSPCall
  3802. //
  3803. // called in lock
  3804. //
  3805. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3806. BOOL
  3807. CCall::OnWaveMSPCall()
  3808. {
  3809. Lock();
  3810. BOOL bWaveMSPCall = ( ( NULL != m_pMSPCall ) && m_pAddress->HasWaveDevice() );
  3811. Unlock();
  3812. return bWaveMSPCall;
  3813. }
  3814. #ifdef USE_PHONEMSP
  3815. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3816. //
  3817. // OnPhoneMSPCall
  3818. //
  3819. // called in lock
  3820. //
  3821. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3822. BOOL
  3823. CCall::OnPhoneMSPCall()
  3824. {
  3825. return ( ( NULL != m_pMSPCall ) && m_pAddress->HasPhoneDevice() );
  3826. }
  3827. #endif USE_PHONEMSP
  3828. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3829. //
  3830. //
  3831. //
  3832. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3833. CAddress *
  3834. CCall::GetCAddress()
  3835. {
  3836. return m_pAddress;
  3837. }
  3838. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3839. //
  3840. // GetStreamControl
  3841. //
  3842. // called in lock
  3843. //
  3844. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3845. ITStreamControl *
  3846. CCall::GetStreamControl()
  3847. {
  3848. HRESULT hr;
  3849. ITStreamControl * pStreamControl;
  3850. // +++ FIXBUG 90668 +++
  3851. if( NULL == m_pMSPCall )
  3852. {
  3853. return NULL;
  3854. }
  3855. hr = m_pMSPCall->QueryInterface(
  3856. IID_ITStreamControl,
  3857. (void**)&pStreamControl
  3858. );
  3859. if ( !SUCCEEDED(hr) )
  3860. {
  3861. return NULL;
  3862. }
  3863. return pStreamControl;
  3864. }
  3865. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3866. //
  3867. // GetMSPCall()
  3868. //
  3869. // not called in lock
  3870. //
  3871. //
  3872. // returns the IUnknown of the msp call (the object we are
  3873. // aggregating)
  3874. //
  3875. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3876. IUnknown *
  3877. CCall::GetMSPCall()
  3878. {
  3879. IUnknown * pUnk;
  3880. Lock();
  3881. pUnk = m_pMSPCall;
  3882. Unlock();
  3883. if ( NULL != pUnk )
  3884. {
  3885. pUnk->AddRef();
  3886. }
  3887. return pUnk;
  3888. }
  3889. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3890. //
  3891. // CCall::DetectDigits
  3892. //
  3893. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3894. STDMETHODIMP
  3895. CCall::DetectDigits(TAPI_DIGITMODE DigitMode)
  3896. {
  3897. HRESULT hr;
  3898. HCALL hCall;
  3899. LOG((TL_TRACE, "DetectDigits - enter"));
  3900. Lock();
  3901. hCall = m_t3Call.hCall;
  3902. Unlock();
  3903. if ( NULL == hCall )
  3904. {
  3905. LOG((TL_TRACE, "DetectDigits - need a call first"));
  3906. return TAPI_E_INVALCALLSTATE;
  3907. }
  3908. hr = LineMonitorDigits(
  3909. hCall,
  3910. DigitMode
  3911. );
  3912. LOG((TL_TRACE, "DetectDigits - exit - return %lx", hr));
  3913. return hr;
  3914. }
  3915. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3916. //
  3917. // CCall::GenerateDigits
  3918. //
  3919. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3920. STDMETHODIMP
  3921. CCall::GenerateDigits(
  3922. BSTR pDigits,
  3923. TAPI_DIGITMODE DigitMode
  3924. )
  3925. {
  3926. HRESULT hr;
  3927. LOG((TL_TRACE, "GenerateDigits - enter"));
  3928. hr = GenerateDigits2(pDigits, DigitMode, 0);
  3929. LOG((TL_TRACE, "GenerateDigits - exit - return %lx", hr));
  3930. return hr;
  3931. }
  3932. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3933. //
  3934. // CCall::GenerateDigits2
  3935. //
  3936. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3937. STDMETHODIMP
  3938. CCall::GenerateDigits2(
  3939. BSTR pDigits,
  3940. TAPI_DIGITMODE DigitMode,
  3941. long lDuration
  3942. )
  3943. {
  3944. HRESULT hr;
  3945. HCALL hCall;
  3946. LOG((TL_TRACE, "GenerateDigits2 - enter"));
  3947. // It is alright for pDigits to be NULL
  3948. if ( ( pDigits != NULL ) && IsBadStringPtrW( pDigits, -1 ) )
  3949. {
  3950. LOG((TL_TRACE, "GenerateDigits2 - bad string"));
  3951. return E_POINTER;
  3952. }
  3953. Lock();
  3954. hCall = m_t3Call.hCall;
  3955. Unlock();
  3956. if ( NULL == hCall )
  3957. {
  3958. LOG((TL_TRACE, "GenerateDigits2 - need call first"));
  3959. return TAPI_E_INVALCALLSTATE;
  3960. }
  3961. //
  3962. // special case for wavemsp
  3963. // suspend the stream so the wave devices are closed before the
  3964. // tapi function starts. SuspendWaveMSPStream is a synchronous
  3965. // call.
  3966. //
  3967. // But if pDigits is NULL, then we do not suspend the stream, as
  3968. // this call is only intended to cancel an already-pending
  3969. // LineGenerateDigits. Only one event will be fired in this case,
  3970. // and the specifics of the event will indicate whether the digit
  3971. // generation was completed or aborted -- the LGD(NULL) itself
  3972. // never results in a separate event being fired.
  3973. //
  3974. if ( OnWaveMSPCall() && ( pDigits != NULL ) )
  3975. {
  3976. SuspendWaveMSPStream();
  3977. }
  3978. hr = LineGenerateDigits(
  3979. hCall,
  3980. DigitMode,
  3981. pDigits,
  3982. lDuration
  3983. );
  3984. //
  3985. // For a wavemsp call, we will tell the wavemsp to resume the stream when
  3986. // we receive the digit completion event from tapisrv. However, if the
  3987. // LineGenerateDigits failed synchronously, then we will never receive
  3988. // such an event, so we must resume the stream now.
  3989. //
  3990. // Also see above -- we didn't suspend the stream if the digit string
  3991. // is NULL.
  3992. //
  3993. if ( OnWaveMSPCall() && ( pDigits != NULL ) && FAILED(hr) )
  3994. {
  3995. ResumeWaveMSPStream();
  3996. }
  3997. LOG((TL_TRACE, "GenerateDigits2 - exit - return %lx", hr));
  3998. return hr;
  3999. }
  4000. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4001. //
  4002. // CCall::GatherDigits
  4003. //
  4004. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4005. STDMETHODIMP
  4006. CCall::GatherDigits(
  4007. TAPI_DIGITMODE DigitMode,
  4008. long lNumDigits,
  4009. BSTR pTerminationDigits,
  4010. long lFirstDigitTimeout,
  4011. long lInterDigitTimeout
  4012. )
  4013. {
  4014. HRESULT hr;
  4015. HCALL hCall;
  4016. LPWSTR pDigitBuffer;
  4017. BOOL fResult;
  4018. LOG((TL_TRACE, "GatherDigits - enter"));
  4019. // It is alright for pTerminationDigits to be NULL
  4020. if ( ( pTerminationDigits != NULL ) && IsBadStringPtrW( pTerminationDigits, -1 ) )
  4021. {
  4022. LOG((TL_TRACE, "GatherDigits - bad string"));
  4023. return E_POINTER;
  4024. }
  4025. Lock();
  4026. hCall = m_t3Call.hCall;
  4027. Unlock();
  4028. if ( NULL == hCall )
  4029. {
  4030. LOG((TL_TRACE, "GatherDigits - need a call first"));
  4031. return TAPI_E_INVALCALLSTATE;
  4032. }
  4033. if (lNumDigits)
  4034. {
  4035. //
  4036. // Allocate the digit string
  4037. //
  4038. pDigitBuffer = (LPWSTR)ClientAlloc( (lNumDigits + 1)*sizeof(WCHAR) );
  4039. if (NULL == pDigitBuffer)
  4040. {
  4041. LOG((TL_TRACE, "GatherDigits - out of memory"));
  4042. return E_OUTOFMEMORY;
  4043. }
  4044. ZeroMemory(pDigitBuffer, (lNumDigits + 1)*sizeof(WCHAR) );
  4045. Lock();
  4046. //
  4047. // Add digit string to the queue
  4048. //
  4049. fResult = m_GatherDigitsQueue.Add(pDigitBuffer);
  4050. if (FALSE == fResult)
  4051. {
  4052. LOG((TL_TRACE, "GatherDigits - unable to add to queue"));
  4053. ClientFree( pDigitBuffer );
  4054. return E_OUTOFMEMORY;
  4055. }
  4056. hr = LineGatherDigits(
  4057. hCall,
  4058. DigitMode,
  4059. pDigitBuffer,
  4060. lNumDigits,
  4061. pTerminationDigits,
  4062. lFirstDigitTimeout,
  4063. lInterDigitTimeout
  4064. );
  4065. if ( FAILED(hr) )
  4066. {
  4067. fResult = m_GatherDigitsQueue.Remove(pDigitBuffer);
  4068. if (TRUE == fResult)
  4069. {
  4070. ClientFree( pDigitBuffer );
  4071. }
  4072. else
  4073. {
  4074. LOG((TL_TRACE, "GatherDigits - unable to remove from queue"));
  4075. // This shouldn't happen
  4076. _ASSERTE(FALSE);
  4077. }
  4078. }
  4079. Unlock();
  4080. }
  4081. else
  4082. {
  4083. //
  4084. // lNumDigits == 0 means cancel the gather digits
  4085. //
  4086. hr = LineGatherDigits(
  4087. hCall,
  4088. DigitMode,
  4089. NULL,
  4090. 0,
  4091. pTerminationDigits,
  4092. lFirstDigitTimeout,
  4093. lInterDigitTimeout
  4094. );
  4095. }
  4096. LOG((TL_TRACE, "GatherDigits - exit - return %lx", hr));
  4097. return hr;
  4098. }
  4099. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4100. //
  4101. // CCall::DetectTones
  4102. //
  4103. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4104. STDMETHODIMP
  4105. CCall::DetectTones(
  4106. TAPI_DETECTTONE * pToneList,
  4107. long lNumTones
  4108. )
  4109. {
  4110. HRESULT hr;
  4111. HCALL hCall;
  4112. LOG((TL_TRACE, "DetectTones - enter"));
  4113. //
  4114. // pToneList == NULL is ok, it means cancel tone detection
  4115. //
  4116. if ( (pToneList != NULL) && IsBadReadPtr( pToneList, lNumTones * sizeof(TAPI_DETECTTONE) ))
  4117. {
  4118. LOG((TL_TRACE, "DetectTones - invalid pointer"));
  4119. return E_POINTER;
  4120. }
  4121. Lock();
  4122. hCall = m_t3Call.hCall;
  4123. Unlock();
  4124. if ( NULL == hCall )
  4125. {
  4126. LOG((TL_TRACE, "DetectTones - need a call first"));
  4127. return TAPI_E_INVALCALLSTATE;
  4128. }
  4129. hr = LineMonitorTones(
  4130. hCall,
  4131. (LPLINEMONITORTONE)pToneList,
  4132. lNumTones
  4133. );
  4134. LOG((TL_TRACE, "DetectTones - exit - return %lx", hr));
  4135. return hr;
  4136. }
  4137. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4138. //
  4139. // CCall::DetectTonesByCollection
  4140. //
  4141. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4142. STDMETHODIMP
  4143. CCall::DetectTonesByCollection(
  4144. ITCollection2 * pDetectToneCollection
  4145. )
  4146. {
  4147. HRESULT hr;
  4148. TAPI_DETECTTONE * pToneList = NULL;
  4149. long lNumTones = 0;
  4150. long lCount;
  4151. LOG((TL_TRACE, "DetectTonesByCollection - enter"));
  4152. //
  4153. // pDetectToneCollection == NULL is ok, it means cancel tone detection
  4154. //
  4155. if ( (pDetectToneCollection != NULL) && IsBadReadPtr( pDetectToneCollection, sizeof(ITCollection2) ) )
  4156. {
  4157. LOG((TL_ERROR, "DetectTonesByCollection - bad pointer"));
  4158. return E_POINTER;
  4159. }
  4160. if ( pDetectToneCollection != NULL )
  4161. {
  4162. //
  4163. // Find out how many items are in the collection and allocate an appropriately
  4164. // sized data structure
  4165. //
  4166. hr = pDetectToneCollection->get_Count(&lCount);
  4167. if ( FAILED(hr) )
  4168. {
  4169. LOG((TL_ERROR, "DetectTonesByCollection - get_Count failed - return %lx", hr));
  4170. return hr;
  4171. }
  4172. pToneList = (TAPI_DETECTTONE *)ClientAlloc( lCount * sizeof(TAPI_DETECTTONE) );
  4173. if ( NULL == pToneList )
  4174. {
  4175. LOG((TL_ERROR, "DetectTonesByCollection - out of memory"));
  4176. return E_OUTOFMEMORY;
  4177. }
  4178. //
  4179. // Go through collection
  4180. //
  4181. for ( int i = 1; i <= lCount; i++ )
  4182. {
  4183. ITDetectTone * pDetectTone;
  4184. IDispatch * pDisp;
  4185. VARIANT var;
  4186. hr = pDetectToneCollection->get_Item(i, &var);
  4187. if ( FAILED(hr) )
  4188. {
  4189. LOG((TL_WARN, "DetectTonesByCollection - get_Item failed - %lx", hr));
  4190. continue;
  4191. }
  4192. //
  4193. // get the IDispatch pointer out of the variant
  4194. //
  4195. try
  4196. {
  4197. if ( var.vt != VT_DISPATCH )
  4198. {
  4199. LOG((TL_WARN, "DetectTonesByCollection - expected VT_DISPATCH"));
  4200. continue;
  4201. }
  4202. pDisp = V_DISPATCH(&var);
  4203. }
  4204. catch(...)
  4205. {
  4206. LOG((TL_WARN, "DetectTonesByCollection - bad variant"));
  4207. continue;
  4208. }
  4209. if ( IsBadReadPtr( pDisp, sizeof(IDispatch) ) )
  4210. {
  4211. LOG((TL_WARN, "DetectTonesByCollection - bad pointer"));
  4212. continue;
  4213. }
  4214. //
  4215. // Query for the ITDetectTone interface
  4216. //
  4217. hr = pDisp->QueryInterface( IID_ITDetectTone, (void **) &pDetectTone );
  4218. if ( FAILED(hr) )
  4219. {
  4220. LOG((TL_WARN, "DetectTonesByCollection - QI failed - %lx", hr));
  4221. continue;
  4222. }
  4223. //
  4224. // Fill in the data structure with information from ITDetectTone
  4225. //
  4226. pDetectTone->get_AppSpecific((long *)&pToneList[lNumTones].dwAppSpecific);
  4227. pDetectTone->get_Duration((long *)&pToneList[lNumTones].dwDuration);
  4228. pDetectTone->get_Frequency(1, (long *)&pToneList[lNumTones].dwFrequency1);
  4229. pDetectTone->get_Frequency(2, (long *)&pToneList[lNumTones].dwFrequency2);
  4230. pDetectTone->get_Frequency(3, (long *)&pToneList[lNumTones].dwFrequency3);
  4231. LOG((TL_INFO, "DetectTonesByCollection - **** Tone %d ****", lNumTones));
  4232. LOG((TL_INFO, "DetectTonesByCollection - AppSpecific %d", pToneList[lNumTones].dwAppSpecific));
  4233. LOG((TL_INFO, "DetectTonesByCollection - Duration %d", pToneList[lNumTones].dwDuration));
  4234. LOG((TL_INFO, "DetectTonesByCollection - Frequency1 %d", pToneList[lNumTones].dwFrequency1));
  4235. LOG((TL_INFO, "DetectTonesByCollection - Frequency2 %d", pToneList[lNumTones].dwFrequency2));
  4236. LOG((TL_INFO, "DetectTonesByCollection - Frequency3 %d", pToneList[lNumTones].dwFrequency3));
  4237. lNumTones++;
  4238. pDetectTone->Release();
  4239. }
  4240. }
  4241. hr = DetectTones( pToneList, lNumTones );
  4242. LOG((TL_TRACE, "DetectTonesByCollection - exit - return %lx", hr));
  4243. return hr;
  4244. }
  4245. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4246. //
  4247. // CCall::GenerateTone
  4248. //
  4249. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4250. STDMETHODIMP
  4251. CCall::GenerateTone(
  4252. TAPI_TONEMODE ToneMode,
  4253. long lDuration
  4254. )
  4255. {
  4256. HRESULT hr;
  4257. HCALL hCall;
  4258. LOG((TL_TRACE, "GenerateTone - enter"));
  4259. Lock();
  4260. hCall = m_t3Call.hCall;
  4261. Unlock();
  4262. if ( NULL == hCall )
  4263. {
  4264. LOG((TL_TRACE, "GenerateTone - need call first"));
  4265. return TAPI_E_INVALCALLSTATE;
  4266. }
  4267. if ( ToneMode == (TAPI_TONEMODE)LINETONEMODE_CUSTOM ) // no custom tones
  4268. {
  4269. return E_INVALIDARG;
  4270. }
  4271. //
  4272. // special case for wavemsp
  4273. // suspend the stream so the wave devices are closed before the
  4274. // tapi function starts. SuspendWaveMSPStream is a synchronous
  4275. // call.
  4276. //
  4277. // But if ToneMode is 0, then we do not suspend the stream, as
  4278. // this call is only intended to cancel an already-pending
  4279. // LineGenerateTone. Only one event will be fired in this case,
  4280. // and the specifics of the event will indicate whether the tone
  4281. // generation was completed or aborted -- the LGT(0) itself
  4282. // never results in a separate event being fired.
  4283. //
  4284. if ( OnWaveMSPCall() && ( ToneMode != (TAPI_TONEMODE)0 ) )
  4285. {
  4286. SuspendWaveMSPStream();
  4287. }
  4288. hr = LineGenerateTone(
  4289. hCall,
  4290. ToneMode,
  4291. lDuration,
  4292. 0,
  4293. NULL
  4294. );
  4295. //
  4296. // For a wavemsp call, we will tell the wavemsp to resume the stream when
  4297. // we receive the digit completion event from tapisrv. However, if the
  4298. // LineGenerateTone failed synchronously, then we will never receive
  4299. // such an event, so we must resume the stream now.
  4300. //
  4301. // Also see above -- we didn't suspend the stream if the ToneMode
  4302. // is 0.
  4303. //
  4304. if ( OnWaveMSPCall() && ( ToneMode != (TAPI_TONEMODE)0 ) && FAILED(hr) )
  4305. {
  4306. ResumeWaveMSPStream();
  4307. }
  4308. LOG((TL_TRACE, "GenerateTone - exit - return %lx", hr));
  4309. return hr;
  4310. }
  4311. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4312. //
  4313. // CCall::GenerateCustomTones
  4314. //
  4315. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4316. STDMETHODIMP
  4317. CCall::GenerateCustomTones(
  4318. TAPI_CUSTOMTONE * pToneList,
  4319. long lNumTones,
  4320. long lDuration
  4321. )
  4322. {
  4323. HRESULT hr;
  4324. HCALL hCall;
  4325. LOG((TL_TRACE, "GenerateCustomTones - enter"));
  4326. if ( IsBadReadPtr( pToneList, lNumTones * sizeof(TAPI_CUSTOMTONE) ) )
  4327. {
  4328. LOG((TL_TRACE, "GenerateCustomTones - invalid pointer"));
  4329. return E_POINTER;
  4330. }
  4331. Lock();
  4332. hCall = m_t3Call.hCall;
  4333. Unlock();
  4334. if ( NULL == hCall )
  4335. {
  4336. LOG((TL_TRACE, "GenerateCustomTones - need call first"));
  4337. return TAPI_E_INVALCALLSTATE;
  4338. }
  4339. //
  4340. // special case for wavemsp
  4341. // suspend the stream so the wave devices are closed before the
  4342. // tapi function starts. SuspendWaveMSPStream is a synchronous
  4343. // call.
  4344. //
  4345. if ( OnWaveMSPCall() )
  4346. {
  4347. SuspendWaveMSPStream();
  4348. }
  4349. hr = LineGenerateTone(
  4350. hCall,
  4351. LINETONEMODE_CUSTOM,
  4352. lDuration,
  4353. lNumTones,
  4354. (LPLINEGENERATETONE)pToneList
  4355. );
  4356. //
  4357. // For a wavemsp call, we will tell the wavemsp to resume the stream when
  4358. // we receive the digit completion event from tapisrv. However, if the
  4359. // LineGenerateTone failed synchronously, then we will never receive
  4360. // such an event, so we must resume the stream now.
  4361. //
  4362. if ( OnWaveMSPCall() && FAILED(hr) )
  4363. {
  4364. ResumeWaveMSPStream();
  4365. }
  4366. LOG((TL_TRACE, "GenerateCustomTones - exit - return %lx", hr));
  4367. return hr;
  4368. }
  4369. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4370. //
  4371. // CCall::GenerateCustomTonesByCollection
  4372. //
  4373. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4374. STDMETHODIMP
  4375. CCall::GenerateCustomTonesByCollection(
  4376. ITCollection2 * pCustomToneCollection,
  4377. long lDuration
  4378. )
  4379. {
  4380. HRESULT hr;
  4381. TAPI_CUSTOMTONE * pToneList = NULL;
  4382. long lNumTones = 0;
  4383. long lCount;
  4384. LOG((TL_TRACE, "GenerateCustomTonesByCollection - enter"));
  4385. if ( IsBadReadPtr( pCustomToneCollection, sizeof(ITCollection2) ) )
  4386. {
  4387. LOG((TL_ERROR, "GenerateCustomTonesByCollection - bad pointer"));
  4388. return E_POINTER;
  4389. }
  4390. //
  4391. // Find out how many items are in the collection and allocate an appropriately
  4392. // sized data structure
  4393. //
  4394. hr = pCustomToneCollection->get_Count(&lCount);
  4395. if ( FAILED(hr) )
  4396. {
  4397. LOG((TL_ERROR, "GenerateCustomTonesByCollection - get_Count failed - return %lx", hr));
  4398. return hr;
  4399. }
  4400. pToneList = (TAPI_CUSTOMTONE *)ClientAlloc( lCount * sizeof(TAPI_CUSTOMTONE) );
  4401. if ( NULL == pToneList )
  4402. {
  4403. LOG((TL_ERROR, "GenerateCustomTonesByCollection - out of memory"));
  4404. return E_OUTOFMEMORY;
  4405. }
  4406. //
  4407. // Go through collection
  4408. //
  4409. for ( int i = 1; i <= lCount; i++ )
  4410. {
  4411. ITCustomTone * pCustomTone;
  4412. IDispatch * pDisp;
  4413. VARIANT var;
  4414. hr = pCustomToneCollection->get_Item(i, &var);
  4415. if ( FAILED(hr) )
  4416. {
  4417. LOG((TL_WARN, "GenerateCustomTonesByCollection - get_Item failed - %lx", hr));
  4418. continue;
  4419. }
  4420. //
  4421. // get the IDispatch pointer out of the variant
  4422. //
  4423. try
  4424. {
  4425. if ( var.vt != VT_DISPATCH )
  4426. {
  4427. LOG((TL_WARN, "GenerateCustomTonesByCollection - expected VT_DISPATCH"));
  4428. continue;
  4429. }
  4430. pDisp = V_DISPATCH(&var);
  4431. }
  4432. catch(...)
  4433. {
  4434. LOG((TL_WARN, "GenerateCustomTonesByCollection - bad variant"));
  4435. continue;
  4436. }
  4437. if ( IsBadReadPtr( pDisp, sizeof(IDispatch) ) )
  4438. {
  4439. LOG((TL_WARN, "GenerateCustomTonesByCollection - bad pointer"));
  4440. continue;
  4441. }
  4442. //
  4443. // Query for the ITDetectTone interface
  4444. //
  4445. hr = pDisp->QueryInterface( IID_ITCustomTone, (void **) &pCustomTone );
  4446. if ( FAILED(hr) )
  4447. {
  4448. LOG((TL_WARN, "GenerateCustomTonesByCollection - QI failed - %lx", hr));
  4449. continue;
  4450. }
  4451. //
  4452. // Fill in the data structure with information from ITDetectTone
  4453. //
  4454. pCustomTone->get_CadenceOff((long *)&pToneList[lNumTones].dwCadenceOff);
  4455. pCustomTone->get_CadenceOn((long *)&pToneList[lNumTones].dwCadenceOn);
  4456. pCustomTone->get_Frequency((long *)&pToneList[lNumTones].dwFrequency);
  4457. pCustomTone->get_Volume((long *)&pToneList[lNumTones].dwVolume);
  4458. LOG((TL_INFO, "GenerateCustomTonesByCollection - **** Tone %d ****", lNumTones));
  4459. LOG((TL_INFO, "GenerateCustomTonesByCollection - CadenceOff %d", pToneList[lNumTones].dwCadenceOff));
  4460. LOG((TL_INFO, "GenerateCustomTonesByCollection - CadenceOn %d", pToneList[lNumTones].dwCadenceOn));
  4461. LOG((TL_INFO, "GenerateCustomTonesByCollection - Frequency %d", pToneList[lNumTones].dwFrequency));
  4462. LOG((TL_INFO, "GenerateCustomTonesByCollection - Volume %d", pToneList[lNumTones].dwVolume));
  4463. lNumTones++;
  4464. pCustomTone->Release();
  4465. }
  4466. hr = GenerateCustomTones( pToneList, lNumTones, lDuration );
  4467. LOG((TL_TRACE, "GenerateCustomTonesByCollection - exit - return %lx", hr));
  4468. return hr;
  4469. }
  4470. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4471. //
  4472. // CCall::CreateDetectToneObject
  4473. //
  4474. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4475. STDMETHODIMP
  4476. CCall::CreateDetectToneObject(
  4477. ITDetectTone ** ppDetectTone
  4478. )
  4479. {
  4480. HRESULT hr;
  4481. LOG((TL_TRACE, "CreateDetectToneObject enter"));
  4482. if ( TAPIIsBadWritePtr( ppDetectTone, sizeof( ITDetectTone * ) ) )
  4483. {
  4484. LOG((TL_ERROR, "CreateDetectToneObject - bad pointer"));
  4485. return E_POINTER;
  4486. }
  4487. // Initialize the return value in case we fail
  4488. *ppDetectTone = NULL;
  4489. CComObject< CDetectTone > * p;
  4490. hr = CComObject< CDetectTone >::CreateInstance( &p );
  4491. if ( S_OK != hr )
  4492. {
  4493. LOG((TL_ERROR, "CreateDetectToneObject - could not create CDetectTone" ));
  4494. return E_OUTOFMEMORY;
  4495. }
  4496. // get the ITDetectTone interface
  4497. hr = p->QueryInterface( IID_ITDetectTone, (void **) ppDetectTone );
  4498. if ( FAILED(hr) )
  4499. {
  4500. LOG((TL_ERROR, "CreateDetectToneObject - could not get IDispatch interface" ));
  4501. delete p;
  4502. return hr;
  4503. }
  4504. LOG((TL_TRACE, "CreateDetectToneObject - exit - return %lx", hr ));
  4505. return hr;
  4506. }
  4507. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4508. //
  4509. // CCall::CreateCustomToneObject
  4510. //
  4511. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4512. STDMETHODIMP
  4513. CCall::CreateCustomToneObject(
  4514. ITCustomTone ** ppCustomTone
  4515. )
  4516. {
  4517. HRESULT hr;
  4518. LOG((TL_TRACE, "CreateCustomToneObject enter"));
  4519. if ( TAPIIsBadWritePtr( ppCustomTone, sizeof( ITCustomTone * ) ) )
  4520. {
  4521. LOG((TL_ERROR, "CreateCustomToneObject - bad pointer"));
  4522. return E_POINTER;
  4523. }
  4524. // Initialize the return value in case we fail
  4525. *ppCustomTone = NULL;
  4526. CComObject< CCustomTone > * p;
  4527. hr = CComObject< CCustomTone >::CreateInstance( &p );
  4528. if ( S_OK != hr )
  4529. {
  4530. LOG((TL_ERROR, "CreateCustomToneObject - could not create CCustomTone" ));
  4531. return E_OUTOFMEMORY;
  4532. }
  4533. // get the ITCustomTone interface
  4534. hr = p->QueryInterface( IID_ITCustomTone, (void **) ppCustomTone );
  4535. if ( FAILED(hr) )
  4536. {
  4537. LOG((TL_ERROR, "CreateCustomToneObject - could not get ITCustomTone interface" ));
  4538. delete p;
  4539. return hr;
  4540. }
  4541. LOG((TL_TRACE, "CreateCustomToneObject - exit - return %lx", hr ));
  4542. return hr;
  4543. }
  4544. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4545. //
  4546. // CCall::GetID
  4547. //
  4548. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4549. STDMETHODIMP
  4550. CCall::GetID(
  4551. BSTR pDeviceClass,
  4552. DWORD * pdwSize,
  4553. BYTE ** ppDeviceID
  4554. )
  4555. {
  4556. HRESULT hr = S_OK;
  4557. LPVARSTRING pVarString = NULL;
  4558. LOG((TL_TRACE, "GetID - enter"));
  4559. if ( IsBadStringPtrW( pDeviceClass, -1 ) )
  4560. {
  4561. LOG((TL_ERROR, "GetID - bad string"));
  4562. return E_POINTER;
  4563. }
  4564. if ( TAPIIsBadWritePtr( pdwSize, sizeof(DWORD)))
  4565. {
  4566. LOG((TL_ERROR, "GetID - bad size"));
  4567. return E_POINTER;
  4568. }
  4569. if ( TAPIIsBadWritePtr( ppDeviceID, sizeof(BYTE *) ) )
  4570. {
  4571. LOG((TL_ERROR, "GetID - bad pointer"));
  4572. return E_POINTER;
  4573. }
  4574. if( m_t3Call.hCall == NULL )
  4575. {
  4576. if( m_CallState == CS_IDLE )
  4577. {
  4578. LOG((TL_ERROR, "GetID - idle call, invalid call state"));
  4579. return TAPI_E_INVALCALLSTATE;
  4580. }
  4581. else
  4582. {
  4583. LOG((TL_ERROR, "GetID - weird call state!!!"));
  4584. return E_UNEXPECTED;
  4585. }
  4586. }
  4587. hr = LineGetID(
  4588. NULL,
  4589. 0,
  4590. m_t3Call.hCall,
  4591. LINECALLSELECT_CALL,
  4592. &pVarString,
  4593. pDeviceClass
  4594. );
  4595. if ( SUCCEEDED(hr) )
  4596. {
  4597. *ppDeviceID = (BYTE *)CoTaskMemAlloc( pVarString->dwUsedSize );
  4598. if (NULL != *ppDeviceID)
  4599. {
  4600. CopyMemory(
  4601. *ppDeviceID,
  4602. ((LPBYTE)pVarString)+pVarString->dwStringOffset,
  4603. pVarString->dwStringSize
  4604. );
  4605. *pdwSize = pVarString->dwStringSize;
  4606. }
  4607. else
  4608. {
  4609. hr = E_OUTOFMEMORY;
  4610. }
  4611. // Check LineGetID to see if it can succeed w/o setting pVarString
  4612. ClientFree (pVarString);
  4613. }
  4614. LOG((TL_TRACE, "GetID - exit - return %lx", hr));
  4615. return hr;
  4616. }
  4617. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4618. //
  4619. // CCall::GetIDAsVariant
  4620. //
  4621. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4622. STDMETHODIMP CCall::GetIDAsVariant( IN BSTR bstrDeviceClass,
  4623. OUT VARIANT *pVarDeviceID )
  4624. {
  4625. LOG((TL_TRACE, "GetIDAsVariant - enter"));
  4626. //
  4627. // did we get a good string?
  4628. //
  4629. if ( IsBadStringPtrW( bstrDeviceClass, -1 ) )
  4630. {
  4631. LOG((TL_ERROR, "GetIDAsVariant - bad string"));
  4632. return E_POINTER;
  4633. }
  4634. //
  4635. // did we get a good variant?
  4636. //
  4637. if ( IsBadWritePtr( pVarDeviceID, sizeof(VARIANT) ) )
  4638. {
  4639. LOG((TL_ERROR, "GetIDAsVariant - bad variant pointer"));
  4640. return E_POINTER;
  4641. }
  4642. //
  4643. // initialize the variant
  4644. //
  4645. VariantInit(pVarDeviceID);
  4646. //
  4647. // get the buffer containing ID
  4648. //
  4649. DWORD dwDeviceIDBufferSize = 0;
  4650. BYTE *pDeviceIDBuffer = NULL;
  4651. HRESULT hr = GetID(bstrDeviceClass,
  4652. &dwDeviceIDBufferSize,
  4653. &pDeviceIDBuffer);
  4654. if (FAILED(hr))
  4655. {
  4656. LOG((TL_ERROR, "GetIDAsVariant - failed to get device id. hr = %lx", hr));
  4657. return hr;
  4658. }
  4659. //
  4660. // place device id buffer into the variant
  4661. //
  4662. hr = FillVariantFromBuffer(dwDeviceIDBufferSize,
  4663. pDeviceIDBuffer,
  4664. pVarDeviceID);
  4665. //
  4666. // succeeded, or failed, we no longer need the buffer
  4667. //
  4668. CoTaskMemFree(pDeviceIDBuffer);
  4669. pDeviceIDBuffer = NULL;
  4670. if (FAILED(hr))
  4671. {
  4672. LOG((TL_ERROR, "GetIDAsVariant - failed to put device id into a variant. hr = %lx"));
  4673. return hr;
  4674. }
  4675. //
  4676. // done. returning the variant that is array of bytes that contains device id.
  4677. //
  4678. LOG((TL_TRACE, "GetIDAsVariant - exit"));
  4679. return S_OK;
  4680. }
  4681. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4682. //
  4683. // CCall::SetMediaType
  4684. //
  4685. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4686. STDMETHODIMP
  4687. CCall::SetMediaType(long lMediaType)
  4688. {
  4689. LOG((TL_TRACE, "SetMediaType - enter"));
  4690. HRESULT hr;
  4691. Lock();
  4692. HCALL hCall = m_t3Call.hCall;
  4693. Unlock();
  4694. if ( hCall == NULL )
  4695. {
  4696. LOG((TL_ERROR, "SetMediaType - invalid hCall"));
  4697. return E_FAIL;
  4698. }
  4699. hr = LineSetMediaMode( hCall, lMediaType );
  4700. LOG((TL_TRACE, "SetMediaType - exit - return %lx", hr));
  4701. return hr;
  4702. }
  4703. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4704. //
  4705. // CCall::MonitorMedia
  4706. //
  4707. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4708. STDMETHODIMP
  4709. CCall::MonitorMedia(long lMediaType)
  4710. {
  4711. LOG((TL_TRACE, "MonitorMedia - enter"));
  4712. HRESULT hr;
  4713. Lock();
  4714. HCALL hCall = m_t3Call.hCall;
  4715. Unlock();
  4716. if ( hCall == NULL )
  4717. {
  4718. LOG((TL_ERROR, "MonitorMedia - invalid hCall"));
  4719. return E_FAIL;
  4720. }
  4721. hr = lineMonitorMedia( hCall, lMediaType );
  4722. LOG((TL_TRACE, "MonitorMedia - exit - return %lx", hr));
  4723. return hr;
  4724. }
  4725. /////////////////////////////////////////////////////////////////////////////
  4726. // IDispatch implementation
  4727. //
  4728. typedef IDispatchImpl<ITCallInfo2Vtbl<CCall>, &IID_ITCallInfo2, &LIBID_TAPI3Lib> CallInfoType;
  4729. typedef IDispatchImpl<ITBasicCallControl2Vtbl<CCall>, &IID_ITBasicCallControl2, &LIBID_TAPI3Lib> BasicCallControlType;
  4730. typedef IDispatchImpl<ITLegacyCallMediaControl2Vtbl<CCall>, &IID_ITLegacyCallMediaControl2, &LIBID_TAPI3Lib> LegacyCallMediaControlType;
  4731. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4732. //
  4733. // CCall::GetIDsOfNames
  4734. //
  4735. // Overide if IDispatch method
  4736. //
  4737. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4738. STDMETHODIMP CCall::GetIDsOfNames(REFIID riid,
  4739. LPOLESTR* rgszNames,
  4740. UINT cNames,
  4741. LCID lcid,
  4742. DISPID* rgdispid
  4743. )
  4744. {
  4745. HRESULT hr = DISP_E_UNKNOWNNAME;
  4746. // See if the requsted method belongs to the default interface
  4747. hr = CallInfoType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  4748. if (SUCCEEDED(hr))
  4749. {
  4750. LOG((TL_INFO, "GetIDsOfNames - found %S on ITCallInfo", *rgszNames));
  4751. rgdispid[0] |= IDISPCALLINFO;
  4752. return hr;
  4753. }
  4754. // If not, then try the Basic Call control interface
  4755. hr = BasicCallControlType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  4756. if (SUCCEEDED(hr))
  4757. {
  4758. LOG((TL_INFO, "GetIDsOfNames - found %S on ITBasicCallControl", *rgszNames));
  4759. rgdispid[0] |= IDISPBASICCALLCONTROL;
  4760. return hr;
  4761. }
  4762. // If not, then try the Legacy CAll Media Control interface
  4763. hr = LegacyCallMediaControlType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  4764. if (SUCCEEDED(hr))
  4765. {
  4766. LOG((TL_INFO, "GetIDsOfNames - found %S on ITLegacyCallMediaControl", *rgszNames));
  4767. rgdispid[0] |= IDISPLEGACYCALLMEDIACONTROL;
  4768. return hr;
  4769. }
  4770. // If not, then try the aggregated MSP Call object
  4771. if (m_pMSPCall != NULL)
  4772. {
  4773. IDispatch *pIDispatchMSPAggCall;
  4774. m_pMSPCall->QueryInterface(IID_IDispatch, (void**)&pIDispatchMSPAggCall);
  4775. hr = pIDispatchMSPAggCall->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  4776. if (SUCCEEDED(hr))
  4777. {
  4778. pIDispatchMSPAggCall->Release();
  4779. LOG((TL_INFO, "GetIDsOfNames - found %S on our aggregated MSP Call", *rgszNames));
  4780. rgdispid[0] |= IDISPAGGREGATEDMSPCALLOBJ;
  4781. return hr;
  4782. }
  4783. pIDispatchMSPAggCall->Release();
  4784. }
  4785. LOG((TL_INFO, "GetIDsOfNames - Didn't find %S on our iterfaces", *rgszNames));
  4786. return hr;
  4787. }
  4788. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4789. //
  4790. // CCall::Invoke
  4791. //
  4792. // Overide if IDispatch method
  4793. //
  4794. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4795. STDMETHODIMP CCall::Invoke(DISPID dispidMember,
  4796. REFIID riid,
  4797. LCID lcid,
  4798. WORD wFlags,
  4799. DISPPARAMS* pdispparams,
  4800. VARIANT* pvarResult,
  4801. EXCEPINFO* pexcepinfo,
  4802. UINT* puArgErr
  4803. )
  4804. {
  4805. HRESULT hr = DISP_E_MEMBERNOTFOUND;
  4806. DWORD dwInterface = (dispidMember & INTERFACEMASK);
  4807. LOG((TL_TRACE, "Invoke - dispidMember %X", dispidMember));
  4808. // Call invoke for the required interface
  4809. switch (dwInterface)
  4810. {
  4811. case IDISPCALLINFO:
  4812. {
  4813. hr = CallInfoType::Invoke(dispidMember,
  4814. riid,
  4815. lcid,
  4816. wFlags,
  4817. pdispparams,
  4818. pvarResult,
  4819. pexcepinfo,
  4820. puArgErr
  4821. );
  4822. break;
  4823. }
  4824. case IDISPBASICCALLCONTROL:
  4825. {
  4826. hr = BasicCallControlType::Invoke(dispidMember,
  4827. riid,
  4828. lcid,
  4829. wFlags,
  4830. pdispparams,
  4831. pvarResult,
  4832. pexcepinfo,
  4833. puArgErr
  4834. );
  4835. break;
  4836. }
  4837. case IDISPLEGACYCALLMEDIACONTROL:
  4838. {
  4839. hr = LegacyCallMediaControlType::Invoke(dispidMember,
  4840. riid,
  4841. lcid,
  4842. wFlags,
  4843. pdispparams,
  4844. pvarResult,
  4845. pexcepinfo,
  4846. puArgErr
  4847. );
  4848. break;
  4849. }
  4850. case IDISPAGGREGATEDMSPCALLOBJ:
  4851. {
  4852. IDispatch *pIDispatchMSPAggCall = NULL;
  4853. if (m_pMSPCall != NULL)
  4854. {
  4855. m_pMSPCall->QueryInterface(IID_IDispatch, (void**)&pIDispatchMSPAggCall);
  4856. hr = pIDispatchMSPAggCall->Invoke(dispidMember,
  4857. riid,
  4858. lcid,
  4859. wFlags,
  4860. pdispparams,
  4861. pvarResult,
  4862. pexcepinfo,
  4863. puArgErr
  4864. );
  4865. pIDispatchMSPAggCall->Release();
  4866. }
  4867. break;
  4868. }
  4869. } // end switch (dwInterface)
  4870. LOG((TL_TRACE, hr, "Invoke - exit" ));
  4871. return hr;
  4872. }
  4873. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4874. //
  4875. // HandleAcceptToAlert
  4876. //
  4877. // Handler for PRIVATE_ISDN__ACCEPTTOALERT message
  4878. // This is processed on the callback thread to do a lineAccept on an offering
  4879. // ISDN call that requires Accept before it will ring. Bug 335566
  4880. //
  4881. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  4882. void HandleAcceptToAlert( PASYNCEVENTMSG pParams )
  4883. {
  4884. HRESULT hr;
  4885. HCALL hCall = (HCALL) pParams->hDevice;
  4886. hr = LineAccept( hCall, NULL, 0 );
  4887. if ( SUCCEEDED(hr) )
  4888. {
  4889. hr = WaitForReply(hr);
  4890. if ( FAILED(hr) )
  4891. {
  4892. LOG((TL_INFO, hr, "HandleAcceptToAlert - lineAccept failed async"));
  4893. }
  4894. }
  4895. else
  4896. {
  4897. LOG((TL_INFO, hr, "HandleAcceptToAlert - lineAccept failed sync"));
  4898. }
  4899. }
  4900. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4901. //
  4902. // OnOffering()
  4903. //
  4904. // If it's an offering call & the TSP requires a lineAccept to start ringing
  4905. // (typically an ISDN feature) then we queue a message to the callback thread
  4906. // to do the lineAccept. We can't do it here because this is processed on
  4907. // the async thread & as lineAccept is an async fucion we would deadlock
  4908. // while waiting for the async reply. Bug 335566
  4909. //
  4910. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4911. HRESULT
  4912. CCall::OnOffering()
  4913. {
  4914. LOG((TL_TRACE, "OnOffering - enter" ));
  4915. HRESULT hr = S_FALSE;
  4916. LONG lCap;
  4917. ASYNCEVENTMSG Msg;
  4918. if (m_pAddress != NULL)
  4919. {
  4920. hr = m_pAddress->get_AddressCapability( AC_ADDRESSCAPFLAGS, &lCap );
  4921. if ( SUCCEEDED(hr) )
  4922. {
  4923. if ( (lCap & LINEADDRCAPFLAGS_ACCEPTTOALERT) && (CP_OWNER == m_CallPrivilege) )
  4924. {
  4925. LOG((TL_TRACE, "OnOffering - queueing PRIVATE_ISDN__ACCEPTTOALERT message."));
  4926. // Build an msg to queue to the callback thread
  4927. Msg.Msg = PRIVATE_ISDN__ACCEPTTOALERT;
  4928. Msg.TotalSize = sizeof (ASYNCEVENTMSG);
  4929. Msg.hDevice = (ULONG_PTR) m_t3Call.hCall;
  4930. Msg.Param1 = 0;
  4931. Msg.Param2 = 0;
  4932. Msg.Param3 = 0;
  4933. QueueCallbackEvent( &Msg );
  4934. // Set the Call flag
  4935. m_dwCallFlags |= CALLFLAG_ACCEPTTOALERT;
  4936. }
  4937. }
  4938. }
  4939. LOG((TL_TRACE, "OnOffering - exit. hr = %lx", hr ));
  4940. return hr;
  4941. }
  4942. //
  4943. // CObjectSafeImpl. since we have aggregates, implement this method
  4944. //
  4945. // return non delegating iunkown of the first aggregated object
  4946. // that supports the interface
  4947. //
  4948. HRESULT CCall::QIOnAggregates(REFIID riid, IUnknown **ppNonDelegatingUnknown)
  4949. {
  4950. //
  4951. // argument check
  4952. //
  4953. if ( TAPIIsBadWritePtr(ppNonDelegatingUnknown, sizeof(IUnknown*)) )
  4954. {
  4955. return E_POINTER;
  4956. }
  4957. //
  4958. // if we fail, at least return consistent values
  4959. //
  4960. *ppNonDelegatingUnknown = NULL;
  4961. //
  4962. // see if mspcall or private support the interface riid
  4963. //
  4964. HRESULT hr = E_FAIL;
  4965. Lock();
  4966. if (m_pMSPCall)
  4967. {
  4968. //
  4969. // does mspcall expose this interface?
  4970. //
  4971. IUnknown *pUnk = NULL;
  4972. hr = m_pMSPCall->QueryInterface(riid, (void**)&pUnk);
  4973. if (SUCCEEDED(hr))
  4974. {
  4975. pUnk->Release();
  4976. pUnk = NULL;
  4977. //
  4978. // return the mspcall's non-delegating unknown
  4979. //
  4980. *ppNonDelegatingUnknown = m_pMSPCall;
  4981. (*ppNonDelegatingUnknown)->AddRef();
  4982. }
  4983. }
  4984. if ( FAILED(hr) && m_pPrivate )
  4985. {
  4986. //
  4987. // bad luck with mspcall? still have a chance with private
  4988. //
  4989. IUnknown *pUnk = NULL;
  4990. hr = m_pPrivate->QueryInterface(riid, (void**)&pUnk);
  4991. if (SUCCEEDED(hr))
  4992. {
  4993. pUnk->Release();
  4994. pUnk = NULL;
  4995. *ppNonDelegatingUnknown = m_pPrivate;
  4996. (*ppNonDelegatingUnknown)->AddRef();
  4997. }
  4998. }
  4999. Unlock();
  5000. return hr;
  5001. }
  5002. // ITBasicCallControl2
  5003. /*++
  5004. RequestTerminal
  5005. ITBasicCallControl2::CreateTerminal() method
  5006. If bstrTerminalClassGUID is CLSID_NULL then
  5007. we'll try to create the default dynamic terminals
  5008. --*/
  5009. STDMETHODIMP CCall::RequestTerminal(
  5010. IN BSTR bstrTerminalClassGUID,
  5011. IN long lMediaType,
  5012. IN TERMINAL_DIRECTION Direction,
  5013. OUT ITTerminal** ppTerminal
  5014. )
  5015. {
  5016. LOG((TL_TRACE, "RequestTerminal - enter" ));
  5017. //
  5018. // Validates arguments
  5019. //
  5020. if( IsBadStringPtrW( bstrTerminalClassGUID, (UINT)-1) )
  5021. {
  5022. LOG((TL_ERROR, "RequestTerminal - exit "
  5023. " bstrTerminalClassGUID invalid, returns E_INVALIDARG"));
  5024. return E_INVALIDARG;
  5025. }
  5026. if( TAPIIsBadWritePtr( ppTerminal, sizeof(ITTerminal*)) )
  5027. {
  5028. LOG((TL_ERROR, "RequestTerminal - exit "
  5029. " ppTerminal invalid, returns E_POINTER"));
  5030. return E_POINTER;
  5031. }
  5032. //
  5033. // Determines if is a static terminal or a dynamic one
  5034. // For static terminal bstrTerminalClassGUID should have one
  5035. // of the following values
  5036. // CLSID_NULL {00000000-0000-0000-0000-000000000000}
  5037. // CLSID_MicrophoneTerminal
  5038. // CLSID_SpeakersTerminal
  5039. // CLSID_VideoInputTerminal
  5040. //
  5041. HRESULT hr = E_FAIL;
  5042. if( IsStaticGUID( bstrTerminalClassGUID ))
  5043. {
  5044. // Create a static terminal
  5045. LOG((TL_INFO, "RequestTerminal -> StaticTerminal" ));
  5046. hr = CreateStaticTerminal(
  5047. bstrTerminalClassGUID,
  5048. Direction,
  5049. lMediaType,
  5050. ppTerminal);
  5051. }
  5052. else
  5053. {
  5054. // Create a dynamic terminal
  5055. LOG((TL_INFO, "RequestTerminal -> DynamicTerminal" ));
  5056. hr = CreateDynamicTerminal(
  5057. bstrTerminalClassGUID,
  5058. Direction,
  5059. lMediaType,
  5060. ppTerminal);
  5061. }
  5062. //
  5063. // Return value
  5064. //
  5065. LOG((TL_TRACE, "RequestTerminal - exit 0x%08x", hr));
  5066. return hr;
  5067. }
  5068. STDMETHODIMP CCall::SelectTerminalOnCall(
  5069. IN ITTerminal *pTerminal
  5070. )
  5071. {
  5072. LOG((TL_TRACE, "SelectTerminalOnCall - enter" ));
  5073. //
  5074. // Validates argument
  5075. //
  5076. if( IsBadReadPtr( pTerminal, sizeof(ITTerminal)) )
  5077. {
  5078. LOG((TL_ERROR, "SelectTerminalOnCall - exit "
  5079. " pTerminal invalid, returns E_POINTER"));
  5080. return E_POINTER;
  5081. }
  5082. //
  5083. // Just a HRESULT
  5084. //
  5085. HRESULT hr = E_FAIL;
  5086. //
  5087. // Is a single or multi track terminal
  5088. //
  5089. ITMultiTrackTerminal* pMultiTrack = NULL;
  5090. hr = pTerminal->QueryInterface(
  5091. IID_ITMultiTrackTerminal,
  5092. (void**)&pMultiTrack);
  5093. if( FAILED(hr) )
  5094. {
  5095. //
  5096. // SingleTrack terminal
  5097. //
  5098. LOG((TL_TRACE, "SelectTerminalOnCall - SingleTrack terminal" ));
  5099. long lMediaType = 0;
  5100. TERMINAL_DIRECTION Direction =TD_NONE;
  5101. hr = SelectSingleTerminalOnCall(
  5102. pTerminal,
  5103. &lMediaType,
  5104. &Direction);
  5105. LOG((TL_TRACE, "SelectTerminalOnCall - "
  5106. "SelectSingleTerminalOnCall exit with 0x%08x", hr));
  5107. }
  5108. else
  5109. {
  5110. //
  5111. // Multitrack terminal
  5112. //
  5113. hr = SelectMultiTerminalOnCall(
  5114. pMultiTrack);
  5115. LOG((TL_TRACE, "SelectTerminalOnCall - "
  5116. "SelectMultiTerminalOnCall failed"));
  5117. }
  5118. //
  5119. // Clean-up
  5120. //
  5121. if( pMultiTrack )
  5122. {
  5123. pMultiTrack->Release();
  5124. }
  5125. LOG((TL_TRACE, "SelectTerminalOnCall - exit 0x%08x", hr ));
  5126. return hr;
  5127. }
  5128. STDMETHODIMP CCall::UnselectTerminalOnCall(
  5129. IN ITTerminal *pTerminal
  5130. )
  5131. {
  5132. LOG((TL_TRACE, "UnselectTerminalOnCall - enter" ));
  5133. //
  5134. // Validates argument
  5135. //
  5136. if( IsBadReadPtr( pTerminal, sizeof(ITTerminal)) )
  5137. {
  5138. LOG((TL_ERROR, "UnselectTerminalOnCall - exit "
  5139. " pTerminal invalid, returns E_POINTER"));
  5140. return E_POINTER;
  5141. }
  5142. //
  5143. // Just a HRESULT
  5144. //
  5145. HRESULT hr = E_FAIL;
  5146. //
  5147. // Is a single or multi track terminal
  5148. //
  5149. ITMultiTrackTerminal* pMultiTrack = NULL;
  5150. hr = pTerminal->QueryInterface(
  5151. IID_ITMultiTrackTerminal,
  5152. (void**)&pMultiTrack);
  5153. if( FAILED(hr) )
  5154. {
  5155. //
  5156. // SingleTrack terminal
  5157. //
  5158. LOG((TL_INFO, "UnselectTerminalOnCall - SingleTrack terminal" ));
  5159. hr = UnSelectSingleTerminalFromCall(
  5160. pTerminal);
  5161. LOG((TL_INFO, "UnselectTerminalOnCall - "
  5162. "UnSelectSingleTerminalFromCall exit 0x%08x", hr));
  5163. }
  5164. else
  5165. {
  5166. //
  5167. // Multitrack terminal
  5168. //
  5169. LOG((TL_INFO, "UnselectTerminalOnCall - MultiTrack terminal" ));
  5170. hr = UnSelectMultiTerminalFromCall(
  5171. pMultiTrack);
  5172. LOG((TL_INFO, "UnselectTerminalOnCall - "
  5173. "UnSelectMultiTerminalOnCall exit 0x%08x", hr));
  5174. }
  5175. //
  5176. // Clean-up
  5177. //
  5178. if( pMultiTrack )
  5179. {
  5180. pMultiTrack->Release();
  5181. }
  5182. LOG((TL_TRACE, "UnselectTerminalOnCall - exit 0x%08x", hr));
  5183. return hr;
  5184. }
  5185. /*++
  5186. SelectSingleTerminalOnCall
  5187. Select pTerminal on a right stream
  5188. pMediaType - if *pMediatype is 0 the we have just to return the media type
  5189. pDirection - if pDirection is TD_NONE we have just to return the direction
  5190. --*/
  5191. HRESULT CCall::SelectSingleTerminalOnCall(
  5192. IN ITTerminal* pTerminal,
  5193. OUT long* pMediaType,
  5194. OUT TERMINAL_DIRECTION* pDirection)
  5195. {
  5196. LOG((TL_TRACE, "SelectSingleTerminalOnCall - Enter" ));
  5197. //
  5198. // Validate terminal pointer
  5199. //
  5200. if( IsBadReadPtr( pTerminal, sizeof(ITTerminal)))
  5201. {
  5202. LOG((TL_ERROR, "SelectSingleTerminalOnCall - exit "
  5203. "pTerminal invalid, returns E_POINTER"));
  5204. return E_POINTER;
  5205. }
  5206. //
  5207. // Is terminal in use?
  5208. //
  5209. HRESULT hr = E_FAIL;
  5210. TERMINAL_STATE state = TS_INUSE;
  5211. pTerminal->get_State( &state );
  5212. if( TS_INUSE == state )
  5213. {
  5214. LOG((TL_ERROR, "SelectSingleTerminalOnCall - exit "
  5215. "terminal IN USE, returns E_UNEXPECTED"));
  5216. return E_UNEXPECTED;
  5217. }
  5218. //
  5219. // Get ITStreamControl interface
  5220. //
  5221. ITStreamControl* pStreamControl = NULL;
  5222. pStreamControl = GetStreamControl();
  5223. if( NULL == pStreamControl )
  5224. {
  5225. LOG((TL_ERROR, "SelectSingleTerminalOnCall - exit "
  5226. " GetStreamControl failed, returns E_UNEXPECTED"));
  5227. return E_UNEXPECTED;
  5228. }
  5229. //
  5230. // Get streams
  5231. //
  5232. IEnumStream * pEnumStreams = NULL;
  5233. hr = pStreamControl->EnumerateStreams(&pEnumStreams);
  5234. //
  5235. // Clean up
  5236. //
  5237. pStreamControl->Release();
  5238. if( FAILED(hr) )
  5239. {
  5240. LOG((TL_ERROR, "SelectSingleTerminalOnCall - exit "
  5241. " EnumerateStreams failed, returns 0x%08x", hr));
  5242. return hr;
  5243. }
  5244. //
  5245. // Find the right stream
  5246. //
  5247. ITStream * pStream = NULL;
  5248. hr = E_FAIL;
  5249. while ( S_OK == pEnumStreams->Next(1, &pStream, NULL) )
  5250. {
  5251. //
  5252. // Find out the media type and direction of this stream,
  5253. // and compare with pTerminal.
  5254. //
  5255. hr = IsRightStream(
  5256. pStream,
  5257. pTerminal,
  5258. pMediaType,
  5259. pDirection
  5260. );
  5261. if( SUCCEEDED(hr) )
  5262. {
  5263. hr = pStream->SelectTerminal( pTerminal );
  5264. if( FAILED(hr) )
  5265. {
  5266. LOG((TL_TRACE, "SelectSingleTerminalOnCall - "
  5267. "pStream->SelectTerminal failed. 0x%08x",hr));
  5268. // Clean-up
  5269. pStream->Release();
  5270. break;
  5271. }
  5272. else
  5273. {
  5274. // Clean-up
  5275. pStream->Release();
  5276. break;
  5277. }
  5278. }
  5279. //
  5280. // Clean-up
  5281. //
  5282. pStream->Release();
  5283. }
  5284. //
  5285. // Clean-up
  5286. //
  5287. pEnumStreams->Release();
  5288. LOG((TL_TRACE, "SelectSingleTerminalOnCall - exit 0x%08x", hr));
  5289. return hr;
  5290. }
  5291. /*++
  5292. SelectMultiTerminalOnCall
  5293. It's a complict algorithm to describe it here
  5294. See specs
  5295. --*/
  5296. HRESULT CCall::SelectMultiTerminalOnCall(
  5297. IN ITMultiTrackTerminal* pMultiTerminal)
  5298. {
  5299. LOG((TL_TRACE, "SelectMultiTerminalOnCall - enter" ));
  5300. //
  5301. // Get tracks
  5302. //
  5303. HRESULT hr = E_FAIL;
  5304. IEnumTerminal* pEnumTerminals = NULL;
  5305. hr = pMultiTerminal->EnumerateTrackTerminals(&pEnumTerminals);
  5306. if( FAILED(hr) )
  5307. {
  5308. LOG((TL_ERROR, "SelectMultiTerminalOnCall - exit "
  5309. "EnumerateTrackTerminals failed, returns 0x%08x", hr));
  5310. return hr;
  5311. }
  5312. ITTerminal* pTerm = NULL;
  5313. hr = pMultiTerminal->QueryInterface(
  5314. IID_ITTerminal,
  5315. (void**)&pTerm);
  5316. if( FAILED(hr) )
  5317. {
  5318. //Clean-up
  5319. pEnumTerminals->Release();
  5320. LOG((TL_ERROR, "SelectMultiTerminalOnCall - exit "
  5321. "QI for Terminal failed, returns 0x%08x", hr));
  5322. return hr;
  5323. }
  5324. long nTermMediaTypes = 0;
  5325. hr = pTerm->get_MediaType( &nTermMediaTypes );
  5326. if( FAILED(hr) )
  5327. {
  5328. //Clean-up
  5329. pEnumTerminals->Release();
  5330. pTerm->Release();
  5331. LOG((TL_ERROR, "SelectMultiTerminalOnCall - exit "
  5332. "get_MediaType failed, returns 0x%08x", hr));
  5333. return hr;
  5334. }
  5335. pTerm->Release();
  5336. //
  5337. // Inner struct
  5338. //
  5339. typedef struct tagSTREAMINFO
  5340. {
  5341. TERMINAL_DIRECTION Direction;
  5342. long lMediaType;
  5343. BOOL bSelected;
  5344. } STREAMINFO;
  5345. //
  5346. // Find tracks unused and select them
  5347. // on the right stream
  5348. ITTerminal * pTerminal = NULL;
  5349. STREAMINFO StreamsInfo[4] = {
  5350. {TD_RENDER, TAPIMEDIATYPE_AUDIO, FALSE},
  5351. {TD_RENDER, TAPIMEDIATYPE_VIDEO, FALSE},
  5352. {TD_CAPTURE, TAPIMEDIATYPE_AUDIO, FALSE},
  5353. {TD_CAPTURE, TAPIMEDIATYPE_VIDEO, FALSE}
  5354. };
  5355. //
  5356. // +++ FIXBUG 92559 +++
  5357. //
  5358. BOOL bSelectAtLeastOne = FALSE;
  5359. LOG((TL_INFO, "SelectMultiTerminalOnCall - FIRST LOOP ENTER"));
  5360. while ( S_OK == pEnumTerminals->Next(1, &pTerminal, NULL) )
  5361. {
  5362. //
  5363. // Select track on the right stream
  5364. //
  5365. long lMediaType = 0;
  5366. TERMINAL_DIRECTION Direction = TD_NONE;
  5367. HRESULT hr = E_FAIL;
  5368. LOG((TL_INFO, "SelectMultiTerminalOnCall - FIRST LOOP IN"));
  5369. hr = SelectSingleTerminalOnCall(
  5370. pTerminal,
  5371. &lMediaType,
  5372. &Direction);
  5373. if( SUCCEEDED(hr) )
  5374. {
  5375. LOG((TL_TRACE, "SelectMultiTerminalOnCall - "
  5376. "select terminal on stream (%ld, %ld)", lMediaType, Direction));
  5377. int nIndex = GetStreamIndex(
  5378. lMediaType,
  5379. Direction);
  5380. if( nIndex != STREAM_NONE )
  5381. {
  5382. StreamsInfo[nIndex].bSelected = TRUE;
  5383. }
  5384. bSelectAtLeastOne = TRUE;
  5385. }
  5386. // Clean-up
  5387. pTerminal->Release();
  5388. }
  5389. LOG((TL_INFO, "SelectMultiTerminalOnCall - FIRST LOOP EXIT"));
  5390. //
  5391. // Clean-up
  5392. //
  5393. pEnumTerminals->Release();
  5394. BOOL bCreateAtLeastOne = FALSE;
  5395. //
  5396. // Let's create a terminal for unselected streams
  5397. //
  5398. LOG((TL_INFO, "SelectMultiTerminalOnCall - SECOND LOOP ENTER"));
  5399. for(int nStream = STREAM_RENDERAUDIO; nStream < STREAM_NONE; nStream++)
  5400. {
  5401. LOG((TL_INFO, "SelectMultiTerminalOnCall - SECOND LOOP IN"));
  5402. if( StreamsInfo[ nStream ].bSelected)
  5403. {
  5404. continue;
  5405. }
  5406. if( (StreamsInfo[ nStream ].lMediaType & nTermMediaTypes)==0 )
  5407. {
  5408. continue;
  5409. }
  5410. //
  5411. // Unselected stream
  5412. //
  5413. LOG((TL_INFO, "SelectMultiTerminalOnCall - SECOND LOOP REALYIN"));
  5414. HRESULT hr = E_FAIL;
  5415. ITTerminal* pTerminal = NULL;
  5416. hr = pMultiTerminal->CreateTrackTerminal(
  5417. StreamsInfo[ nStream ].lMediaType,
  5418. StreamsInfo[ nStream ].Direction,
  5419. &pTerminal);
  5420. if( FAILED(hr) )
  5421. {
  5422. LOG((TL_ERROR, "SelectMultiTerminalOnCall - "
  5423. "create terminal on stream (%ld, %ld) failed",
  5424. StreamsInfo[ nStream ].lMediaType,
  5425. StreamsInfo[ nStream ].Direction));
  5426. }
  5427. else
  5428. {
  5429. long lMediaType = StreamsInfo[ nStream ].lMediaType;
  5430. TERMINAL_DIRECTION Direction = StreamsInfo[ nStream ].Direction;
  5431. hr = SelectSingleTerminalOnCall(
  5432. pTerminal,
  5433. &lMediaType,
  5434. &Direction);
  5435. if( FAILED(hr) )
  5436. {
  5437. LOG((TL_INFO, "SelectMultiTerminalOnCall - "
  5438. "select terminal on stream (%ld, %ld) failed",
  5439. StreamsInfo[ nStream ].lMediaType,
  5440. StreamsInfo[ nStream ].Direction));
  5441. pMultiTerminal->RemoveTrackTerminal( pTerminal );
  5442. }
  5443. else
  5444. {
  5445. LOG((TL_ERROR, "SelectMultiTerminalOnCall - SelectSingleTerminal SUCCEEDED"));
  5446. bCreateAtLeastOne = TRUE;
  5447. }
  5448. // Clean-up
  5449. pTerminal->Release();
  5450. }
  5451. }
  5452. LOG((TL_INFO, "SelectMultiTerminalOnCall - SECOND LOOP EXIT"));
  5453. if( bSelectAtLeastOne )
  5454. {
  5455. LOG((TL_INFO, "SelectMultiTerminalOnCall - "
  5456. "Select at least one existing track terminal"));
  5457. hr = S_OK;
  5458. }
  5459. else
  5460. {
  5461. if( bCreateAtLeastOne )
  5462. {
  5463. LOG((TL_ERROR, "SelectMultiTerminalOnCall - "
  5464. "Create and select at least one track terminal"));
  5465. hr = S_OK;
  5466. }
  5467. else
  5468. {
  5469. LOG((TL_ERROR, "SelectMultiTerminalOnCall - "
  5470. "Create and/or select no track terminal"));
  5471. hr = E_FAIL;
  5472. }
  5473. }
  5474. LOG((TL_TRACE, "SelectMultiTerminalOnCall - exit 0X%08X", hr ));
  5475. return hr;
  5476. }
  5477. HRESULT CCall::IsRightStream(
  5478. IN ITStream* pStream,
  5479. IN ITTerminal* pTerminal,
  5480. OUT long* pMediaType/*= NULL*/,
  5481. OUT TERMINAL_DIRECTION* pDirection/*=NULL*/)
  5482. {
  5483. LOG((TL_TRACE, "IsRightStream - enter" ));
  5484. if( NULL == pStream )
  5485. {
  5486. LOG((TL_ERROR, "IsRightStream - exit "
  5487. "pStream failed, returns E_POINTER"));
  5488. return E_POINTER;
  5489. }
  5490. HRESULT hr = E_FAIL;
  5491. long lMediaStream, lMediaTerminal;
  5492. TERMINAL_DIRECTION DirStream, DirTerminal;
  5493. //
  5494. // Determine the media type and direction of this stream.
  5495. //
  5496. hr = pStream->get_MediaType( &lMediaStream );
  5497. if ( FAILED(hr) )
  5498. {
  5499. LOG((TL_ERROR, "IsRightStream - exit "
  5500. "IStream::get_MediaType failed, returns 0x%08x", hr));
  5501. return hr;
  5502. }
  5503. hr = pStream->get_Direction( &DirStream );
  5504. if ( FAILED(hr) )
  5505. {
  5506. LOG((TL_ERROR, "IsRightStream - exit "
  5507. "IStream::get_Direction failed, returns 0x%08x", hr));
  5508. return hr;
  5509. }
  5510. //
  5511. // Determine the media type and direction of this terminal.
  5512. //
  5513. hr = pTerminal->get_MediaType( &lMediaTerminal );
  5514. if ( FAILED(hr) )
  5515. {
  5516. LOG((TL_ERROR, "IsRightStream - exit "
  5517. "ITTerminal::get_MediaType failed, returns 0x%08x", hr));
  5518. return hr;
  5519. }
  5520. hr = pTerminal->get_Direction( &DirTerminal );
  5521. if ( FAILED(hr) )
  5522. {
  5523. LOG((TL_ERROR, "IsRightStream - exit "
  5524. "ITTerminal::get_Direction failed, returns 0x%08x", hr));
  5525. return hr;
  5526. }
  5527. //
  5528. // Compare the media types supported
  5529. //
  5530. if ( (0 == (lMediaTerminal & lMediaStream)) /*||
  5531. (*pMediaType != 0 && *pMediaType != lMediaStream)*/ )
  5532. {
  5533. LOG((TL_ERROR, "IsRightStream - exit "
  5534. "media types unmatched, returns E_FAIL (S=0x%08x,T=0x%08x)",
  5535. lMediaStream, lMediaTerminal));
  5536. return E_FAIL;
  5537. }
  5538. //
  5539. // Compare directions
  5540. //
  5541. if( ( DirTerminal != DirStream) /*||
  5542. ( *pDirection != TD_NONE && *pDirection != DirStream)*/)
  5543. {
  5544. LOG((TL_ERROR, "IsRightStream - exit "
  5545. "directions unmatched, returns E_FAIL (S=0x%08x,T=0x%08x)",
  5546. DirStream,DirTerminal));
  5547. return E_FAIL;
  5548. }
  5549. //
  5550. // The wants to know the media type & direction?
  5551. //
  5552. *pMediaType = lMediaStream;
  5553. *pDirection = DirStream;
  5554. LOG((TL_TRACE, "IsRightStream - exit, matched (M=0x%08x, D=0x%08x)",
  5555. *pMediaType, *pDirection));
  5556. return S_OK;
  5557. }
  5558. /*++
  5559. GetStreamIndex
  5560. --*/
  5561. int CCall::GetStreamIndex(
  5562. IN long lMediaType,
  5563. IN TERMINAL_DIRECTION Direction)
  5564. {
  5565. int nIndex = STREAM_NONE;
  5566. LOG((TL_TRACE, "GetStreamIndex - enter (%ld, %ld)", lMediaType, Direction));
  5567. if(Direction == TD_RENDER )
  5568. {
  5569. if( lMediaType == TAPIMEDIATYPE_AUDIO )
  5570. {
  5571. nIndex = STREAM_RENDERAUDIO;
  5572. }
  5573. else
  5574. {
  5575. nIndex = STREAM_RENDERVIDEO;
  5576. }
  5577. }
  5578. else
  5579. {
  5580. if( lMediaType == TAPIMEDIATYPE_AUDIO )
  5581. {
  5582. nIndex = STREAM_CAPTUREAUDIO;
  5583. }
  5584. else
  5585. {
  5586. nIndex = STREAM_CAPTUREVIDEO;
  5587. }
  5588. }
  5589. LOG((TL_TRACE, "GetStreamIndex - exit %d", nIndex));
  5590. return nIndex;
  5591. }
  5592. /*++
  5593. UnSelectSingleTerminalFromCall
  5594. --*/
  5595. HRESULT CCall::UnSelectSingleTerminalFromCall(
  5596. IN ITTerminal* pTerminal)
  5597. {
  5598. LOG((TL_TRACE, "UnSelectSingleTerminalFromCall - enter" ));
  5599. //
  5600. // Get ITStreamControl interface
  5601. //
  5602. ITStreamControl* pStreamControl = NULL;
  5603. pStreamControl = GetStreamControl();
  5604. if( NULL == pStreamControl )
  5605. {
  5606. LOG((TL_ERROR, "UnSelectSingleTerminalFromCall - exit "
  5607. " GetStreamControl failed, returns E_UNEXPECTED"));
  5608. return E_UNEXPECTED;
  5609. }
  5610. //
  5611. // Get streams
  5612. //
  5613. IEnumStream * pEnumStreams = NULL;
  5614. HRESULT hr = E_FAIL;
  5615. hr = pStreamControl->EnumerateStreams(&pEnumStreams);
  5616. //
  5617. // Clean up
  5618. //
  5619. pStreamControl->Release();
  5620. if( FAILED(hr) )
  5621. {
  5622. LOG((TL_ERROR, "UnSelectSingleTerminalFromCall - exit "
  5623. "EnumerateStreams failed, returns 0x%08x", hr));
  5624. return hr;
  5625. }
  5626. //
  5627. // Find the right stream
  5628. //
  5629. ITStream * pStream = NULL;
  5630. hr = TAPI_E_INVALIDTERMINAL;
  5631. while ( S_OK == pEnumStreams->Next(1, &pStream, NULL) )
  5632. {
  5633. //
  5634. // Unselect terminal
  5635. //
  5636. hr = pStream->UnselectTerminal(
  5637. pTerminal);
  5638. //
  5639. // Clean-up
  5640. //
  5641. pStream->Release();
  5642. LOG((TL_INFO, "UnSelectSingleTerminalFromCall - "
  5643. "pStream->UnselectTerminal returns 0x%08x", hr));
  5644. if( hr == S_OK)
  5645. break;
  5646. }
  5647. //
  5648. // Clean-up
  5649. //
  5650. pEnumStreams->Release();
  5651. LOG((TL_TRACE, "UnSelectSingleTerminalFromCall - exit 0x%08x", hr));
  5652. return hr;
  5653. }
  5654. /*++
  5655. UnSelectMultiTerminalFromCall
  5656. --*/
  5657. HRESULT CCall::UnSelectMultiTerminalFromCall(
  5658. IN ITMultiTrackTerminal* pMultiTerminal)
  5659. {
  5660. LOG((TL_TRACE, "UnSelectMultiTerminalFromCall - enter" ));
  5661. //
  5662. // Get tracks
  5663. //
  5664. HRESULT hr = E_FAIL;
  5665. IEnumTerminal* pEnumTerminals = NULL;
  5666. hr = pMultiTerminal->EnumerateTrackTerminals(&pEnumTerminals);
  5667. if( FAILED(hr) )
  5668. {
  5669. LOG((TL_ERROR, "UnSelectMultiTerminalFromCall - exit "
  5670. "EnumerateTrackTerminals failed, returns 0x%08x", hr));
  5671. return hr;
  5672. }
  5673. //
  5674. // Find tracks and unselect them
  5675. //
  5676. ITTerminal * pTerminal = NULL;
  5677. HRESULT hrUnselect = S_OK; // The return HR
  5678. BOOL bOnStream = FALSE; // If we have a track on stream
  5679. while ( S_OK == pEnumTerminals->Next(1, &pTerminal, NULL) )
  5680. {
  5681. LOG((TL_INFO, "UnSelectMultiTerminalFromCall - NextTerminalBegin "));
  5682. //
  5683. // Try to find out if the terminal
  5684. // was selected on a stream
  5685. //
  5686. BOOL bSelected = FALSE;
  5687. HRESULT hr = IsTerminalSelected(
  5688. pTerminal,
  5689. &bSelected
  5690. );
  5691. if( FAILED(hr) )
  5692. {
  5693. hrUnselect = hr;
  5694. pTerminal->Release();
  5695. LOG((TL_INFO, "UnSelectMultiTerminalFromCall - "
  5696. "IsTerminalSelected failed all method will failed hrUnselect=0x%08x",
  5697. hrUnselect));
  5698. continue;
  5699. }
  5700. //
  5701. // The terminal wasn't selected?
  5702. //
  5703. if( !bSelected )
  5704. {
  5705. //
  5706. // The terminal wasn't selected
  5707. // goto the next terminal
  5708. //
  5709. LOG((TL_INFO, "UnSelectMultiTerminalFromCall - "
  5710. "the terminal wasn't selected on a stream, "
  5711. "goto the next terminal hrUnselect=0x%08x",
  5712. hrUnselect));
  5713. pTerminal->Release();
  5714. continue;
  5715. }
  5716. //
  5717. // We have an terminal on stream
  5718. //
  5719. bOnStream = TRUE;
  5720. //
  5721. // The terminal was selected on stream
  5722. // try to unselect terminal
  5723. //
  5724. hr = UnSelectSingleTerminalFromCall(
  5725. pTerminal
  5726. );
  5727. //
  5728. // Unselection failed?
  5729. //
  5730. if( FAILED(hr) )
  5731. {
  5732. //
  5733. // Event this unselection failed
  5734. // try to unselect the other terminals
  5735. // so go to the next terminal
  5736. //
  5737. hrUnselect = hr;
  5738. LOG((TL_INFO, "UnSelectMultiTerminalFromCall - "
  5739. "the terminal wasn't unselected from the stream, "
  5740. "goto the next terminal hrUnselect=0x%08x",
  5741. hrUnselect));
  5742. pTerminal->Release();
  5743. continue;
  5744. }
  5745. //
  5746. // Unselection succeded
  5747. // Leave the hrUnselected as it was before
  5748. // we start the loop with hrUnselect=S_OK
  5749. // if a previous terminal failed
  5750. // we already have setted on FAIL the hrUnselect
  5751. // Goto the next terminal
  5752. //
  5753. pTerminal->Release();
  5754. LOG((TL_INFO, "UnSelectMultiTerminalFromCall - NextTerminalEnd hrUnselect=0x%08x", hrUnselect));
  5755. }
  5756. //
  5757. // Clean-up
  5758. //
  5759. pEnumTerminals->Release();
  5760. //
  5761. // If we don't have track on streams
  5762. // this is realy bad
  5763. //
  5764. if( !bOnStream )
  5765. {
  5766. hrUnselect = E_FAIL;
  5767. }
  5768. hr = hrUnselect;
  5769. LOG((TL_TRACE, "UnSelectMultiTerminalFromCall - exit 0x%08x", hr));
  5770. return hr;
  5771. }
  5772. /*++
  5773. IsStaticGUID
  5774. Is caleled by RequestTerminal
  5775. Determines if the GUID represents a static terminal
  5776. or a dynamic one
  5777. --*/
  5778. BOOL CCall::IsStaticGUID(
  5779. BSTR bstrTerminalGUID)
  5780. {
  5781. LOG((TL_TRACE, "IsStaticGUID - enter" ));
  5782. BOOL bStatic = FALSE;
  5783. //
  5784. // Get the CLSID from bstrTerminalGUID
  5785. //
  5786. CLSID clsidTerminal;
  5787. HRESULT hr = E_FAIL;
  5788. hr = CLSIDFromString( bstrTerminalGUID, &clsidTerminal );
  5789. if( FAILED(hr) )
  5790. {
  5791. LOG((TL_ERROR, "IsStaticGUID - exit "
  5792. "CLSIDFromString failed, returns FALSE"));
  5793. return FALSE;
  5794. }
  5795. //
  5796. // Is clsidTerminal a 'static terminal' CLSID?
  5797. //
  5798. if( (clsidTerminal == CLSID_NULL) ||
  5799. (clsidTerminal == CLSID_MicrophoneTerminal) ||
  5800. (clsidTerminal == CLSID_SpeakersTerminal) ||
  5801. (clsidTerminal == CLSID_VideoInputTerminal))
  5802. {
  5803. bStatic = TRUE;
  5804. }
  5805. LOG((TL_TRACE, "IsStaticGUID - exit (%d)", bStatic));
  5806. return bStatic;
  5807. }
  5808. /*++
  5809. CreateStaticTerminal
  5810. Called by RequestTerminal
  5811. --*/
  5812. HRESULT CCall::CreateStaticTerminal(
  5813. IN BSTR bstrTerminalClassGUID,
  5814. IN TERMINAL_DIRECTION Direction,
  5815. IN long lMediaType,
  5816. OUT ITTerminal** ppTerminal
  5817. )
  5818. {
  5819. LOG((TL_TRACE, "CreateStaticTerminal - enter"));
  5820. //
  5821. // Helper method, the argument should be valid
  5822. //
  5823. _ASSERTE( bstrTerminalClassGUID );
  5824. _ASSERTE( *pTerminal );
  5825. //
  5826. // Get ITTerminalSupport interface
  5827. //
  5828. HRESULT hr = E_FAIL;
  5829. ITTerminalSupport* pSupport = NULL;
  5830. hr = m_pAddress->QueryInterface(
  5831. IID_ITTerminalSupport,
  5832. (void**)&pSupport);
  5833. if( FAILED(hr) )
  5834. {
  5835. LOG((TL_ERROR, "CreateStaticTerminal - exit"
  5836. "QueryInterface for ITTerminalSupport failed, returns 0x%08x", hr));
  5837. return hr;
  5838. }
  5839. //
  5840. // Get terminal CLSID from BSTR
  5841. //
  5842. CLSID clsidTerminal = CLSID_NULL;
  5843. hr = CLSIDFromString( bstrTerminalClassGUID, &clsidTerminal );
  5844. if( FAILED(hr) )
  5845. {
  5846. // Cleanup
  5847. pSupport->Release();
  5848. LOG((TL_ERROR, "CreateStaticTerminal - exit"
  5849. "CLSIDFromString failed, returns 0x%08x", hr));
  5850. return hr;
  5851. }
  5852. //
  5853. // Is CLSID matching with lMediaType and Direction?
  5854. //
  5855. if( clsidTerminal != CLSID_NULL )
  5856. {
  5857. if( clsidTerminal == CLSID_MicrophoneTerminal &&
  5858. ((lMediaType != TAPIMEDIATYPE_AUDIO) || (Direction != TD_CAPTURE)))
  5859. {
  5860. // Cleanup
  5861. pSupport->Release();
  5862. LOG((TL_ERROR, "CreateStaticTerminal - exit"
  5863. "CLSID_MicrophoneTerminal unmatched, returns E_UNEXPECTED"));
  5864. return E_UNEXPECTED;
  5865. }
  5866. if( clsidTerminal == CLSID_SpeakersTerminal &&
  5867. ((lMediaType != TAPIMEDIATYPE_AUDIO) || (Direction != TD_RENDER)))
  5868. {
  5869. // Cleanup
  5870. pSupport->Release();
  5871. LOG((TL_ERROR, "CreateStaticTerminal - exit"
  5872. "CLSID_SpeakersTerminal unmatched, returns E_UNEXPECTED"));
  5873. return E_UNEXPECTED;
  5874. }
  5875. if( clsidTerminal == CLSID_VideoInputTerminal &&
  5876. ((lMediaType != TAPIMEDIATYPE_VIDEO) || (Direction != TD_CAPTURE)))
  5877. {
  5878. // Cleanup
  5879. pSupport->Release();
  5880. LOG((TL_ERROR, "CreateStaticTerminal - exit"
  5881. "CLSID_VideoInputTerminal unmatched, returns E_UNEXPECTED"));
  5882. return E_UNEXPECTED;
  5883. }
  5884. }
  5885. else
  5886. {
  5887. // Shouldn't be the Dynamic terminal media type and direction
  5888. if((lMediaType == TAPIMEDIATYPE_VIDEO) && (Direction == TD_RENDER))
  5889. {
  5890. // Cleanup
  5891. pSupport->Release();
  5892. LOG((TL_ERROR, "CreateStaticTerminal - exit"
  5893. "try to create a dynamic terminal, returns E_UNEXPECTED"));
  5894. return E_UNEXPECTED;
  5895. }
  5896. }
  5897. //
  5898. // Cool, let's create the terminal
  5899. //
  5900. LOG((TL_INFO, "CreateStaticTerminal -> "
  5901. "ITterminalSupport::GetDefaultStaticTerminal"));
  5902. hr = pSupport->GetDefaultStaticTerminal(
  5903. lMediaType,
  5904. Direction,
  5905. ppTerminal);
  5906. //
  5907. // Clean-up ITTerminalSupport interface
  5908. //
  5909. pSupport->Release();
  5910. LOG((TL_TRACE, "CreateStaticTerminal - exit 0x%08x", hr));
  5911. return hr;
  5912. }
  5913. /*++
  5914. CreateDynamicTerminal
  5915. Called by RequestTerminal
  5916. --*/
  5917. HRESULT CCall::CreateDynamicTerminal(
  5918. IN BSTR bstrTerminalClassGUID,
  5919. IN TERMINAL_DIRECTION Direction,
  5920. IN long lMediaType,
  5921. OUT ITTerminal** ppTerminal
  5922. )
  5923. {
  5924. LOG((TL_TRACE, "CreateDynamicTerminal - enter"));
  5925. //
  5926. // Helper method, the argument should be valid
  5927. //
  5928. _ASSERTE( bstrTerminalClassGUID );
  5929. _ASSERTE( *pTerminal );
  5930. //
  5931. // Get ITTerminalSupport interface
  5932. //
  5933. HRESULT hr = E_FAIL;
  5934. ITTerminalSupport* pSupport = NULL;
  5935. hr = m_pAddress->QueryInterface(
  5936. IID_ITTerminalSupport,
  5937. (void**)&pSupport);
  5938. if( FAILED(hr) )
  5939. {
  5940. LOG((TL_ERROR, "CreateDynamicTerminal - exit"
  5941. "QueryInterface for ITTerminalSupport failed, returns 0x%08x", hr));
  5942. return hr;
  5943. }
  5944. //
  5945. // Create dynamic terminal
  5946. //
  5947. LOG((TL_INFO, "CreateDynamicTerminal -> "
  5948. "ITTerminalSupport::CreateTerminal"));
  5949. hr = pSupport->CreateTerminal(
  5950. bstrTerminalClassGUID,
  5951. lMediaType,
  5952. Direction,
  5953. ppTerminal);
  5954. //
  5955. // Clean-up ITTerminalSupport interface
  5956. //
  5957. pSupport->Release();
  5958. LOG((TL_TRACE, "CreateDynamicTerminal - exit 0x%08x", hr));
  5959. return hr;
  5960. }
  5961. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  5962. // Class : CCall
  5963. // Interface : ITCallInfo2
  5964. // Method : put_FilterEvent
  5965. //
  5966. //
  5967. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  5968. HRESULT
  5969. CCall::put_EventFilter(
  5970. TAPI_EVENT TapiEvent,
  5971. long lSubEvent,
  5972. VARIANT_BOOL bEnable
  5973. )
  5974. {
  5975. LOG((TL_TRACE, "put_EventFilter - enter"));
  5976. // Enter critical section
  5977. Lock();
  5978. //
  5979. // Validates the pair TapiEvent - lSubEvent
  5980. // Accept 'allsubevents'
  5981. //
  5982. if( !m_EventMasks.IsSubEventValid( TapiEvent, lSubEvent, TRUE, TRUE) )
  5983. {
  5984. LOG((TL_ERROR, "put_EventFilter - "
  5985. "This event can't be set: %x, return E_INVALIDARG", TapiEvent ));
  5986. // Leave critical section
  5987. Unlock();
  5988. return E_INVALIDARG;
  5989. }
  5990. // Let's set the flag
  5991. HRESULT hr = E_FAIL;
  5992. hr = SetSubEventFlag(
  5993. TapiEvent,
  5994. lSubEvent,
  5995. (bEnable == VARIANT_TRUE)
  5996. );
  5997. // Leave critical section
  5998. Unlock();
  5999. LOG((TL_TRACE, "put_EventFilter - exit 0x%08x", hr));
  6000. return hr;
  6001. }
  6002. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6003. // Class : CCall
  6004. // Interface : ITCallInfo2
  6005. // Method : get_FilterEvent
  6006. //
  6007. //
  6008. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6009. HRESULT
  6010. CCall::get_EventFilter(
  6011. TAPI_EVENT TapiEvent,
  6012. long lSubEvent,
  6013. VARIANT_BOOL* pEnable
  6014. )
  6015. {
  6016. LOG((TL_TRACE, "get_EventFilter - enter"));
  6017. //
  6018. // Validates output argument
  6019. //
  6020. if( IsBadReadPtr(pEnable, sizeof(VARIANT_BOOL)) )
  6021. {
  6022. LOG((TL_ERROR, "get_EventFilter - "
  6023. "invalid VARIANT_BOOL pointer , return E_POINTER" ));
  6024. return E_POINTER;
  6025. }
  6026. // Enter critical section
  6027. Lock();
  6028. //
  6029. // Validates the pair TapiEvent - lSubEvent
  6030. // Don't accept 'allsubevents'
  6031. //
  6032. if( !m_EventMasks.IsSubEventValid( TapiEvent, lSubEvent, FALSE, TRUE) )
  6033. {
  6034. LOG((TL_ERROR, "get_EventFilter - "
  6035. "This event can't be set: %x, return E_INVALIDARG", TapiEvent ));
  6036. // Leave critical section
  6037. Unlock();
  6038. return E_INVALIDARG;
  6039. }
  6040. //
  6041. // Get the subevent mask for that (event, subevent) pair
  6042. //
  6043. BOOL bEnable = FALSE;
  6044. HRESULT hr = GetSubEventFlag(
  6045. TapiEvent,
  6046. (DWORD)lSubEvent,
  6047. &bEnable);
  6048. if( FAILED(hr) )
  6049. {
  6050. LOG((TL_ERROR, "get_EventFilter - "
  6051. "GetSubEventFlag failed, return 0x%08x", hr ));
  6052. // Leave critical section
  6053. Unlock();
  6054. return hr;
  6055. }
  6056. //
  6057. // Set the output argument
  6058. //
  6059. *pEnable = bEnable ? VARIANT_TRUE : VARIANT_FALSE;
  6060. // Leave critical section
  6061. Unlock();
  6062. LOG((TL_TRACE, "get_EventFilter - exit S_OK"));
  6063. return S_OK;
  6064. }
  6065. //
  6066. // SetSubEventFlag
  6067. // It is calle by CAddress::SetSubEventFlagToCalls()
  6068. // Sets the subevent flag
  6069. //
  6070. HRESULT CCall::SetSubEventFlag(
  6071. IN TAPI_EVENT TapiEvent,
  6072. IN DWORD dwSubEvent,
  6073. IN BOOL bEnable
  6074. )
  6075. {
  6076. LOG((TL_TRACE, "SetSubEventFlag - enter"));
  6077. //
  6078. // Set the flag for that (event,subevent) pair
  6079. //
  6080. HRESULT hr = E_FAIL;
  6081. hr = m_EventMasks.SetSubEventFlag(
  6082. TapiEvent,
  6083. dwSubEvent,
  6084. bEnable);
  6085. LOG((TL_TRACE, "SetSubEventFlag - exit 0x%08x", hr));
  6086. return hr;
  6087. }
  6088. /*++
  6089. GetSubEventFlag
  6090. It is called by get_EventFilter() method
  6091. --*/
  6092. HRESULT CCall::GetSubEventFlag(
  6093. TAPI_EVENT TapiEvent,
  6094. DWORD dwSubEvent,
  6095. BOOL* pEnable
  6096. )
  6097. {
  6098. LOG((TL_TRACE, "GetSubEventFlag enter" ));
  6099. HRESULT hr = E_FAIL;
  6100. //
  6101. // Get the subevent falg
  6102. //
  6103. hr = m_EventMasks.GetSubEventFlag(
  6104. TapiEvent,
  6105. dwSubEvent,
  6106. pEnable
  6107. );
  6108. LOG((TL_TRACE, "GetSubEventFlag exit 0x%08x", hr));
  6109. return hr;
  6110. }
  6111. /*++
  6112. GetSubEventsMask
  6113. --*/
  6114. DWORD CCall::GetSubEventsMask(
  6115. IN TAPI_EVENT TapiEvent
  6116. )
  6117. {
  6118. LOG((TL_TRACE, "GetSubEventsMask - enter"));
  6119. DWORD dwSubEventFlag = m_EventMasks.GetSubEventMask(
  6120. TapiEvent
  6121. );
  6122. LOG((TL_TRACE, "GetSubEventsMask - exit %ld", dwSubEventFlag));
  6123. return dwSubEventFlag;
  6124. }
  6125. HRESULT CCall::IsTerminalSelected(
  6126. IN ITTerminal* pTerminal,
  6127. OUT BOOL* pSelected
  6128. )
  6129. {
  6130. LOG((TL_TRACE, "IsTerminalSelected - enter"));
  6131. // Initialize
  6132. *pSelected = FALSE;
  6133. HRESULT hr = E_FAIL;
  6134. long nMTTerminal = TAPIMEDIATYPE_AUDIO;
  6135. TERMINAL_DIRECTION DirTerminal = TD_CAPTURE;
  6136. // Get media type
  6137. hr = pTerminal->get_MediaType(&nMTTerminal);
  6138. if( FAILED(hr) )
  6139. {
  6140. LOG((TL_ERROR, "IsTerminalSelected - get_MediaType failed. Exit 0x%08x, %d", hr, *pSelected));
  6141. return hr;
  6142. }
  6143. // Get direction
  6144. hr = pTerminal->get_Direction(&DirTerminal);
  6145. if( FAILED(hr) )
  6146. {
  6147. LOG((TL_ERROR, "IsTerminalSelected - get_Direction failed. Exit %0x%08x, %d", hr, *pSelected));
  6148. return hr;
  6149. }
  6150. LOG((TL_INFO, "IsTerminalSelected - MT=%d, Dir=%d",
  6151. nMTTerminal, DirTerminal));
  6152. // Get stream control
  6153. ITStreamControl* pStreamControl = NULL;
  6154. pStreamControl = GetStreamControl();
  6155. if( NULL == pStreamControl )
  6156. {
  6157. LOG((TL_ERROR, "IsTerminalSelected - exit "
  6158. " GetStreamControl failed, returns E_UNEXPECTED, %d", *pSelected));
  6159. return E_UNEXPECTED;
  6160. }
  6161. //Enumerate streams
  6162. IEnumStream* pStreams = NULL;
  6163. hr = pStreamControl->EnumerateStreams(&pStreams);
  6164. pStreamControl->Release();
  6165. if( FAILED(hr) )
  6166. {
  6167. LOG((TL_ERROR, "IsTerminalSelected - exit "
  6168. " EnumerateStreams failed, returns 0x%08x, %d",hr, *pSelected));
  6169. return hr;
  6170. }
  6171. // Parse the enumeration
  6172. ITStream* pStream = NULL;
  6173. ULONG ulFetched = 0;
  6174. while( S_OK == pStreams->Next(1, &pStream, &ulFetched))
  6175. {
  6176. // Get media type for the stream
  6177. long nMTStream = TAPIMEDIATYPE_AUDIO;
  6178. hr = pStream->get_MediaType(&nMTStream);
  6179. if( FAILED(hr))
  6180. {
  6181. LOG((TL_ERROR, "IsTerminalSelected - exit "
  6182. " get_MediaType failed, returns 0x%08x, %d",hr, *pSelected));
  6183. return hr;
  6184. }
  6185. // Get direction for stream
  6186. TERMINAL_DIRECTION DirStream = TD_CAPTURE;
  6187. hr = pStream->get_Direction(&DirStream);
  6188. if( FAILED(hr))
  6189. {
  6190. LOG((TL_ERROR, "IsTerminalSelected - exit "
  6191. " get_MediaType failed, returns 0x%08x, %d",hr, *pSelected));
  6192. pStream->Release();
  6193. pStreams->Release();
  6194. return hr;
  6195. }
  6196. // The stream is matching with the terminal?
  6197. if( (nMTTerminal!=nMTStream) || (DirTerminal!=DirStream) )
  6198. {
  6199. pStream->Release();
  6200. continue; //Go to the next stream
  6201. }
  6202. // We are on the right stream
  6203. // enumerate the terminals
  6204. IEnumTerminal* pTerminals = NULL;
  6205. hr = pStream->EnumerateTerminals( &pTerminals);
  6206. if( FAILED(hr))
  6207. {
  6208. LOG((TL_ERROR, "IsTerminalSelected - exit "
  6209. " EnumerateTerminals failed, returns 0x%08x, %d",hr, *pSelected));
  6210. pStream->Release();
  6211. pStreams->Release();
  6212. return hr;
  6213. }
  6214. // Clean-up
  6215. pStream->Release();
  6216. // Parse the terminals
  6217. ITTerminal* pTerminalStream = NULL;
  6218. ULONG ulTerminal = 0;
  6219. while(S_OK==pTerminals->Next(1, &pTerminalStream, &ulTerminal))
  6220. {
  6221. if( pTerminal == pTerminalStream)
  6222. {
  6223. *pSelected = TRUE;
  6224. pTerminalStream->Release();
  6225. break;
  6226. }
  6227. pTerminalStream->Release();
  6228. }
  6229. // Clean-up
  6230. pTerminals->Release();
  6231. break;
  6232. }
  6233. // Clean-up streams
  6234. pStreams->Release();
  6235. LOG((TL_TRACE, "IsTerminalSelected - exit S_OK Selected=%d", *pSelected));
  6236. return S_OK;
  6237. }
  6238. /*++
  6239. Method:
  6240. GetConfControlCall
  6241. Parameters:
  6242. None.
  6243. Return Value:
  6244. Conference controller call object associated with this call.
  6245. Remarks:
  6246. None.
  6247. --*/
  6248. CCall*
  6249. CCall::GetConfControlCall(void)
  6250. {
  6251. CCall* pConfContCall = NULL;
  6252. Lock();
  6253. //
  6254. // NikhilB: Call object has a reference to Callhub object so its safe to
  6255. // lock the callhub object before locking the call. This is to avoid a
  6256. // deadlock that happens dur to locking the call and the callhub in reverse
  6257. // orders in different functions.
  6258. //
  6259. if( m_pCallHub != NULL )
  6260. {
  6261. m_pCallHub->AddRef();
  6262. AddRef();
  6263. Unlock();
  6264. // lock the callhub object before locking the call
  6265. m_pCallHub->Lock();
  6266. Lock();
  6267. Release();
  6268. m_pCallHub->Release();
  6269. pConfContCall = m_pCallHub ->GetConferenceControllerCall();
  6270. m_pCallHub->Unlock();
  6271. }
  6272. Unlock();
  6273. return pConfContCall;
  6274. }
  6275. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6276. // Class : CDetectTone
  6277. // Interface : ITDetectTone
  6278. // Method : put_AppSpecific
  6279. //
  6280. //
  6281. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6282. HRESULT CDetectTone::put_AppSpecific( long lAppSpecific )
  6283. {
  6284. LOG((TL_TRACE, "put_AppSpecific - enter"));
  6285. Lock();
  6286. m_lAppSpecific = lAppSpecific;
  6287. Unlock();
  6288. LOG((TL_TRACE, "put_AppSpecific - exit - S_OK"));
  6289. return S_OK;
  6290. }
  6291. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6292. // Class : CDetectTone
  6293. // Interface : ITDetectTone
  6294. // Method : get_AppSpecific
  6295. //
  6296. //
  6297. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6298. HRESULT CDetectTone::get_AppSpecific( long * plAppSpecific )
  6299. {
  6300. LOG((TL_TRACE, "get_AppSpecific - enter"));
  6301. if ( TAPIIsBadWritePtr( plAppSpecific, sizeof(long) ) )
  6302. {
  6303. LOG((TL_ERROR, "get_AppSpecific - bad pointer"));
  6304. return E_POINTER;
  6305. }
  6306. Lock();
  6307. *plAppSpecific = m_lAppSpecific;
  6308. Unlock();
  6309. LOG((TL_TRACE, "get_AppSpecific - exit - S_OK"));
  6310. return S_OK;
  6311. }
  6312. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6313. // Class : CDetectTone
  6314. // Interface : ITDetectTone
  6315. // Method : put_Duration
  6316. //
  6317. //
  6318. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6319. HRESULT CDetectTone::put_Duration( long lDuration )
  6320. {
  6321. LOG((TL_TRACE, "put_Duration - enter"));
  6322. Lock();
  6323. m_lDuration = lDuration;
  6324. Unlock();
  6325. LOG((TL_TRACE, "put_Duration - exit - S_OK"));
  6326. return S_OK;
  6327. }
  6328. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6329. // Class : CDetectTone
  6330. // Interface : ITDetectTone
  6331. // Method : get_Duration
  6332. //
  6333. //
  6334. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6335. HRESULT CDetectTone::get_Duration( long * plDuration )
  6336. {
  6337. LOG((TL_TRACE, "get_Duration - enter"));
  6338. if ( TAPIIsBadWritePtr( plDuration, sizeof(long) ) )
  6339. {
  6340. LOG((TL_ERROR, "get_Duration - bad pointer"));
  6341. return E_POINTER;
  6342. }
  6343. Lock();
  6344. *plDuration = m_lDuration;
  6345. Unlock();
  6346. LOG((TL_TRACE, "get_Duration - exit - S_OK"));
  6347. return S_OK;
  6348. }
  6349. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6350. // Class : CDetectTone
  6351. // Interface : ITDetectTone
  6352. // Method : put_Frequency
  6353. //
  6354. //
  6355. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6356. HRESULT CDetectTone::put_Frequency(
  6357. long Index,
  6358. long lFrequency
  6359. )
  6360. {
  6361. LOG((TL_TRACE, "put_Frequency - enter"));
  6362. if ( (Index < 1) || (Index > 3))
  6363. {
  6364. LOG((TL_ERROR, "put_Frequency - invalid index"));
  6365. return E_INVALIDARG;
  6366. }
  6367. Lock();
  6368. m_lFrequency[Index - 1] = lFrequency;
  6369. Unlock();
  6370. LOG((TL_TRACE, "put_Frequency - exit - S_OK"));
  6371. return S_OK;
  6372. }
  6373. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6374. // Class : CDetectTone
  6375. // Interface : ITDetectTone
  6376. // Method : get_Frequency
  6377. //
  6378. //
  6379. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6380. HRESULT CDetectTone::get_Frequency(
  6381. long Index,
  6382. long * plFrequency
  6383. )
  6384. {
  6385. LOG((TL_TRACE, "get_Frequency - enter"));
  6386. if ( TAPIIsBadWritePtr( plFrequency, sizeof(long) ) )
  6387. {
  6388. LOG((TL_ERROR, "get_Frequency - bad pointer"));
  6389. return E_POINTER;
  6390. }
  6391. if ( (Index < 1) || (Index > 3))
  6392. {
  6393. LOG((TL_ERROR, "get_Frequency - invalid index"));
  6394. return E_INVALIDARG;
  6395. }
  6396. Lock();
  6397. *plFrequency = m_lFrequency[Index - 1];
  6398. Unlock();
  6399. LOG((TL_TRACE, "get_Frequency - exit - S_OK"));
  6400. return S_OK;
  6401. }
  6402. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6403. // Class : CCustomTone
  6404. // Interface : ITCustomTone
  6405. // Method : put_Frequency
  6406. //
  6407. //
  6408. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6409. HRESULT CCustomTone::put_Frequency( long lFrequency )
  6410. {
  6411. LOG((TL_TRACE, "put_Frequency - enter"));
  6412. Lock();
  6413. m_lFrequency = lFrequency;
  6414. Unlock();
  6415. LOG((TL_TRACE, "put_Frequency - exit - S_OK"));
  6416. return S_OK;
  6417. }
  6418. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6419. // Class : CCustomTone
  6420. // Interface : ITCustomTone
  6421. // Method : get_Frequency
  6422. //
  6423. //
  6424. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6425. HRESULT CCustomTone::get_Frequency( long * plFrequency )
  6426. {
  6427. LOG((TL_TRACE, "get_Frequency - enter"));
  6428. if ( TAPIIsBadWritePtr( plFrequency, sizeof(long) ) )
  6429. {
  6430. LOG((TL_ERROR, "get_Frequency - bad pointer"));
  6431. return E_POINTER;
  6432. }
  6433. Lock();
  6434. *plFrequency = m_lFrequency;
  6435. Unlock();
  6436. LOG((TL_TRACE, "get_Frequency - exit - S_OK"));
  6437. return S_OK;
  6438. }
  6439. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6440. // Class : CCustomTone
  6441. // Interface : ITCustomTone
  6442. // Method : put_CadenceOn
  6443. //
  6444. //
  6445. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6446. HRESULT CCustomTone::put_CadenceOn( long lCadenceOn )
  6447. {
  6448. LOG((TL_TRACE, "put_CadenceOn - enter"));
  6449. Lock();
  6450. m_lCadenceOn = lCadenceOn;
  6451. Unlock();
  6452. LOG((TL_TRACE, "put_CadenceOn - exit - S_OK"));
  6453. return S_OK;
  6454. }
  6455. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6456. // Class : CCustomTone
  6457. // Interface : ITCustomTone
  6458. // Method : get_CadenceOn
  6459. //
  6460. //
  6461. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6462. HRESULT CCustomTone::get_CadenceOn( long * plCadenceOn )
  6463. {
  6464. LOG((TL_TRACE, "get_CadenceOn - enter"));
  6465. if ( TAPIIsBadWritePtr( plCadenceOn, sizeof(long) ) )
  6466. {
  6467. LOG((TL_ERROR, "get_CadenceOn - bad pointer"));
  6468. return E_POINTER;
  6469. }
  6470. Lock();
  6471. *plCadenceOn = m_lCadenceOn;
  6472. Unlock();
  6473. LOG((TL_TRACE, "get_CadenceOn - exit - S_OK"));
  6474. return S_OK;
  6475. }
  6476. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6477. // Class : CCustomTone
  6478. // Interface : ITCustomTone
  6479. // Method : put_CadenceOff
  6480. //
  6481. //
  6482. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6483. HRESULT CCustomTone::put_CadenceOff( long lCadenceOff )
  6484. {
  6485. LOG((TL_TRACE, "put_CadenceOff - enter"));
  6486. Lock();
  6487. m_lCadenceOff = lCadenceOff;
  6488. Unlock();
  6489. LOG((TL_TRACE, "put_CadenceOff - exit - S_OK"));
  6490. return S_OK;
  6491. }
  6492. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6493. // Class : CCustomTone
  6494. // Interface : ITCustomTone
  6495. // Method : get_CadenceOff
  6496. //
  6497. //
  6498. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6499. HRESULT CCustomTone::get_CadenceOff( long * plCadenceOff )
  6500. {
  6501. LOG((TL_TRACE, "get_CadenceOff - enter"));
  6502. if ( TAPIIsBadWritePtr( plCadenceOff, sizeof(long) ) )
  6503. {
  6504. LOG((TL_ERROR, "get_CadenceOff - bad pointer"));
  6505. return E_POINTER;
  6506. }
  6507. Lock();
  6508. *plCadenceOff = m_lCadenceOff;
  6509. Unlock();
  6510. LOG((TL_TRACE, "get_CadenceOff - exit - S_OK"));
  6511. return S_OK;
  6512. }
  6513. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6514. // Class : CCustomTone
  6515. // Interface : ITCustomTone
  6516. // Method : put_Volume
  6517. //
  6518. //
  6519. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6520. HRESULT CCustomTone::put_Volume( long lVolume )
  6521. {
  6522. LOG((TL_TRACE, "put_Volume - enter"));
  6523. Lock();
  6524. m_lVolume = lVolume;
  6525. Unlock();
  6526. LOG((TL_TRACE, "put_Volume - exit - S_OK"));
  6527. return S_OK;
  6528. }
  6529. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6530. // Class : CCustomTone
  6531. // Interface : ITCustomTone
  6532. // Method : get_CadenceOff
  6533. //
  6534. //
  6535. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6536. HRESULT CCustomTone::get_Volume( long * plVolume )
  6537. {
  6538. LOG((TL_TRACE, "get_Volume - enter"));
  6539. if ( TAPIIsBadWritePtr( plVolume, sizeof(long) ) )
  6540. {
  6541. LOG((TL_ERROR, "get_Volume - bad pointer"));
  6542. return E_POINTER;
  6543. }
  6544. Lock();
  6545. *plVolume = m_lVolume;
  6546. Unlock();
  6547. LOG((TL_TRACE, "get_Volume - exit - S_OK"));
  6548. return S_OK;
  6549. }