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.

4616 lines
104 KiB

  1. /*++
  2. Copyright (c) 1997 - 1999 Microsoft Corporation
  3. Module Name:
  4. tapiobj.cpp
  5. Abstract:
  6. Implementation of the TAPI object for TAPI 3.0.
  7. The TAPI object represents the application's entry point
  8. into TAPI - it is similar to the hLineApp / hPhoneApp.
  9. Author:
  10. mquinton - 4/17/97
  11. Notes:
  12. optional-notes
  13. Revision History:
  14. --*/
  15. #include "stdafx.h"
  16. #include "common.h"
  17. #include "atlwin.cpp"
  18. #include "tapievt.h"
  19. extern "C" {
  20. #include "..\..\inc\tapihndl.h"
  21. }
  22. extern CRITICAL_SECTION gcsTapiObjectArray;
  23. extern CRITICAL_SECTION gcsGlobalInterfaceTable;
  24. //
  25. // handle for heap for the handle table
  26. //
  27. // does not need to be exported, hence static
  28. //
  29. static HANDLE ghTapiHeap = 0;
  30. //
  31. // handle table handle
  32. //
  33. HANDLE ghHandleTable = 0;
  34. ///////////////////////////////////////////////////////////////////////////////
  35. //
  36. // FreeContextCallback
  37. //
  38. // callback function called by the handle table when a table entry
  39. // is removed. No need to do anything in this case.
  40. //
  41. VOID
  42. CALLBACK
  43. FreeContextCallback(
  44. LPVOID Context,
  45. LPVOID Context2
  46. )
  47. {
  48. }
  49. ///////////////////////////////////////////////////////////////////////////////
  50. //
  51. // AllocateAndInitializeHandleTable
  52. //
  53. // this function creates heap for handle table and the handle table itself
  54. //
  55. // Note: this function is not thread-safe. It is only called from
  56. // ctapi::Initialize() from ghTapiInitShutdownSerializeMutex lock
  57. //
  58. HRESULT AllocateAndInitializeHandleTable()
  59. {
  60. LOG((TL_TRACE, "AllocateAndInitializeHandleTable - entered"));
  61. //
  62. // heap should not exist at this point
  63. //
  64. _ASSERTE(NULL == ghTapiHeap);
  65. if (NULL != ghTapiHeap)
  66. {
  67. LOG((TL_ERROR, "AllocateAndInitializeHandleTable() heap already exists"));
  68. return E_UNEXPECTED;
  69. }
  70. //
  71. // handle table should not exist at this point
  72. //
  73. _ASSERTE(NULL == ghHandleTable);
  74. if (NULL != ghHandleTable)
  75. {
  76. LOG((TL_ERROR, "AllocateAndInitializeHandleTable() handle table already exists"));
  77. return E_UNEXPECTED;
  78. }
  79. //
  80. // attempt to create heap
  81. //
  82. if (!(ghTapiHeap = HeapCreate (0, 0x10000, 0)))
  83. {
  84. //
  85. // heap creation failed, use process's heap
  86. //
  87. LOG((TL_WARN, "AllocateAndInitializeHandleTable() failed to allocate private heap. using process's heap"));
  88. ghTapiHeap = GetProcessHeap();
  89. if (NULL == ghTapiHeap)
  90. {
  91. LOG((TL_ERROR, "AllocateAndInitializeHandleTable failed to get process's heap"));
  92. return E_OUTOFMEMORY;
  93. }
  94. } // HeapCreate()
  95. //
  96. // we have the heap. use it to create handle table
  97. //
  98. ghHandleTable = CreateHandleTable( ghTapiHeap,
  99. FreeContextCallback,
  100. 1, // min handle value
  101. MAX_DWORD // max handle value
  102. );
  103. if (NULL == ghHandleTable)
  104. {
  105. LOG((TL_ERROR, "AllocateAndInitializeHandleTable failed to create handle table"));
  106. HeapDestroy (ghTapiHeap);
  107. ghTapiHeap = NULL;
  108. return E_OUTOFMEMORY;
  109. }
  110. //
  111. // succeeded creating heap and handle table
  112. //
  113. LOG((TL_INFO, "AllocateAndInitializeHandleTable - succeeded"));
  114. return S_OK;
  115. }
  116. ///////////////////////////////////////////////////////////////////////////////
  117. //
  118. // ShutdownAndDeallocateHandleTable
  119. //
  120. // this function deletes handle table, and destroys heap on which it was
  121. // allocated (if not process heap)
  122. //
  123. // Note: this function is not thread-safe. It is only called from
  124. // ctapi::Initialize() and Shutdown() from ghTapiInitShutdownSerializeMutex lock
  125. //
  126. HRESULT ShutdownAndDeallocateHandleTable()
  127. {
  128. LOG((TL_TRACE, "ShutdownAndDeallocateHandleTable - entered"));
  129. //
  130. // heap should exist at this point
  131. //
  132. _ASSERTE(NULL != ghTapiHeap);
  133. if (NULL == ghTapiHeap)
  134. {
  135. LOG((TL_ERROR, "ShutdownAndDeallocateHandleTable heap does not exist"));
  136. return E_UNEXPECTED;
  137. }
  138. //
  139. // handle table should exist at this point
  140. //
  141. _ASSERTE(NULL != ghHandleTable);
  142. if (NULL == ghHandleTable)
  143. {
  144. LOG((TL_ERROR, "ShutdownAndDeallocateHandleTable handle table does not exist"));
  145. return E_UNEXPECTED;
  146. }
  147. //
  148. // delete handle table
  149. //
  150. DeleteHandleTable (ghHandleTable);
  151. ghHandleTable = NULL;
  152. //
  153. // if we created heap for it, destroy it
  154. //
  155. if (ghTapiHeap != GetProcessHeap())
  156. {
  157. LOG((TL_INFO, "ShutdownAndDeallocateHandleTable destroying heap"));
  158. HeapDestroy (ghTapiHeap);
  159. }
  160. else
  161. {
  162. LOG((TL_INFO, "ShutdownAndDeallocateHandleTable not destroyng current heap -- used process's heap"));
  163. }
  164. //
  165. // in any case, loose reference to the heap.
  166. //
  167. ghTapiHeap = NULL;
  168. LOG((TL_INFO, "ShutdownAndDeallocateHandleTable - succeeded"));
  169. return S_OK;
  170. }
  171. IGlobalInterfaceTable * gpGIT = NULL;
  172. LONG
  173. WINAPI
  174. AllocClientResources(
  175. DWORD dwErrorClass
  176. );
  177. extern HRESULT mapTAPIErrorCode(long lErrorCode);
  178. /////////////////////////////////////////////////////////////////////////////
  179. // CTAPI
  180. //
  181. // Static data members
  182. TAPIObjectArrayNR CTAPI::m_sTAPIObjectArray;
  183. extern HANDLE ghTapiInitShutdownSerializeMutex;
  184. extern ULONG_PTR GenerateHandleAndAddToHashTable( ULONG_PTR Element);
  185. extern void RemoveHandleFromHashTable(ULONG_PTR dwHandle);
  186. extern CHashTable * gpHandleHashTable;
  187. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  188. //
  189. // CTAPI::ReleaseGIT
  190. //
  191. // releases Global Interface Table
  192. //
  193. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  194. void CTAPI::ReleaseGIT()
  195. {
  196. EnterCriticalSection( &gcsGlobalInterfaceTable );
  197. if ( NULL != gpGIT )
  198. {
  199. LOG((TL_TRACE, "Shutdown - release GIT"));
  200. gpGIT->Release();
  201. gpGIT = NULL;
  202. }
  203. LeaveCriticalSection( &gcsGlobalInterfaceTable );
  204. }
  205. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  206. //
  207. // CTAPI::AllocateInitializeAllCaches
  208. //
  209. // allocates and initializes cache objects (address, line, phone).
  210. //
  211. // returns S_OK on success or E_OUTOFMEMORY on failure
  212. //
  213. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  214. HRESULT CTAPI::AllocateInitializeAllCaches()
  215. {
  216. LOG((TL_TRACE, "AllocateInitializeAllCaches - enter"));
  217. //
  218. // all caches already initialized?
  219. //
  220. if ( (NULL != m_pAddressCapCache) &&
  221. (NULL != m_pLineCapCache) &&
  222. (NULL != m_pPhoneCapCache) )
  223. {
  224. LOG((TL_TRACE, "AllocateInitializeAllCaches - already initialized. nothing to do"));
  225. return S_OK;
  226. }
  227. //
  228. // only some caches are initialized? that's a bug!
  229. //
  230. if ( (NULL != m_pAddressCapCache) ||
  231. (NULL != m_pLineCapCache) ||
  232. (NULL != m_pPhoneCapCache) )
  233. {
  234. LOG((TL_ERROR, "AllocateInitializeAllCaches - already initialized"));
  235. _ASSERTE(FALSE);
  236. //
  237. // we could try to complete cleanup and continue, but this would be too
  238. // risky since we don't really know how we got here to begin with.
  239. // simply failing is much safer.
  240. //
  241. return E_UNEXPECTED;
  242. }
  243. ////////////////////////
  244. //
  245. // allocate address cache
  246. //
  247. try
  248. {
  249. m_pAddressCapCache = new CStructCache;
  250. }
  251. catch(...)
  252. {
  253. // Initialize critical section in the constructor most likely threw this exception
  254. LOG((TL_ERROR, "AllocateInitializeAllCaches - m_pAddressCapCache constructor threw an exception"));
  255. m_pAddressCapCache = NULL;
  256. }
  257. if (NULL == m_pAddressCapCache)
  258. {
  259. LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to allocate m_pAddressCapCache"));
  260. FreeAllCaches();
  261. return E_OUTOFMEMORY;
  262. }
  263. //
  264. // attempt to initialize address cache
  265. //
  266. HRESULT hr = m_pAddressCapCache->Initialize(5,
  267. sizeof(LINEADDRESSCAPS) + 500,
  268. BUFFERTYPE_ADDRCAP
  269. );
  270. if (FAILED(hr))
  271. {
  272. LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to initialize m_pAddressCapCache. hr = %lx", hr));
  273. FreeAllCaches();
  274. return hr;
  275. }
  276. ////////////////////////
  277. //
  278. // allocate line cache
  279. //
  280. try
  281. {
  282. m_pLineCapCache = new CStructCache;
  283. }
  284. catch(...)
  285. {
  286. // Initialize critical section in the constructor most likely threw this exception
  287. LOG((TL_ERROR, "AllocateInitializeAllCaches - m_pLineCapCache constructor threw an exception"));
  288. m_pLineCapCache = NULL;
  289. }
  290. if (NULL == m_pLineCapCache )
  291. {
  292. LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to allocate m_pLineCapCache"));
  293. FreeAllCaches();
  294. return E_OUTOFMEMORY;
  295. }
  296. //
  297. // attempt to initialize line cache
  298. //
  299. hr = m_pLineCapCache->Initialize(5,
  300. sizeof(LINEDEVCAPS) + 500,
  301. BUFFERTYPE_LINEDEVCAP
  302. );
  303. if (FAILED(hr))
  304. {
  305. LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to initialize m_pLineCapCache. hr = %lx", hr));
  306. FreeAllCaches();
  307. return hr;
  308. }
  309. ////////////////////////
  310. //
  311. // allocate phone cache
  312. //
  313. try
  314. {
  315. m_pPhoneCapCache = new CStructCache;
  316. }
  317. catch(...)
  318. {
  319. // Initialize critical section in the constructor most likely threw this exception
  320. LOG((TL_ERROR, "AllocateInitializeAllCaches - m_pPhoneCapCache constructor threw an exception"));
  321. m_pPhoneCapCache = NULL;
  322. }
  323. //
  324. // succeeded?
  325. //
  326. if (NULL == m_pPhoneCapCache)
  327. {
  328. LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to allocate m_pPhoneCapCache"));
  329. FreeAllCaches();
  330. return E_OUTOFMEMORY;
  331. }
  332. //
  333. // initialize phone cache
  334. //
  335. hr = m_pPhoneCapCache->Initialize(5,
  336. sizeof(PHONECAPS) + 500,
  337. BUFFERTYPE_PHONECAP
  338. );
  339. if (FAILED(hr))
  340. {
  341. LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to initialize m_pPhoneCapCache. hr = %lx", hr));
  342. FreeAllCaches();
  343. return hr;
  344. }
  345. LOG((TL_TRACE, "AllocateInitializeAllCaches - finish"));
  346. return S_OK;
  347. }
  348. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  349. //
  350. // CTAPI::FreeAllCaches
  351. //
  352. // shuts down and deletes all allocated cache objects (address, line, phone)
  353. //
  354. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  355. void CTAPI::FreeAllCaches()
  356. {
  357. LOG((TL_TRACE, "FreeAllCaches - enter"));
  358. //
  359. // Note: it is safe to shutdown a cache that failed initialization or was
  360. // not initialized at all
  361. //
  362. if (NULL != m_pAddressCapCache)
  363. {
  364. LOG((TL_TRACE, "FreeAllCaches - freeing AddressCapCache"));
  365. m_pAddressCapCache->Shutdown();
  366. delete m_pAddressCapCache;
  367. m_pAddressCapCache = NULL;
  368. }
  369. if (NULL != m_pLineCapCache)
  370. {
  371. LOG((TL_TRACE, "FreeAllCaches - freeing LineCapCache"));
  372. m_pLineCapCache->Shutdown();
  373. delete m_pLineCapCache;
  374. m_pLineCapCache = NULL;
  375. }
  376. if (NULL != m_pPhoneCapCache)
  377. {
  378. LOG((TL_TRACE, "FreeAllCaches - freeing PhoneCapCache"));
  379. m_pPhoneCapCache->Shutdown();
  380. delete m_pPhoneCapCache;
  381. m_pPhoneCapCache = NULL;
  382. }
  383. LOG((TL_TRACE, "FreeAllCaches - exit"));
  384. }
  385. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  386. //
  387. // CTAPI::Initialize
  388. //
  389. // Intialize the TAPI object
  390. //
  391. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  392. HRESULT
  393. STDMETHODCALLTYPE
  394. CTAPI::Initialize(
  395. void
  396. )
  397. {
  398. HRESULT hr;
  399. int tapiObjectArraySize=0;
  400. LOG((TL_TRACE, "Initialize[%p] enter", this ));
  401. //Serialize the Init and Shutdown code
  402. WaitForSingleObject( ghTapiInitShutdownSerializeMutex, INFINITE );
  403. //
  404. // if we're already initialized
  405. // just return
  406. //
  407. Lock();
  408. if ( m_dwFlags & TAPIFLAG_INITIALIZED )
  409. {
  410. LOG((TL_TRACE, "Already initialized - return S_FALSE"));
  411. Unlock();
  412. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  413. return S_FALSE;
  414. }
  415. //
  416. // start up TAPI if we haven't already
  417. //
  418. EnterCriticalSection( &gcsTapiObjectArray );
  419. tapiObjectArraySize = m_sTAPIObjectArray.GetSize();
  420. LeaveCriticalSection ( &gcsTapiObjectArray );
  421. if ( 0 == tapiObjectArraySize )
  422. {
  423. //
  424. // create handle table
  425. //
  426. hr = AllocateAndInitializeHandleTable();
  427. if (FAILED(hr))
  428. {
  429. LOG((TL_ERROR, "Initialize failed to create handle table"));
  430. Unlock();
  431. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  432. return hr;
  433. }
  434. hr = mapTAPIErrorCode( AllocClientResources (1) );
  435. if ( 0 != hr )
  436. {
  437. LOG((TL_ERROR, "AllocClientResources failed - %lx", hr));
  438. ShutdownAndDeallocateHandleTable();
  439. Unlock();
  440. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  441. return hr;
  442. }
  443. EnterCriticalSection( &gcsGlobalInterfaceTable );
  444. //
  445. // get/create the global interface table
  446. //
  447. hr = CoCreateInstance(
  448. CLSID_StdGlobalInterfaceTable,
  449. NULL,
  450. CLSCTX_INPROC_SERVER,
  451. IID_IGlobalInterfaceTable,
  452. (void **)&gpGIT
  453. );
  454. LeaveCriticalSection( &gcsGlobalInterfaceTable );
  455. if ( !SUCCEEDED(hr) )
  456. {
  457. LOG((TL_ERROR, "Initialize - cocreate git failed - %lx", hr));
  458. ShutdownAndDeallocateHandleTable();
  459. Unlock();
  460. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  461. return hr;
  462. }
  463. }
  464. //
  465. // allocate and initialize all caches
  466. //
  467. // note: if something fails in Initialize later on, we don't really need
  468. // to clean caches in initialize itself, because the caches will be freed
  469. // in CTAPI::FinalRelease when the tapi object is destroyed.
  470. //
  471. hr = AllocateInitializeAllCaches();
  472. if ( FAILED(hr))
  473. {
  474. LOG((TL_ERROR, "Initialize - failed to create and initialize caches"));
  475. if ( 0 == tapiObjectArraySize )
  476. {
  477. EnterCriticalSection( &gcsGlobalInterfaceTable );
  478. if ( NULL != gpGIT )
  479. {
  480. LOG((TL_TRACE, "Shutdown - release GIT"));
  481. gpGIT->Release();
  482. gpGIT = NULL;
  483. }
  484. LeaveCriticalSection( &gcsGlobalInterfaceTable );
  485. ShutdownAndDeallocateHandleTable();
  486. }
  487. Unlock();
  488. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  489. return E_OUTOFMEMORY;
  490. }
  491. //
  492. // Call LineInitialize
  493. //
  494. hr = NewInitialize();
  495. if (S_OK != hr)
  496. {
  497. LOG((TL_ERROR, "Initialize - NewInitialize returned %lx", hr));
  498. if ( 0 == tapiObjectArraySize )
  499. {
  500. EnterCriticalSection( &gcsGlobalInterfaceTable );
  501. if ( NULL != gpGIT )
  502. {
  503. LOG((TL_TRACE, "Shutdown - release GIT"));
  504. gpGIT->Release();
  505. gpGIT = NULL;
  506. }
  507. LeaveCriticalSection( &gcsGlobalInterfaceTable );
  508. ShutdownAndDeallocateHandleTable();
  509. }
  510. FreeAllCaches();
  511. Unlock();
  512. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  513. return hr;
  514. }
  515. //
  516. // create the address objects
  517. //
  518. hr = CreateAllAddressesOnAllLines();
  519. if (S_OK != hr)
  520. {
  521. LOG((TL_INFO, "Initialize - CreateAddresses returned %lx", hr));
  522. NewShutdown();
  523. if ( 0 == tapiObjectArraySize )
  524. {
  525. EnterCriticalSection( &gcsGlobalInterfaceTable );
  526. if ( NULL != gpGIT )
  527. {
  528. LOG((TL_TRACE, "Shutdown - release GIT"));
  529. gpGIT->Release();
  530. gpGIT = NULL;
  531. }
  532. LeaveCriticalSection( &gcsGlobalInterfaceTable );
  533. ShutdownAndDeallocateHandleTable();
  534. }
  535. FreeAllCaches();
  536. Unlock();
  537. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  538. return hr;
  539. }
  540. //
  541. // create the phone objects
  542. //
  543. hr = CreateAllPhones();
  544. if (S_OK != hr)
  545. {
  546. LOG((TL_INFO, "Initialize - CreateAllPhones returned %lx", hr));
  547. NewShutdown();
  548. m_AddressArray.Shutdown ();
  549. if ( 0 == tapiObjectArraySize )
  550. {
  551. EnterCriticalSection( &gcsGlobalInterfaceTable );
  552. if ( NULL != gpGIT )
  553. {
  554. LOG((TL_TRACE, "Shutdown - release GIT"));
  555. gpGIT->Release();
  556. gpGIT = NULL;
  557. }
  558. LeaveCriticalSection( &gcsGlobalInterfaceTable );
  559. ShutdownAndDeallocateHandleTable();
  560. }
  561. FreeAllCaches();
  562. Unlock();
  563. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  564. return hr;
  565. }
  566. //
  567. // create the connectionpoint object
  568. //
  569. CComObject< CTAPIConnectionPoint > * p;
  570. hr = CComObject< CTAPIConnectionPoint >::CreateInstance( &p );
  571. if ( FAILED(hr) )
  572. {
  573. LOG((TL_ERROR, "new CTAPIConnectionPoint failed"));
  574. NewShutdown();
  575. m_AddressArray.Shutdown ();
  576. m_PhoneArray.Shutdown ();
  577. if ( 0 == tapiObjectArraySize )
  578. {
  579. EnterCriticalSection( &gcsGlobalInterfaceTable );
  580. if ( NULL != gpGIT )
  581. {
  582. LOG((TL_TRACE, "Shutdown - release GIT"));
  583. gpGIT->Release();
  584. gpGIT = NULL;
  585. }
  586. LeaveCriticalSection( &gcsGlobalInterfaceTable );
  587. ShutdownAndDeallocateHandleTable();
  588. }
  589. FreeAllCaches();
  590. Unlock();
  591. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  592. return hr;
  593. }
  594. //
  595. // init the connection point
  596. //
  597. hr = p->Initialize(
  598. (IConnectionPointContainer *)this,
  599. IID_ITTAPIEventNotification
  600. );
  601. if ( FAILED(hr) )
  602. {
  603. LOG((TL_ERROR, "initialize CTAPIConnectionPoint failed"));
  604. delete p;
  605. NewShutdown();
  606. m_AddressArray.Shutdown ();
  607. m_PhoneArray.Shutdown ();
  608. if ( 0 == tapiObjectArraySize )
  609. {
  610. EnterCriticalSection( &gcsGlobalInterfaceTable );
  611. if ( NULL != gpGIT )
  612. {
  613. LOG((TL_TRACE, "Shutdown - release GIT"));
  614. gpGIT->Release();
  615. gpGIT = NULL;
  616. }
  617. LeaveCriticalSection( &gcsGlobalInterfaceTable );
  618. ShutdownAndDeallocateHandleTable();
  619. }
  620. FreeAllCaches();
  621. Unlock();
  622. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  623. return hr;
  624. }
  625. m_pCP = p;
  626. //
  627. // this object is initialized
  628. //
  629. m_dwFlags = TAPIFLAG_INITIALIZED;
  630. //
  631. // save object in global list
  632. //
  633. CTAPI * pTapi = this;
  634. EnterCriticalSection( &gcsTapiObjectArray );
  635. m_sTAPIObjectArray.Add( pTapi );
  636. // Set the event filter mask
  637. // Always ask for
  638. // TE_CALLSTATE,
  639. // TE_CALLNOTIFICATION,
  640. // TE_PHONEVENET,
  641. // TE_CALLHUB,
  642. // TE_CALLINFOCHANGE
  643. // events. These events are used internally by Tapi3
  644. ULONG64 ulMask =
  645. EM_LINE_CALLSTATE | // TE_CALLSTATE
  646. EM_LINE_APPNEWCALL | // TE_CALLNOTIFICATION
  647. EM_PHONE_CLOSE | // TE_PHONEEVENT
  648. EM_PHONE_STATE | // TE_PHONEEVENT
  649. EM_PHONE_BUTTONMODE | // TE_PHONEEVENT
  650. EM_PHONE_BUTTONSTATE | // TE_PHONEVENT
  651. EM_LINE_APPNEWCALLHUB | // TE_CALLHUB
  652. EM_LINE_CALLHUBCLOSE | // TE_CALLHUB
  653. EM_LINE_CALLINFO | // TE_CALLINFOCHANGE
  654. EM_LINE_CREATE | // TE_TAPIOBJECT
  655. EM_LINE_REMOVE | // TE_TAPIOBJECT
  656. EM_LINE_CLOSE | // TE_TAPIOBJECT
  657. EM_PHONE_CREATE | // TE_TAPIOBJECT
  658. EM_PHONE_REMOVE | // TE_TAPIOBJECT
  659. EM_LINE_DEVSPECIFICEX | // TE_ADDRESSDEVSPECIFIC
  660. EM_LINE_DEVSPECIFIC | // TE_ADDRESSDEVSPECIFIC
  661. EM_PHONE_DEVSPECIFIC; // TE_PHONEDEVSPECIFIC
  662. DWORD dwLineDevStateSubMasks =
  663. LINEDEVSTATE_REINIT | // TE_TAPIOBJECT
  664. LINEDEVSTATE_TRANSLATECHANGE ; // TE_TAPIOBJECT
  665. tapiSetEventFilterMasks (
  666. TAPIOBJ_NULL,
  667. NULL,
  668. ulMask
  669. );
  670. tapiSetEventFilterSubMasks (
  671. TAPIOBJ_NULL,
  672. NULL,
  673. EM_LINE_LINEDEVSTATE,
  674. dwLineDevStateSubMasks
  675. );
  676. LeaveCriticalSection ( &gcsTapiObjectArray );
  677. Unlock();
  678. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  679. LOG((TL_TRACE, "Initialize exit - return SUCCESS"));
  680. return S_OK;
  681. }
  682. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  683. //
  684. // CTAPI::get_Addresses
  685. //
  686. // Creates & returns the collection of address objects
  687. //
  688. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  689. HRESULT
  690. STDMETHODCALLTYPE
  691. CTAPI::get_Addresses(VARIANT * pVariant)
  692. {
  693. LOG((TL_TRACE, "get_Addresses enter"));
  694. LOG((TL_TRACE, " pVariant ------->%p", pVariant));
  695. HRESULT hr;
  696. IDispatch * pDisp;
  697. Lock();
  698. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ) )
  699. {
  700. LOG((TL_ERROR, "get_Addresses - tapi object must be initialized first" ));
  701. Unlock();
  702. return E_INVALIDARG;
  703. }
  704. Unlock();
  705. if (TAPIIsBadWritePtr( pVariant, sizeof (VARIANT) ) )
  706. {
  707. LOG((TL_ERROR, "get_Addresses - bad pointer"));
  708. return E_POINTER;
  709. }
  710. CComObject< CTapiCollection< ITAddress > > * p;
  711. CComObject< CTapiCollection< ITAddress > >::CreateInstance( &p );
  712. if (NULL == p)
  713. {
  714. LOG((TL_ERROR, "get_Addresses - could not create collection" ));
  715. return E_OUTOFMEMORY;
  716. }
  717. Lock();
  718. // initialize
  719. hr = p->Initialize( m_AddressArray );
  720. Unlock();
  721. if (S_OK != hr)
  722. {
  723. LOG((TL_ERROR, "get_Addresses - could not initialize collection" ));
  724. delete p;
  725. return hr;
  726. }
  727. // get the IDispatch interface
  728. hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp );
  729. if (S_OK != hr)
  730. {
  731. LOG((TL_ERROR, "get_Addresses - could not get IDispatch interface" ));
  732. delete p;
  733. return hr;
  734. }
  735. // put it in the variant
  736. VariantInit(pVariant);
  737. pVariant->vt = VT_DISPATCH;
  738. pVariant->pdispVal = pDisp;
  739. LOG((TL_TRACE, "get_Addressess exit - return %lx", hr ));
  740. return hr;
  741. }
  742. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  743. //
  744. // CTAPI::EnumerateAddresses
  745. //
  746. // Create & return an address enumerator
  747. //
  748. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  749. HRESULT
  750. STDMETHODCALLTYPE
  751. CTAPI::EnumerateAddresses(
  752. IEnumAddress ** ppEnumAddresses
  753. )
  754. {
  755. HRESULT hr = S_OK;
  756. CComObject< CTapiEnum<IEnumAddress, ITAddress, &IID_IEnumAddress> > * pEnum;
  757. LOG((TL_TRACE, "EnumerateAddresses enter"));
  758. Lock();
  759. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
  760. {
  761. LOG((TL_ERROR, "EnumerateAddresses - tapi object must be initialized first" ));
  762. Unlock();
  763. return TAPI_E_REINIT;
  764. }
  765. Unlock();
  766. if ( TAPIIsBadWritePtr( ppEnumAddresses, sizeof (IEnumAddress *) ) )
  767. {
  768. LOG((TL_ERROR, "EnumerateAddresses - bad pointer"));
  769. return E_POINTER;
  770. }
  771. // create the object
  772. hr = CComObject< CTapiEnum<IEnumAddress, ITAddress, &IID_IEnumAddress> >::CreateInstance( &pEnum );
  773. if (S_OK != hr)
  774. {
  775. LOG((TL_ERROR, "EnumerateAddresses - could not create enum - return %lx", hr));
  776. return hr;
  777. }
  778. // initialize
  779. Lock();
  780. hr = pEnum->Initialize( m_AddressArray );
  781. Unlock();
  782. if (S_OK != hr)
  783. {
  784. pEnum->Release();
  785. LOG((TL_ERROR, "EnumerateAddresses - could not initialize enum - return %lx", hr));
  786. return hr;
  787. }
  788. *ppEnumAddresses = pEnum;
  789. LOG((TL_TRACE, "EnumerateAddresses exit - return %lx", hr));
  790. return hr;
  791. }
  792. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  793. //
  794. // CTAPI::GetPhoneArray
  795. //
  796. // Fill a phone array. The array will have references to all
  797. // of the phone objects it contains.
  798. //
  799. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  800. HRESULT
  801. CTAPI::GetPhoneArray(
  802. PhoneArray *pPhoneArray
  803. )
  804. {
  805. HRESULT hr = S_OK;
  806. LOG((TL_TRACE, "GetPhoneArray enter"));
  807. Lock();
  808. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
  809. {
  810. LOG((TL_ERROR, "GetPhoneArray - tapi object must be initialized first" ));
  811. Unlock();
  812. return E_INVALIDARG;
  813. }
  814. Unlock();
  815. if ( IsBadReadPtr( pPhoneArray, sizeof (PhoneArray) ) )
  816. {
  817. LOG((TL_ERROR, "GetPhoneArray - bad pointer"));
  818. return E_POINTER;
  819. }
  820. Lock();
  821. // initialize the array
  822. for(int iCount = 0; iCount < m_PhoneArray.GetSize(); iCount++)
  823. {
  824. pPhoneArray->Add(m_PhoneArray[iCount]);
  825. }
  826. Unlock();
  827. LOG((TL_TRACE, "GetPhoneArray exit - return %lx", hr));
  828. return hr;
  829. }
  830. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  831. //
  832. // CTAPI::RegisterCallHubNotifications
  833. //
  834. // This method is used to tell TAPI that the application is interested in
  835. // receiving callhub events.
  836. //
  837. // RETURNS
  838. //
  839. // S_OK
  840. //
  841. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  842. HRESULT
  843. STDMETHODCALLTYPE
  844. CTAPI::RegisterCallHubNotifications(
  845. VARIANT_BOOL bNotify
  846. )
  847. {
  848. LOG((TL_TRACE, "RegisterCallHubNotifications - enter"));
  849. Lock();
  850. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
  851. {
  852. LOG((TL_ERROR, "RCHN - tapi object must be initialized first" ));
  853. Unlock();
  854. return E_INVALIDARG;
  855. }
  856. if ( bNotify )
  857. {
  858. LOG((TL_INFO, "RCHN - callhub notify on"));
  859. m_dwFlags |= TAPIFLAG_CALLHUBNOTIFY;
  860. }
  861. else
  862. {
  863. LOG((TL_INFO, "RCHN - callhub notify off"));
  864. m_dwFlags &= ~TAPIFLAG_CALLHUBNOTIFY;
  865. }
  866. Unlock();
  867. LOG((TL_TRACE, "RegisterCallHubNotifications - exit - success"));
  868. return S_OK;
  869. }
  870. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  871. //
  872. // SetCallHubTracking
  873. //
  874. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  875. HRESULT
  876. CTAPI::SetCallHubTracking(
  877. VARIANT pAddresses,
  878. VARIANT_BOOL bSet
  879. )
  880. {
  881. HRESULT hr = S_OK;
  882. SAFEARRAY * pAddressArray;
  883. LONG llBound, luBound;
  884. int iCount;
  885. LOG((TL_TRACE, "SetCallHubTracking - enter"));
  886. Lock();
  887. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
  888. {
  889. LOG((TL_ERROR, "SCHT - tapi object must be initialized first" ));
  890. Unlock();
  891. return E_INVALIDARG;
  892. }
  893. Unlock();
  894. hr = VerifyAndGetArrayBounds(
  895. pAddresses,
  896. &pAddressArray,
  897. &llBound,
  898. &luBound
  899. );
  900. if (!SUCCEEDED(hr))
  901. {
  902. LOG((TL_ERROR, "SCHT - invalid address array - return %lx", hr));
  903. return hr;
  904. }
  905. //
  906. // all addresses
  907. //
  908. if (NULL == pAddressArray)
  909. {
  910. Lock();
  911. //
  912. // go through all the addresses
  913. //
  914. for (iCount = 0; iCount < m_AddressArray.GetSize(); iCount++ )
  915. {
  916. CAddress * pCAddress;
  917. //
  918. // register
  919. //
  920. pCAddress = dynamic_cast<CAddress *>(m_AddressArray[iCount]);
  921. if (NULL == pCAddress)
  922. {
  923. LOG((TL_ERROR, "SCHT - out of memory"));
  924. Unlock();
  925. return E_OUTOFMEMORY;
  926. }
  927. hr = (pCAddress)->SetCallHubTracking( bSet );
  928. if (!SUCCEEDED(hr))
  929. {
  930. LOG((TL_WARN,
  931. "SCHT failed %lx on address %lx",
  932. hr,
  933. iCount
  934. ));
  935. }
  936. }
  937. m_dwFlags |= TAPIFLAG_ALLCALLHUBTRACKING;
  938. Unlock();
  939. return S_OK;
  940. }
  941. //
  942. // if here, only registering addresses
  943. // from array
  944. //
  945. // go through array
  946. //
  947. for ( ; llBound <=luBound; llBound++ )
  948. {
  949. ITAddress * pAddress;
  950. CAddress * pCAddress;
  951. hr = SafeArrayGetElement(
  952. pAddressArray,
  953. &llBound,
  954. &pAddress
  955. );
  956. if ( (!SUCCEEDED(hr)) || (NULL == pAddress) )
  957. {
  958. continue;
  959. }
  960. pCAddress = dynamic_cast<CAddress *>(pAddress);
  961. hr = pCAddress->SetCallHubTracking( bSet );
  962. //
  963. // safearragetelement addrefs
  964. //
  965. pAddress->Release();
  966. if (!SUCCEEDED(hr))
  967. {
  968. LOG((
  969. TL_WARN,
  970. "SCHT failed %lx on address %p",
  971. hr,
  972. pAddress
  973. ));
  974. return hr;
  975. }
  976. }
  977. LOG((TL_TRACE, "SetCallHubTracking - exit - success"));
  978. return S_OK;
  979. }
  980. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  981. //
  982. // CTAPI::RegisterCallNotifications
  983. //
  984. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  985. HRESULT
  986. STDMETHODCALLTYPE
  987. CTAPI::RegisterCallNotifications(
  988. ITAddress * pAddress,
  989. VARIANT_BOOL fMonitor,
  990. VARIANT_BOOL fOwner,
  991. long lMediaTypes,
  992. long lCallbackInstance,
  993. long * plRegister
  994. )
  995. {
  996. HRESULT hr = S_OK;
  997. PVOID pRegister;
  998. DWORD dwMediaModes = 0, dwPrivs = 0;
  999. REGISTERITEM * pRegisterItem;
  1000. CAddress * pCAddress;
  1001. LOG((TL_TRACE, "RegisterCallNotifications - enter"));
  1002. Lock();
  1003. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
  1004. {
  1005. LOG((TL_ERROR, "RegisterCallNotifications - tapi object must be initialized first" ));
  1006. Unlock();
  1007. return E_INVALIDARG;
  1008. }
  1009. Unlock();
  1010. if (TAPIIsBadWritePtr( plRegister, sizeof(long) ) )
  1011. {
  1012. LOG((TL_ERROR, "RegisterCallNotifications - invalid plRegister"));
  1013. return E_POINTER;
  1014. }
  1015. try
  1016. {
  1017. pCAddress = dynamic_cast<CAddress *>(pAddress);
  1018. }
  1019. catch(...)
  1020. {
  1021. hr = E_POINTER;
  1022. }
  1023. if ( ( NULL == pCAddress ) || !SUCCEEDED(hr) )
  1024. {
  1025. LOG((TL_ERROR, "RegisterCallNotifications - bad address"));
  1026. return E_POINTER;
  1027. }
  1028. //
  1029. // determine the privileges
  1030. //
  1031. if (fOwner)
  1032. {
  1033. dwPrivs |= LINECALLPRIVILEGE_OWNER;
  1034. }
  1035. if (fMonitor)
  1036. {
  1037. dwPrivs |= LINECALLPRIVILEGE_MONITOR;
  1038. }
  1039. if ( 0 == dwPrivs )
  1040. {
  1041. LOG((TL_ERROR, "RegisterCallNotifications - fMonitor and/or fOwner must be true"));
  1042. return E_INVALIDARG;
  1043. }
  1044. if (! (pCAddress->GetMediaMode(
  1045. lMediaTypes,
  1046. &dwMediaModes
  1047. ) ) )
  1048. {
  1049. LOG((TL_ERROR, "RegisterCallNotifications - bad mediamodes"));
  1050. return E_INVALIDARG;
  1051. }
  1052. Lock();
  1053. pRegisterItem = (REGISTERITEM *)ClientAlloc( sizeof(REGISTERITEM) );
  1054. if ( NULL == pRegisterItem )
  1055. {
  1056. LOG((TL_ERROR, "RegisterCallNotifications - Alloc registrationarray failed"));
  1057. Unlock();
  1058. return E_OUTOFMEMORY;
  1059. }
  1060. hr = pCAddress->AddCallNotification(
  1061. dwPrivs,
  1062. dwMediaModes,
  1063. lCallbackInstance,
  1064. &pRegister
  1065. );
  1066. if (!SUCCEEDED(hr))
  1067. {
  1068. LOG((TL_ERROR, "RegisterCallNotifications - AddCallNotification failed"));
  1069. ClientFree( pRegisterItem );
  1070. Unlock();
  1071. return hr;
  1072. }
  1073. pRegisterItem->dwType = RA_ADDRESS;
  1074. pRegisterItem->pInterface = (PVOID)pCAddress;
  1075. pRegisterItem->pRegister = pRegister;
  1076. try
  1077. {
  1078. m_RegisterItemPtrList.push_back( (PVOID)pRegisterItem );
  1079. }
  1080. catch(...)
  1081. {
  1082. hr = E_OUTOFMEMORY;
  1083. LOG((TL_ERROR, "RegisterCallNotifications- failed - because of alloc failure"));
  1084. ClientFree( pRegisterItem );
  1085. }
  1086. #if DBG
  1087. if (m_dwEventFilterMask == 0)
  1088. {
  1089. LOG((TL_WARN, "RegisterCallNotifications - no Event Mask set !!!"));
  1090. }
  1091. #endif
  1092. Unlock();
  1093. //
  1094. // return registration cookie
  1095. //
  1096. if( S_OK == hr )
  1097. {
  1098. //
  1099. // create a 32-bit handle for the RegisterItem pointer
  1100. //
  1101. DWORD dwCookie = CreateHandleTableEntry((ULONG_PTR)pRegisterItem);
  1102. if (0 == dwCookie)
  1103. {
  1104. hr = E_OUTOFMEMORY;
  1105. LOG((TL_ERROR, "RegisterCallNotifications - failed to create a handle for REGISTERITEM object %p", pRegisterItem));
  1106. }
  1107. else
  1108. {
  1109. LOG((TL_INFO,
  1110. "RegisterCallNotifications - Mapped handle %lx (to be returned as cookie) to REGISTERITEM object %p",
  1111. dwCookie, pRegisterItem ));
  1112. // register the cookie with the address object, so address can remove it if
  1113. // the address is deallocated before the call to CTAPI::UnregisterNotifications
  1114. pCAddress->RegisterNotificationCookie(dwCookie);
  1115. *plRegister = dwCookie;
  1116. }
  1117. }
  1118. LOG((TL_TRACE, "RegisterCallNotifications - return %lx", hr));
  1119. return hr;
  1120. }
  1121. STDMETHODIMP
  1122. CTAPI::UnregisterNotifications(
  1123. long ulRegister
  1124. )
  1125. {
  1126. DWORD dwType;
  1127. HRESULT hr = S_OK;
  1128. REGISTERITEM * pRegisterItem = NULL;
  1129. LOG((TL_TRACE, "UnregisterNotifications - enter. Cookie %lx", ulRegister));
  1130. Lock();
  1131. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
  1132. {
  1133. LOG((TL_ERROR, "UnregNot - tapi object must be initialized first" ));
  1134. Unlock();
  1135. return E_INVALIDARG;
  1136. }
  1137. //
  1138. // convert cookie to registration object pointer
  1139. //
  1140. pRegisterItem = (REGISTERITEM*) GetHandleTableEntry(ulRegister);
  1141. //
  1142. // remove cookie from the table
  1143. //
  1144. DeleteHandleTableEntry(ulRegister);
  1145. Unlock();
  1146. if ( NULL != pRegisterItem )
  1147. {
  1148. LOG((TL_INFO, "UnregisterNotifications - Matched cookie %lx to REGISTERITEM object %p", ulRegister, pRegisterItem ));
  1149. if (IsBadReadPtr( pRegisterItem, sizeof(REGISTERITEM) ) )
  1150. {
  1151. LOG((TL_ERROR, "UnregNot - invalid pRegisterItem returned from the handle table search"));
  1152. return E_POINTER;
  1153. }
  1154. }
  1155. else
  1156. {
  1157. LOG((TL_WARN, "UnregisterNotifications - invalid lRegister"));
  1158. return E_INVALIDARG;
  1159. }
  1160. dwType = pRegisterItem->dwType;
  1161. //
  1162. // switch on the type of notification
  1163. //
  1164. switch ( dwType )
  1165. {
  1166. case RA_ADDRESS:
  1167. CAddress * pCAddress;
  1168. ITAddress * pAddress;
  1169. pCAddress = (CAddress *) (pRegisterItem->pInterface);
  1170. //
  1171. // try to get the address
  1172. //
  1173. try
  1174. {
  1175. hr = pCAddress->QueryInterface(
  1176. IID_ITAddress,
  1177. (void **)&pAddress
  1178. );
  1179. }
  1180. catch(...)
  1181. {
  1182. hr = E_POINTER;
  1183. }
  1184. if ( !SUCCEEDED(hr) )
  1185. {
  1186. LOG((TL_ERROR, "Invalid interface in unregisternotifications"));
  1187. return hr;
  1188. }
  1189. //
  1190. // tell the address
  1191. //
  1192. pCAddress->RemoveCallNotification( pRegisterItem->pRegister );
  1193. //
  1194. // tell the address to remove a cookie from its list
  1195. //
  1196. pCAddress->RemoveNotificationCookie(ulRegister);
  1197. pAddress->Release();
  1198. Lock();
  1199. //
  1200. // remove array from our list
  1201. //
  1202. m_RegisterItemPtrList.remove( pRegisterItem );
  1203. Unlock();
  1204. //
  1205. // free structure
  1206. //
  1207. ClientFree( pRegisterItem );
  1208. break;
  1209. case RA_CALLHUB:
  1210. break;
  1211. }
  1212. LOG((TL_TRACE, "UnregisterNotifications - exit - success"));
  1213. return S_OK;
  1214. }
  1215. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1216. //
  1217. //
  1218. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1219. STDMETHODIMP
  1220. CTAPI::get_CallHubs(
  1221. VARIANT * pVariant
  1222. )
  1223. {
  1224. LOG((TL_TRACE, "get_CallHubs enter"));
  1225. LOG((TL_TRACE, " pVariant ------->%p", pVariant));
  1226. HRESULT hr;
  1227. IDispatch * pDisp;
  1228. Lock();
  1229. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ) )
  1230. {
  1231. LOG((TL_ERROR, "get_CallHubs - tapi object must be initialized first" ));
  1232. Unlock();
  1233. return E_INVALIDARG;
  1234. }
  1235. Unlock();
  1236. if ( TAPIIsBadWritePtr( pVariant, sizeof(VARIANT) ) )
  1237. {
  1238. LOG((TL_ERROR, "get_CallHubs - bad pointer"));
  1239. return E_POINTER;
  1240. }
  1241. CComObject< CTapiCollection< ITCallHub > > * p;
  1242. CComObject< CTapiCollection< ITCallHub > >::CreateInstance( &p );
  1243. if (NULL == p)
  1244. {
  1245. LOG((TL_ERROR, "get_CallHubs - could not create collection" ));
  1246. return E_OUTOFMEMORY;
  1247. }
  1248. Lock();
  1249. //
  1250. // initialize
  1251. //
  1252. hr = p->Initialize( m_CallHubArray );
  1253. Unlock();
  1254. if (S_OK != hr)
  1255. {
  1256. LOG((TL_ERROR, "get_CallHubs - could not initialize collection" ));
  1257. delete p;
  1258. return hr;
  1259. }
  1260. //
  1261. // get the IDispatch interface
  1262. //
  1263. hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp );
  1264. if (S_OK != hr)
  1265. {
  1266. LOG((TL_ERROR, "get_CallHubs - could not get IDispatch interface" ));
  1267. delete p;
  1268. return hr;
  1269. }
  1270. //
  1271. // put it in the variant
  1272. //
  1273. VariantInit(pVariant);
  1274. pVariant->vt = VT_DISPATCH;
  1275. pVariant->pdispVal = pDisp;
  1276. LOG((TL_TRACE, "get_CallHubss exit - return %lx", hr ));
  1277. return hr;
  1278. }
  1279. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1280. //
  1281. // EnumerateCallHubs
  1282. //
  1283. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1284. STDMETHODIMP
  1285. CTAPI::EnumerateCallHubs(
  1286. IEnumCallHub ** ppEnumCallHub
  1287. )
  1288. {
  1289. HRESULT hr = S_OK;
  1290. CComObject< CTapiEnum<IEnumCallHub, ITCallHub, &IID_IEnumCallHub> > * pEnum;
  1291. LOG((TL_TRACE, "EnumerateCallHubs enter"));
  1292. Lock();
  1293. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
  1294. {
  1295. LOG((TL_ERROR, "EnumerateCallHubs - tapi object must be initialized first" ));
  1296. Unlock();
  1297. return E_INVALIDARG;
  1298. }
  1299. Unlock();
  1300. if ( TAPIIsBadWritePtr( ppEnumCallHub, sizeof( IEnumCallHub *) ) )
  1301. {
  1302. LOG((TL_ERROR, "EnumerateCallHubs - bad pointer"));
  1303. return E_POINTER;
  1304. }
  1305. //
  1306. // create the object
  1307. //
  1308. hr = CComObject< CTapiEnum<IEnumCallHub, ITCallHub, &IID_IEnumCallHub> >::CreateInstance( &pEnum );
  1309. if (S_OK != hr)
  1310. {
  1311. LOG((TL_ERROR, "EnumerateCallHubs - could not create enum - return %lx", hr));
  1312. return hr;
  1313. }
  1314. //
  1315. // initialize
  1316. //
  1317. Lock();
  1318. hr = pEnum->Initialize( m_CallHubArray );
  1319. Unlock();
  1320. if (S_OK != hr)
  1321. {
  1322. pEnum->Release();
  1323. LOG((TL_ERROR, "EnumerateCallHubs - could not initialize enum - return %lx", hr));
  1324. return hr;
  1325. }
  1326. *ppEnumCallHub = pEnum;
  1327. LOG((TL_TRACE, "EnumerateCallHubs exit - return %lx", hr));
  1328. return hr;
  1329. }
  1330. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1331. //
  1332. // CTAPI::EnumConnectionPoints
  1333. //
  1334. // Standard IConnectionPoint method
  1335. //
  1336. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1337. HRESULT
  1338. __stdcall
  1339. CTAPI::EnumConnectionPoints(
  1340. IEnumConnectionPoints **ppEnum
  1341. )
  1342. {
  1343. HRESULT hr;
  1344. LOG((TL_TRACE, "EnumConnectionPoints enter"));
  1345. hr = E_NOTIMPL;
  1346. LOG((TL_TRACE, "EnumConnectionPointer exit - return %lx", hr));
  1347. return hr;
  1348. }
  1349. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1350. //
  1351. // FindConnectionPoint
  1352. //
  1353. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1354. HRESULT
  1355. __stdcall
  1356. CTAPI::FindConnectionPoint(
  1357. REFIID riid,
  1358. IConnectionPoint **ppCP
  1359. )
  1360. {
  1361. LOG((TL_TRACE, "FindConnectionPoint enter"));
  1362. #if DBG
  1363. {
  1364. WCHAR guidName[100];
  1365. StringFromGUID2(riid, (LPOLESTR)&guidName, 100);
  1366. LOG((TL_INFO, "FindConnectionPoint - RIID : %S", guidName));
  1367. }
  1368. #endif
  1369. Lock();
  1370. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
  1371. {
  1372. LOG((TL_ERROR, "FindConnectionPoint - tapi object must be initialized first" ));
  1373. Unlock();
  1374. return TAPI_E_NOT_INITIALIZED;
  1375. }
  1376. Unlock();
  1377. if ( TAPIIsBadWritePtr( ppCP, sizeof(IConnectionPoint *) ) )
  1378. {
  1379. LOG((TL_ERROR, "FindConnectionPoint - bad pointer"));
  1380. return E_POINTER;
  1381. }
  1382. //
  1383. // is this the right interface?
  1384. //
  1385. if ( (IID_ITTAPIEventNotification != riid ) && (DIID_ITTAPIDispatchEventNotification != riid ) )
  1386. {
  1387. * ppCP = NULL;
  1388. LOG((TL_ERROR, "FindConnectionPoint - do not support this riid"));
  1389. return CONNECT_E_NOCONNECTION;
  1390. }
  1391. //
  1392. // if it's the right interface, create a new connection point
  1393. // and return it
  1394. //
  1395. Lock();
  1396. *ppCP = m_pCP;
  1397. (*ppCP)->AddRef();
  1398. Unlock();
  1399. //
  1400. // success
  1401. //
  1402. LOG((TL_TRACE, "FindConnectionPoint - Success"));
  1403. return S_OK;
  1404. }
  1405. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1406. //
  1407. // CreateAllAddressesOnAllLines
  1408. // This is called when the first TAPI object is created.
  1409. //
  1410. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1411. HRESULT
  1412. CTAPI::CreateAllAddressesOnAllLines(
  1413. void
  1414. )
  1415. {
  1416. DWORD dwCount;
  1417. LOG((TL_TRACE, "CreateAllAddressesOnAllLines enter"));
  1418. Lock();
  1419. // go through all line devs
  1420. for (dwCount = 0; dwCount < m_dwLineDevs; dwCount++)
  1421. {
  1422. CreateAddressesOnSingleLine( dwCount, FALSE );
  1423. }
  1424. Unlock();
  1425. return S_OK;
  1426. }
  1427. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1428. //
  1429. // CreateAddressesOnSingleLine
  1430. //
  1431. // assumed called in lock!
  1432. //
  1433. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1434. HRESULT
  1435. CTAPI::CreateAddressesOnSingleLine( DWORD dwDeviceID, BOOL bFireEvent )
  1436. {
  1437. DWORD dwRealAddresses = 0, dwAddress;
  1438. DWORD dwAPIVersion;
  1439. HRESULT hr;
  1440. LPLINEDEVCAPS pDevCaps = NULL;
  1441. LPLINEADDRESSCAPS pAddressCaps = NULL;
  1442. LOG((TL_TRACE, "CreateAddressesOnSingleLine: entered."));
  1443. hr = LineNegotiateAPIVersion(
  1444. (HLINEAPP)m_dwLineInitDataHandle,
  1445. dwDeviceID,
  1446. &dwAPIVersion
  1447. );
  1448. if (S_OK != hr)
  1449. {
  1450. LOG((TL_WARN, "CreateAddressesOnSingleLine: LineNegotiateAPIVersion failed on device %d", dwDeviceID));
  1451. return hr;
  1452. }
  1453. LOG((TL_INFO, "CreateAddressesOnSingleLine: LineNegotiateAPIVersion returned version %lx", dwAPIVersion));
  1454. hr = LineGetDevCapsWithAlloc(
  1455. (HLINEAPP)m_dwLineInitDataHandle,
  1456. dwDeviceID,
  1457. dwAPIVersion,
  1458. &pDevCaps
  1459. );
  1460. if (S_OK != hr)
  1461. {
  1462. LOG((TL_WARN, "CreateAddressesOnSingleLine: LineGetDevCaps failed for device %d", dwDeviceID));
  1463. if ( NULL != pDevCaps )
  1464. {
  1465. ClientFree( pDevCaps );
  1466. }
  1467. return hr;
  1468. }
  1469. if (pDevCaps->dwNumAddresses == 0)
  1470. {
  1471. LOG((TL_WARN, "CreateAddressesOnSingleLine: Device %d has no addressess - will assume 1 address", dwDeviceID));
  1472. pDevCaps->dwNumAddresses = 1;
  1473. }
  1474. LPVARSTRING pVarString;
  1475. DWORD dwProviderID;
  1476. //
  1477. // get the permanent provider ID for this line.
  1478. //
  1479. hr = LineGetID(
  1480. NULL,
  1481. dwDeviceID,
  1482. NULL,
  1483. LINECALLSELECT_DEVICEID,
  1484. &pVarString,
  1485. L"tapi/providerid"
  1486. );
  1487. if (S_OK != hr)
  1488. {
  1489. if (NULL != pVarString)
  1490. {
  1491. ClientFree( pVarString);
  1492. }
  1493. if ( NULL != pDevCaps )
  1494. {
  1495. ClientFree( pDevCaps );
  1496. }
  1497. LOG((TL_ERROR, "CreateAddressesOnSingleLine: get_ServiceProviderName - LineGetID returned %lx", hr ));
  1498. return hr;
  1499. }
  1500. //
  1501. // get the id DWORD at the end of the structure
  1502. //
  1503. dwProviderID = *((LPDWORD) (((LPBYTE) pVarString) + pVarString->dwStringOffset));
  1504. ClientFree( pVarString );
  1505. // go through all the addresses on each line, and
  1506. // create an address object.
  1507. for (dwAddress = 0; dwAddress < pDevCaps->dwNumAddresses; dwAddress++)
  1508. {
  1509. CComObject<CAddress> * pAddress;
  1510. ITAddress * pITAddress;
  1511. try
  1512. {
  1513. hr = CComObject<CAddress>::CreateInstance( &pAddress );
  1514. }
  1515. catch(...)
  1516. {
  1517. LOG((TL_ERROR, "CreateAddressesOnSingleLine: CreateInstance - Address - threw"));
  1518. continue;
  1519. }
  1520. if ( !SUCCEEDED(hr) || (NULL == pAddress) )
  1521. {
  1522. LOG((TL_ERROR, "CreateAddressesOnSingleLine: CreateInstance - Address - failed - %lx", hr));
  1523. continue;
  1524. }
  1525. //
  1526. // initialize the address
  1527. // if there are no phone devices,
  1528. // give NULL for the hPhoneApp, so the address
  1529. // doesn't think that there may be a phone device
  1530. //
  1531. hr = pAddress->Initialize(
  1532. this,
  1533. (HLINEAPP)m_dwLineInitDataHandle,
  1534. #ifdef USE_PHONEMSP
  1535. (m_dwPhoneDevs)?((HPHONEAPP)m_dwPhoneInitDataHandle):NULL,
  1536. #endif USE_PHONEMSP
  1537. dwAPIVersion,
  1538. dwDeviceID,
  1539. dwAddress,
  1540. dwProviderID,
  1541. pDevCaps,
  1542. m_dwEventFilterMask
  1543. );
  1544. if (S_OK != hr)
  1545. {
  1546. LOG((TL_ERROR, "CreateAddressesOnSingleLine: failed for device %d, address %d", dwDeviceID, dwAddress));
  1547. delete pAddress;
  1548. continue;
  1549. }
  1550. //
  1551. // add to list
  1552. //
  1553. pITAddress = dynamic_cast<ITAddress *>(pAddress);
  1554. m_AddressArray.Add( pITAddress );
  1555. pAddress->Release();
  1556. if ( bFireEvent )
  1557. {
  1558. CTapiObjectEvent::FireEvent(
  1559. this,
  1560. TE_ADDRESSCREATE,
  1561. pAddress,
  1562. 0,
  1563. NULL
  1564. );
  1565. }
  1566. }
  1567. if ( NULL != pDevCaps )
  1568. {
  1569. ClientFree( pDevCaps );
  1570. }
  1571. LOG((TL_INFO, "CreateAddressesOnSingleLine: completed."));
  1572. return S_OK;
  1573. }
  1574. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1575. //
  1576. // CreateAllPhones
  1577. // This is called when the first TAPI object is created.
  1578. //
  1579. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1580. HRESULT
  1581. CTAPI::CreateAllPhones(
  1582. void
  1583. )
  1584. {
  1585. DWORD dwCount;
  1586. LOG((TL_TRACE, "CreateAllPhones enter"));
  1587. Lock();
  1588. // go through all phone devs
  1589. for (dwCount = 0; dwCount < m_dwPhoneDevs; dwCount++)
  1590. {
  1591. CreatePhone( dwCount, FALSE );
  1592. }
  1593. Unlock();
  1594. return S_OK;
  1595. }
  1596. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1597. //
  1598. // CreatePhone
  1599. //
  1600. // assumed called in lock!
  1601. //
  1602. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1603. HRESULT
  1604. CTAPI::CreatePhone( DWORD dwDeviceID, BOOL bFireEvent )
  1605. {
  1606. DWORD dwAPIVersion;
  1607. HRESULT hr;
  1608. hr = PhoneNegotiateAPIVersion(
  1609. (HPHONEAPP)m_dwPhoneInitDataHandle,
  1610. dwDeviceID,
  1611. &dwAPIVersion
  1612. );
  1613. if (S_OK != hr)
  1614. {
  1615. LOG((TL_WARN, "CreatePhone - phoneNegotiateAPIVersion failed on device %d", dwDeviceID));
  1616. return hr;
  1617. }
  1618. LOG((TL_INFO, "CreatePhone - phoneNegotiateAPIVersion returned version %lx", dwAPIVersion));
  1619. // create a phone object.
  1620. CComObject<CPhone> * pPhone;
  1621. ITPhone * pITPhone;
  1622. __try
  1623. {
  1624. hr = CComObject<CPhone>::CreateInstance( &pPhone );
  1625. }
  1626. __except( (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ?
  1627. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
  1628. {
  1629. LOG((TL_ERROR, "CreatePhone - CreateInstancefailed - because of alloc failure"));
  1630. return hr;
  1631. }
  1632. if ( !SUCCEEDED(hr) || (NULL == pPhone) )
  1633. {
  1634. LOG((TL_ERROR, "CreatePhone - CreateInstance failed - %lx", hr));
  1635. return hr;
  1636. }
  1637. //
  1638. // initialize the phone
  1639. //
  1640. hr = pPhone->Initialize(
  1641. this,
  1642. (HLINEAPP)m_dwPhoneInitDataHandle,
  1643. dwAPIVersion,
  1644. dwDeviceID
  1645. );
  1646. if ( FAILED(hr) )
  1647. {
  1648. LOG((TL_ERROR, "CreatePhone failed for device %d", dwDeviceID));
  1649. delete pPhone;
  1650. return hr;
  1651. }
  1652. //
  1653. // add to list
  1654. //
  1655. pITPhone = dynamic_cast<ITPhone *>(pPhone);
  1656. m_PhoneArray.Add( pITPhone );
  1657. pPhone->Release();
  1658. if ( bFireEvent )
  1659. {
  1660. CTapiObjectEvent::FireEvent(this,
  1661. TE_PHONECREATE,
  1662. NULL,
  1663. 0,
  1664. pITPhone
  1665. );
  1666. }
  1667. return S_OK;
  1668. }
  1669. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1670. //
  1671. // Shutdown
  1672. //
  1673. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1674. HRESULT
  1675. STDMETHODCALLTYPE
  1676. CTAPI::Shutdown()
  1677. {
  1678. PtrList::iterator iter, end;
  1679. int iCount;
  1680. DWORD dwSignalled;
  1681. int tapiObjectArraySize=0;
  1682. CTAPI *pTapi;
  1683. LOG((TL_TRACE, "Shutdown[%p] - enter", this));
  1684. LOG((TL_TRACE, "Shutdown - enter"));
  1685. CoWaitForMultipleHandles (0,
  1686. INFINITE,
  1687. 1,
  1688. &ghTapiInitShutdownSerializeMutex,
  1689. &dwSignalled
  1690. );
  1691. Lock();
  1692. if ( (!( m_dwFlags & TAPIFLAG_INITIALIZED )) &&
  1693. (!( m_dwFlags & TAPIFLAG_REINIT)))
  1694. {
  1695. LOG((TL_WARN, "Shutdown - already shutdown - return S_FALSE"));
  1696. Unlock();
  1697. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  1698. return S_FALSE;
  1699. }
  1700. m_dwFlags &= ~TAPIFLAG_INITIALIZED;
  1701. m_dwFlags &= ~TAPIFLAG_REINIT;
  1702. pTapi = this;
  1703. //
  1704. // close all the phones
  1705. //
  1706. for(iCount = 0; iCount < m_PhoneArray.GetSize(); iCount++)
  1707. {
  1708. CPhone *pCPhone = NULL;
  1709. try
  1710. {
  1711. pCPhone = dynamic_cast<CPhone *>(m_PhoneArray[iCount]);
  1712. }
  1713. catch(...)
  1714. {
  1715. LOG((TL_ERROR, "Shutdown - phone array contains a bad phone pointer"));
  1716. pCPhone = NULL;
  1717. }
  1718. if (NULL != pCPhone)
  1719. {
  1720. pCPhone->ForceClose();
  1721. }
  1722. }
  1723. EnterCriticalSection( &gcsTapiObjectArray );
  1724. m_sTAPIObjectArray.Remove ( pTapi );
  1725. tapiObjectArraySize = m_sTAPIObjectArray.GetSize();
  1726. LeaveCriticalSection ( &gcsTapiObjectArray );
  1727. m_AgentHandlerArray.Shutdown();
  1728. gpLineHashTable->Flush(this);
  1729. gpCallHashTable->Flush(this);
  1730. gpCallHubHashTable->Flush(this);
  1731. gpPhoneHashTable->Flush(this);
  1732. //
  1733. // tell each address in the array that it is time to toss all
  1734. // the cookies
  1735. //
  1736. int nAddressArraySize = m_AddressArray.GetSize();
  1737. for (int i = 0; i < nAddressArraySize; i++)
  1738. {
  1739. //
  1740. // we need a pointer to CAddress to unregister cookies
  1741. //
  1742. CAddress *pAddress = NULL;
  1743. //
  1744. // in case address array contains a pointer to nonreadable memory,
  1745. // do dynamic cast inside try/catch
  1746. //
  1747. try
  1748. {
  1749. pAddress = dynamic_cast<CAddress*>(m_AddressArray[i]);
  1750. }
  1751. catch(...)
  1752. {
  1753. LOG((TL_ERROR, "Shutdown - address array contains a bad address pointer"));
  1754. pAddress = NULL;
  1755. }
  1756. //
  1757. // attempt to unregister address' notifications
  1758. //
  1759. if (NULL != pAddress)
  1760. {
  1761. //
  1762. // unregister all notification cookies
  1763. //
  1764. pAddress->UnregisterAllCookies();
  1765. //
  1766. // notify address that tapi is being shutdown, so it can do
  1767. // whatever clean up is necessary
  1768. //
  1769. pAddress->AddressOnTapiShutdown();
  1770. }
  1771. else
  1772. {
  1773. //
  1774. // we have an address that is not an address. debug!
  1775. //
  1776. LOG((TL_ERROR,
  1777. "Shutdown - address array contains a bad address pointer."));
  1778. _ASSERTE(FALSE);
  1779. }
  1780. }
  1781. m_AddressArray.Shutdown();
  1782. m_PhoneArray.Shutdown();
  1783. m_CallHubArray.Shutdown();
  1784. Unlock();
  1785. NewShutdown();
  1786. Lock();
  1787. if ( NULL != m_pCP )
  1788. {
  1789. m_pCP->Release();
  1790. m_pCP = NULL;
  1791. }
  1792. iter = m_RegisterItemPtrList.begin();
  1793. end = m_RegisterItemPtrList.end();
  1794. while (iter != end)
  1795. {
  1796. ClientFree( *iter );
  1797. iter ++;
  1798. }
  1799. m_RegisterItemPtrList.clear();
  1800. Unlock();
  1801. if ( 0 == tapiObjectArraySize )
  1802. {
  1803. FinalTapiCleanup();
  1804. EnterCriticalSection( &gcsGlobalInterfaceTable );
  1805. ReleaseGIT();
  1806. LeaveCriticalSection( &gcsGlobalInterfaceTable );
  1807. //
  1808. // no longer need handle table.
  1809. //
  1810. ShutdownAndDeallocateHandleTable();
  1811. }
  1812. ReleaseMutex( ghTapiInitShutdownSerializeMutex );
  1813. LOG((TL_TRACE, "Shutdown - exit"));
  1814. return S_OK;
  1815. }
  1816. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1817. //
  1818. // finalrelease of tapi object
  1819. //
  1820. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1821. void
  1822. CTAPI::FinalRelease()
  1823. {
  1824. LOG((TL_TRACE, "FinalRelease - enter"));
  1825. Lock();
  1826. FreeAllCaches();
  1827. Unlock();
  1828. LOG((TL_TRACE, "FinalRelease - exit"));
  1829. }
  1830. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1831. //
  1832. // VerifyAndGetArrayBounds
  1833. //
  1834. // Helper function for variant/safearrays
  1835. //
  1836. // Array
  1837. // IN Variant that contains a safearray
  1838. //
  1839. // ppsa
  1840. // OUT safearray returned here
  1841. //
  1842. // pllBound
  1843. // OUT array lower bound returned here
  1844. //
  1845. // pluBound
  1846. // OUT array upper boudn returned here
  1847. //
  1848. // RETURNS
  1849. //
  1850. // verifies that Array contains an array, and returns the array, upper
  1851. // and lower bounds.
  1852. //
  1853. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1854. HRESULT
  1855. VerifyAndGetArrayBounds(
  1856. VARIANT Array,
  1857. SAFEARRAY ** ppsa,
  1858. long * pllBound,
  1859. long * pluBound
  1860. )
  1861. {
  1862. UINT uDims;
  1863. HRESULT hr = S_OK;
  1864. //
  1865. // see if the variant & safearray are valid
  1866. //
  1867. try
  1868. {
  1869. if (!(V_ISARRAY(&Array)))
  1870. {
  1871. if ( VT_NULL ==Array.vt )
  1872. {
  1873. //
  1874. // null is usually valid
  1875. //
  1876. *ppsa = NULL;
  1877. LOG((TL_INFO, "Returning NULL array"));
  1878. return S_FALSE;
  1879. }
  1880. LOG((TL_ERROR, "Array - not an array"));
  1881. return E_INVALIDARG;
  1882. }
  1883. if ( NULL == Array.parray )
  1884. {
  1885. //
  1886. // null is usually valide
  1887. //
  1888. *ppsa = NULL;
  1889. LOG((TL_INFO, "Returning NULL array"));
  1890. return S_FALSE;
  1891. }
  1892. *ppsa = V_ARRAY(&Array);
  1893. uDims = SafeArrayGetDim( *ppsa );
  1894. }
  1895. catch(...)
  1896. {
  1897. hr = E_POINTER;
  1898. }
  1899. if (!SUCCEEDED(hr))
  1900. {
  1901. LOG((TL_ERROR, "Array - invalid array"));
  1902. return hr;
  1903. }
  1904. //
  1905. // verify array
  1906. //
  1907. if (1 != uDims)
  1908. {
  1909. if (0 == uDims)
  1910. {
  1911. LOG((TL_ERROR, "Array - has 0 dim"));
  1912. return E_INVALIDARG;
  1913. }
  1914. else
  1915. {
  1916. LOG((TL_WARN, "Array - has > 1 dim - will only use 1"));
  1917. }
  1918. }
  1919. //
  1920. // Get array bounds
  1921. //
  1922. SafeArrayGetUBound(
  1923. *ppsa,
  1924. 1,
  1925. pluBound
  1926. );
  1927. SafeArrayGetLBound(
  1928. *ppsa,
  1929. 1,
  1930. pllBound
  1931. );
  1932. return S_OK;
  1933. }
  1934. BOOL QueueCallbackEvent(CTAPI * pTapi, TAPI_EVENT te, IDispatch * pEvent);
  1935. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1936. //
  1937. //
  1938. //
  1939. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1940. HRESULT
  1941. CTAPI::Event(
  1942. TAPI_EVENT te,
  1943. IDispatch * pEvent
  1944. )
  1945. {
  1946. HRESULT hr = S_OK;
  1947. DWORD dwEventFilterMask;
  1948. LOG((TL_TRACE, "Event[%p] - enter. Event[0x%x]", this, te));
  1949. Lock();
  1950. dwEventFilterMask = m_dwEventFilterMask;
  1951. Unlock();
  1952. if( (te != TE_ADDRESS) &&
  1953. (te != TE_CALLHUB) &&
  1954. (te != TE_CALLINFOCHANGE) &&
  1955. (te != TE_CALLMEDIA) &&
  1956. (te != TE_CALLNOTIFICATION) &&
  1957. (te != TE_CALLSTATE) &&
  1958. (te != TE_FILETERMINAL) &&
  1959. (te != TE_PRIVATE) &&
  1960. (te != TE_QOSEVENT) &&
  1961. (te != TE_TAPIOBJECT) &&
  1962. (te != TE_ADDRESSDEVSPECIFIC) &&
  1963. (te != TE_PHONEDEVSPECIFIC) )
  1964. {
  1965. if( (te & dwEventFilterMask) == 0)
  1966. {
  1967. //
  1968. // Don't fire the event
  1969. //
  1970. hr = S_FALSE;
  1971. LOG((TL_INFO, "Event - This Event not Enabled %x", te));
  1972. return hr;
  1973. }
  1974. }
  1975. //
  1976. // It's an event from the event filtering mechanism
  1977. // TE_ADDRESS, TE_CALLHUB, TE_CALLINFOCHANGE, TE_CALLMEDIA,
  1978. // TE_CALLNOTIFICATION, TE_CALLSTATE, TE_FILETERMINAL,
  1979. // TE_PRIVATE, TE_QOSEVENT, TE_TAPIOBJECT
  1980. //
  1981. AddRef();
  1982. pEvent->AddRef();
  1983. if(QueueCallbackEvent(this, te, pEvent) == TRUE)
  1984. {
  1985. LOG((TL_INFO, "Event queued"));
  1986. }
  1987. else
  1988. {
  1989. Release();
  1990. pEvent->Release();
  1991. LOG((TL_INFO, "Event queuing Failed"));
  1992. }
  1993. LOG((TL_TRACE, "Event - exit"));
  1994. return hr;
  1995. }
  1996. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1997. //
  1998. //
  1999. //
  2000. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2001. HRESULT
  2002. CTAPI::EventFire(
  2003. TAPI_EVENT te,
  2004. IDispatch * pEvent
  2005. )
  2006. {
  2007. ITTAPIEventNotification * pCallback = NULL;
  2008. IDispatch * pDispatch = NULL;
  2009. HRESULT hr = S_OK;
  2010. CTAPIConnectionPoint * pCP;
  2011. LOG((TL_TRACE, "EventFire - enter"));
  2012. Lock();
  2013. if( NULL != m_pCP )
  2014. {
  2015. m_pCP->AddRef();
  2016. }
  2017. pCP = m_pCP;
  2018. Unlock();
  2019. if ( NULL != pCP )
  2020. {
  2021. pDispatch = (IDispatch *)pCP->GrabEventCallback();
  2022. if ( NULL != pDispatch )
  2023. {
  2024. hr = pDispatch->QueryInterface(IID_ITTAPIEventNotification,
  2025. (void **)&pCallback
  2026. );
  2027. if (SUCCEEDED(hr) )
  2028. {
  2029. if ( NULL != pCallback )
  2030. {
  2031. LOG((TL_TRACE, "EventFire - fire on ITTAPIEventNotification"));
  2032. pCallback->Event( te, pEvent );
  2033. pCallback->Release();
  2034. }
  2035. #if DBG
  2036. else
  2037. {
  2038. LOG((TL_WARN, "EventFire - can't fire event on ITTAPIEventNotification - no callback"));
  2039. }
  2040. #endif
  2041. }
  2042. else
  2043. {
  2044. CComVariant varResult;
  2045. CComVariant* pvars = new CComVariant[2];
  2046. LOG((TL_TRACE, "EventFire - fire on IDispatch"));
  2047. VariantClear(&varResult);
  2048. pvars[1] = te;
  2049. pvars[0] = pEvent;
  2050. DISPPARAMS disp = { pvars, NULL, 2, 0 };
  2051. pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
  2052. delete[] pvars;
  2053. hr = varResult.scode;
  2054. }
  2055. pDispatch->Release();
  2056. }
  2057. #if DBG
  2058. else
  2059. {
  2060. LOG((TL_WARN, "Event - can't fire event on IDispatch - no callback"));
  2061. }
  2062. #endif
  2063. }
  2064. #if DBG
  2065. else
  2066. {
  2067. LOG((TL_WARN, "Event - can't fire event - no m_pCP"));
  2068. }
  2069. #endif
  2070. if(NULL != pCP)
  2071. {
  2072. pCP->Release();
  2073. }
  2074. pEvent->Release();
  2075. LOG((TL_TRACE, "EventFire - exit"));
  2076. return S_OK;
  2077. }
  2078. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2079. //
  2080. // AddCallHub
  2081. //
  2082. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2083. void
  2084. CTAPI::AddCallHub( CCallHub * pCallHub )
  2085. {
  2086. ITCallHub * pITCallHub;
  2087. Lock();
  2088. pITCallHub = dynamic_cast<ITCallHub *>(pCallHub);
  2089. m_CallHubArray.Add( pITCallHub );
  2090. Unlock();
  2091. }
  2092. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2093. //
  2094. // RemoveCallHub
  2095. //
  2096. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2097. void
  2098. CTAPI::RemoveCallHub( CCallHub * pCallHub )
  2099. {
  2100. ITCallHub * pITCallHub;
  2101. Lock();
  2102. pITCallHub = dynamic_cast<ITCallHub *>(pCallHub);
  2103. m_CallHubArray.Remove( pITCallHub );
  2104. Unlock();
  2105. }
  2106. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2107. //
  2108. //
  2109. //
  2110. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2111. STDMETHODIMP
  2112. CTAPI::get_PrivateTAPIObjects(VARIANT*)
  2113. {
  2114. LOG((TL_TRACE, "get_PrivateTAPIObjects - enter"));
  2115. LOG((TL_ERROR, "get_PrivateTAPIObjects - exit E_NOTIMPL"));
  2116. return E_NOTIMPL;
  2117. }
  2118. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2119. //
  2120. // former EnumeratePrivateTAPIObjects
  2121. //
  2122. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2123. STDMETHODIMP
  2124. CTAPI::EnumeratePrivateTAPIObjects(IEnumUnknown**)
  2125. {
  2126. LOG((TL_TRACE, "EnumeratePrivateTAPIObjects - enter"));
  2127. LOG((TL_ERROR, "EnumeratePrivateTAPIObjects - return E_NOTIMPL"));
  2128. return E_NOTIMPL;
  2129. }
  2130. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2131. //
  2132. // RegisterRequestRecipient
  2133. //
  2134. // simply call LineRegisterRequestRecipient - registers as assisted
  2135. // telephony application
  2136. //
  2137. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2138. STDMETHODIMP
  2139. CTAPI::RegisterRequestRecipient(
  2140. long lRegistrationInstance,
  2141. long lRequestMode,
  2142. #ifdef NEWREQUEST
  2143. long lAddressTypes,
  2144. #endif
  2145. VARIANT_BOOL fEnable
  2146. )
  2147. {
  2148. HRESULT hr;
  2149. LOG((TL_TRACE, "RegisterRequestRecipient - enter"));
  2150. Lock();
  2151. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
  2152. {
  2153. LOG((TL_ERROR, "RegisterRequestRecipient - tapi object must be initialized first" ));
  2154. Unlock();
  2155. return E_INVALIDARG;
  2156. }
  2157. Unlock();
  2158. hr = LineRegisterRequestRecipient(
  2159. (HLINEAPP)m_dwLineInitDataHandle,
  2160. lRegistrationInstance,
  2161. lRequestMode,
  2162. #ifdef NEWREQUEST
  2163. lAddressTypes,
  2164. #endif
  2165. fEnable?TRUE : FALSE
  2166. );
  2167. return hr;
  2168. }
  2169. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2170. //
  2171. // SetAssistedTelephonyPriority
  2172. //
  2173. // set the app priority for assisted telephony
  2174. //
  2175. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2176. STDMETHODIMP
  2177. CTAPI::SetAssistedTelephonyPriority(
  2178. BSTR pAppFilename,
  2179. VARIANT_BOOL fPriority
  2180. )
  2181. {
  2182. HRESULT hr;
  2183. LOG((TL_TRACE, "SetAssistedTelephonyPriority - enter"));
  2184. hr = LineSetAppPriority(
  2185. pAppFilename,
  2186. 0,
  2187. LINEREQUESTMODE_MAKECALL,
  2188. fPriority?1:0
  2189. );
  2190. LOG((TL_TRACE, "SetAssistedTelephonyPriority - exit - return %lx", hr));
  2191. return hr;
  2192. }
  2193. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2194. //
  2195. // SetApplicationPriority
  2196. //
  2197. // sets the app priority for incoming calls and handoff.
  2198. //
  2199. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2200. STDMETHODIMP
  2201. CTAPI::SetApplicationPriority(
  2202. BSTR pAppFilename,
  2203. long lMediaType,
  2204. VARIANT_BOOL fPriority
  2205. )
  2206. {
  2207. HRESULT hr;
  2208. LOG((TL_TRACE, "SetApplicationPriority - enter"));
  2209. hr = LineSetAppPriority(
  2210. pAppFilename,
  2211. lMediaType,
  2212. 0,
  2213. fPriority?1:0
  2214. );
  2215. LOG((TL_TRACE, "SetApplicationPriority - exit - return %lx", hr));
  2216. return hr;
  2217. }
  2218. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2219. //
  2220. // put_EventFilter
  2221. //
  2222. // sets the Event filter mask
  2223. //
  2224. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2225. STDMETHODIMP
  2226. CTAPI::put_EventFilter(long lFilterMask)
  2227. {
  2228. HRESULT hr = S_OK;
  2229. DWORD dwOldFilterMask;
  2230. ULONG64 ulEventMasks;
  2231. DWORD dwLineDevStateSubMasks;
  2232. DWORD dwAddrStateSubMasks;
  2233. LOG((TL_TRACE, "put_EventFilter - enter"));
  2234. if (~ALL_EVENT_FILTER_MASK & lFilterMask)
  2235. {
  2236. LOG((TL_ERROR, "put_EventFilter - Unknown Event type in mask %x", lFilterMask ));
  2237. hr = E_INVALIDARG;
  2238. }
  2239. else
  2240. {
  2241. Lock();
  2242. //
  2243. // Event Filtering, we should pass the mask
  2244. // to all addresses
  2245. //
  2246. HRESULT hr = E_FAIL;
  2247. hr = SetEventFilterToAddresses( lFilterMask );
  2248. if( FAILED(hr) )
  2249. {
  2250. Unlock();
  2251. LOG((TL_ERROR, "put_EventFilter - exit"
  2252. "CopyEventFilterMaskToAddresses failed. Returns 0x%08x", hr));
  2253. return hr;
  2254. }
  2255. //
  2256. // Set the event filter
  2257. //
  2258. dwOldFilterMask = m_dwEventFilterMask;
  2259. m_dwEventFilterMask = lFilterMask;
  2260. Unlock();
  2261. // Convert lFilterMask to server side 64 bit masks
  2262. // we alway should receive:
  2263. // TE_CALLSTATE,
  2264. // TE_CALLNOTIFICATION,
  2265. // TE_PHONEEVENT
  2266. // TE_CALLHUB
  2267. // TE_CALLINFOCHANGE
  2268. // TE_TAPIOBJECT
  2269. // events because these events are used internally
  2270. // by Tapi3 objets
  2271. ulEventMasks = EM_LINE_CALLSTATE // TE_CALLSTATE
  2272. | EM_LINE_APPNEWCALL // TE_CALLNOTIFICATION
  2273. | EM_PHONE_CLOSE // TE_PHONEEVENT
  2274. | EM_PHONE_STATE // TE_PHONEEVENT
  2275. | EM_PHONE_BUTTONMODE // TE_PHONEEVENT
  2276. | EM_PHONE_BUTTONSTATE // TE_PHONEVENT
  2277. | EM_LINE_APPNEWCALLHUB // TE_CALLHUB
  2278. | EM_LINE_CALLHUBCLOSE // TE_CALLHUB
  2279. | EM_LINE_CALLINFO // TE_CALLINFOCHANGE
  2280. | EM_LINE_CREATE // TE_TAPIOBJECT
  2281. | EM_LINE_REMOVE // TE_TAPIOBJECT
  2282. | EM_LINE_CLOSE // TE_TAPIOBJECT
  2283. | EM_PHONE_CREATE // TE_TAPIOBJECT
  2284. | EM_PHONE_REMOVE // TE_TAPIOBJECT
  2285. ;
  2286. dwLineDevStateSubMasks = LINEDEVSTATE_REINIT // TE_TAPIOBJECT
  2287. | LINEDEVSTATE_TRANSLATECHANGE; // TE_TAPIOBJECT
  2288. dwAddrStateSubMasks = 0;
  2289. if (lFilterMask & TE_ADDRESS)
  2290. {
  2291. // AE_STATE
  2292. dwLineDevStateSubMasks |=
  2293. LINEDEVSTATE_CONNECTED |
  2294. LINEDEVSTATE_INSERVICE |
  2295. LINEDEVSTATE_OUTOFSERVICE |
  2296. LINEDEVSTATE_MAINTENANCE |
  2297. LINEDEVSTATE_REMOVED |
  2298. LINEDEVSTATE_DISCONNECTED |
  2299. LINEDEVSTATE_LOCK;
  2300. // AE_MSGWAITON, AAE_MSGWAITOFF
  2301. dwLineDevStateSubMasks |=
  2302. LINEDEVSTATE_MSGWAITON |
  2303. LINEDEVSTATE_MSGWAITOFF ;
  2304. // AE_CAPSCHANGE
  2305. dwAddrStateSubMasks |=
  2306. LINEADDRESSSTATE_CAPSCHANGE;
  2307. dwLineDevStateSubMasks |=
  2308. LINEDEVSTATE_CAPSCHANGE;
  2309. dwLineDevStateSubMasks |=
  2310. LINEDEVSTATE_RINGING | // AE_RINGING
  2311. LINEDEVSTATE_CONFIGCHANGE; // AE_CONFIGCHANGE
  2312. dwAddrStateSubMasks |=
  2313. LINEADDRESSSTATE_FORWARD; // AE_FORWARD
  2314. // AE_NEWTERMINAL : ignore private MSP events
  2315. // AE_REMOVETERMINAL : ignore private MSP events
  2316. }
  2317. if (lFilterMask & TE_CALLMEDIA)
  2318. {
  2319. // Skil media event
  2320. }
  2321. if (lFilterMask & TE_PRIVATE)
  2322. {
  2323. // skip MSP private event
  2324. }
  2325. if (lFilterMask & TE_REQUEST)
  2326. {
  2327. // LINE_REQUEST is not masked by the server
  2328. }
  2329. if (lFilterMask & TE_AGENT)
  2330. {
  2331. ulEventMasks |= EM_LINE_AGENTSTATUSEX | EM_LINE_AGENTSTATUS;
  2332. }
  2333. if (lFilterMask & TE_AGENTSESSION)
  2334. {
  2335. ulEventMasks |= EM_LINE_AGENTSESSIONSTATUS;
  2336. }
  2337. if (lFilterMask & TE_QOSEVENT)
  2338. {
  2339. ulEventMasks |= EM_LINE_QOSINFO;
  2340. }
  2341. if (lFilterMask & TE_AGENTHANDLER)
  2342. {
  2343. // TAPI 3 client side only?
  2344. }
  2345. if (lFilterMask & TE_ACDGROUP)
  2346. {
  2347. ulEventMasks |= EM_LINE_GROUPSTATUS;
  2348. }
  2349. if (lFilterMask & TE_QUEUE)
  2350. {
  2351. ulEventMasks |= EM_LINE_QUEUESTATUS;
  2352. }
  2353. if (lFilterMask & TE_DIGITEVENT)
  2354. {
  2355. // LINE_MONITORDIGITS not controled by event filtering
  2356. }
  2357. if (lFilterMask & TE_GENERATEEVENT)
  2358. {
  2359. // LINE_GENERATE not controled by event filtering
  2360. }
  2361. if (lFilterMask & TE_TONEEVENT)
  2362. {
  2363. // LINE_MONITORTONE not controled by event filtering
  2364. }
  2365. if (lFilterMask & TE_GATHERDIGITS)
  2366. {
  2367. // LINE_GATHERDIGITS not controled by event filtering
  2368. }
  2369. if (lFilterMask & TE_ADDRESSDEVSPECIFIC)
  2370. {
  2371. ulEventMasks |= EM_LINE_DEVSPECIFICEX | EM_LINE_DEVSPECIFIC;
  2372. }
  2373. if (lFilterMask & TE_PHONEDEVSPECIFIC)
  2374. {
  2375. ulEventMasks |= EM_PHONE_DEVSPECIFIC;
  2376. }
  2377. hr = tapiSetEventFilterMasks (
  2378. TAPIOBJ_NULL,
  2379. NULL,
  2380. ulEventMasks
  2381. );
  2382. if (hr == 0)
  2383. {
  2384. hr = tapiSetEventFilterSubMasks (
  2385. TAPIOBJ_NULL,
  2386. NULL,
  2387. EM_LINE_LINEDEVSTATE,
  2388. dwLineDevStateSubMasks
  2389. );
  2390. }
  2391. if (hr == 0)
  2392. {
  2393. hr = tapiSetEventFilterSubMasks (
  2394. TAPIOBJ_NULL,
  2395. NULL,
  2396. EM_LINE_ADDRESSSTATE,
  2397. dwAddrStateSubMasks
  2398. );
  2399. }
  2400. if (hr != 0)
  2401. {
  2402. hr = mapTAPIErrorCode(hr);
  2403. }
  2404. LOG((TL_INFO, "put_EventFilter - mask changed %x to %x", dwOldFilterMask, lFilterMask ));
  2405. }
  2406. LOG((TL_TRACE,hr, "put_EventFilter - exit "));
  2407. return hr;
  2408. }
  2409. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2410. //
  2411. // get_EventFilter
  2412. //
  2413. // gets the Event filter mask
  2414. //
  2415. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2416. STDMETHODIMP
  2417. CTAPI::get_EventFilter(long * plFilterMask)
  2418. {
  2419. HRESULT hr = S_OK;
  2420. LOG((TL_TRACE, "get_EventFilter - enter"));
  2421. if ( TAPIIsBadWritePtr( plFilterMask, sizeof(long) ) )
  2422. {
  2423. LOG((TL_ERROR, "get_EventFilter - bad plFilterMask pointer"));
  2424. hr = E_POINTER;
  2425. }
  2426. else
  2427. {
  2428. Lock();
  2429. *plFilterMask = m_dwEventFilterMask;
  2430. Unlock();
  2431. }
  2432. LOG((TL_TRACE, hr, "get_EventFilter - exit "));
  2433. return hr;
  2434. }
  2435. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2436. // Interface : ITTAPI2
  2437. // Method : get_Phones
  2438. //
  2439. //
  2440. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2441. HRESULT
  2442. CTAPI::get_Phones(
  2443. VARIANT * pPhones
  2444. )
  2445. {
  2446. HRESULT hr;
  2447. IDispatch * pDisp;
  2448. LOG((TL_TRACE, "get_Phones enter"));
  2449. Lock();
  2450. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ) )
  2451. {
  2452. LOG((TL_ERROR, "get_Phones - tapi object must be initialized first" ));
  2453. Unlock();
  2454. return TAPI_E_NOT_INITIALIZED;
  2455. }
  2456. Unlock();
  2457. if ( TAPIIsBadWritePtr( pPhones, sizeof( VARIANT ) ) )
  2458. {
  2459. LOG((TL_ERROR, "get_Phones - bad pointer"));
  2460. return E_POINTER;
  2461. }
  2462. CComObject< CTapiCollection< ITPhone > > * p;
  2463. CComObject< CTapiCollection< ITPhone > >::CreateInstance( &p );
  2464. if (NULL == p)
  2465. {
  2466. LOG((TL_ERROR, "get_Phones - could not create collection" ));
  2467. return E_OUTOFMEMORY;
  2468. }
  2469. // get the IDispatch interface
  2470. hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp );
  2471. if (S_OK != hr)
  2472. {
  2473. LOG((TL_ERROR, "get_Phones - could not get IDispatch interface" ));
  2474. delete p;
  2475. return hr;
  2476. }
  2477. Lock();
  2478. // initialize
  2479. hr = p->Initialize( m_PhoneArray );
  2480. Unlock();
  2481. if (S_OK != hr)
  2482. {
  2483. LOG((TL_ERROR, "get_Phones - could not initialize collection" ));
  2484. pDisp->Release();
  2485. return hr;
  2486. }
  2487. // put it in the variant
  2488. VariantInit(pPhones);
  2489. pPhones->vt = VT_DISPATCH;
  2490. pPhones->pdispVal = pDisp;
  2491. LOG((TL_TRACE, "get_Phones - exit - return %lx", hr ));
  2492. return hr;
  2493. }
  2494. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2495. // Interface : ITTAPI2
  2496. // Method : EnumeratePhones
  2497. //
  2498. //
  2499. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2500. HRESULT
  2501. CTAPI::EnumeratePhones(
  2502. IEnumPhone ** ppEnumPhone
  2503. )
  2504. {
  2505. HRESULT hr;
  2506. LOG((TL_TRACE, "EnumeratePhones - enter"));
  2507. LOG((TL_TRACE, " ppEnumPhone----->%p", ppEnumPhone ));
  2508. Lock();
  2509. if (!( m_dwFlags & TAPIFLAG_INITIALIZED ) )
  2510. {
  2511. LOG((TL_ERROR, "EnumeratePhones - tapi object must be initialized first" ));
  2512. Unlock();
  2513. return TAPI_E_NOT_INITIALIZED;
  2514. }
  2515. Unlock();
  2516. if ( TAPIIsBadWritePtr( ppEnumPhone, sizeof( IEnumPhone * ) ) )
  2517. {
  2518. LOG((TL_ERROR, "EnumeratePhones - bad pointer"));
  2519. return E_POINTER;
  2520. }
  2521. //
  2522. // create the enumerator
  2523. //
  2524. CComObject< CTapiEnum< IEnumPhone, ITPhone, &IID_IEnumPhone > > * p;
  2525. hr = CComObject< CTapiEnum< IEnumPhone, ITPhone, &IID_IEnumPhone > >
  2526. ::CreateInstance( &p );
  2527. if (S_OK != hr)
  2528. {
  2529. LOG((TL_ERROR, "EnumeratePhones - could not create enum" ));
  2530. return hr;
  2531. }
  2532. Lock();
  2533. // initialize it with our phone list, initialize adds a reference to p
  2534. p->Initialize( m_PhoneArray );
  2535. Unlock();
  2536. //
  2537. // return it
  2538. //
  2539. *ppEnumPhone = p;
  2540. LOG((TL_TRACE, "EnumeratePhones - exit - return %lx", hr ));
  2541. return hr;
  2542. }
  2543. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2544. // Interface : ITTAPI2
  2545. // Method : CreateEmptyCollectionObject
  2546. //
  2547. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2548. STDMETHODIMP
  2549. CTAPI::CreateEmptyCollectionObject(
  2550. ITCollection2 ** ppCollection
  2551. )
  2552. {
  2553. HRESULT hr;
  2554. LOG((TL_TRACE, "CreateEmptyCollectionObject enter"));
  2555. if ( TAPIIsBadWritePtr( ppCollection, sizeof( ITCollection2 * ) ) )
  2556. {
  2557. LOG((TL_ERROR, "CreateEmptyCollectionObject - bad pointer"));
  2558. return E_POINTER;
  2559. }
  2560. // Initialize the return value in case we fail
  2561. *ppCollection = NULL;
  2562. CComObject< CTapiCollection< IDispatch > > * p;
  2563. hr = CComObject< CTapiCollection< IDispatch > >::CreateInstance( &p );
  2564. if ( S_OK != hr )
  2565. {
  2566. LOG((TL_ERROR, "CreateEmptyCollectionObject - could not create CTapiCollection" ));
  2567. return E_OUTOFMEMORY;
  2568. }
  2569. // get the ITCollection2 interface
  2570. hr = p->QueryInterface( IID_ITCollection2, (void **) ppCollection );
  2571. if ( FAILED(hr) )
  2572. {
  2573. LOG((TL_ERROR, "CreateEmptyCollectionObject - could not get ITCollection2 interface" ));
  2574. delete p;
  2575. return hr;
  2576. }
  2577. LOG((TL_TRACE, "CreateEmptyCollectionObject - exit - return %lx", hr ));
  2578. return hr;
  2579. }
  2580. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2581. //
  2582. // DoLineCreate
  2583. //
  2584. // handles line_create message. basically, creates a new
  2585. // address object
  2586. //
  2587. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2588. void
  2589. CTAPI::DoLineCreate( DWORD dwDeviceID )
  2590. {
  2591. HRESULT hr;
  2592. Lock();
  2593. CreateAddressesOnSingleLine( dwDeviceID, TRUE );
  2594. Unlock();
  2595. }
  2596. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2597. //
  2598. // DoLineRemove( DWORD dwDeviceID )
  2599. //
  2600. // tapisrv has sent a LINE_REMOVE message. find the corresponding
  2601. // address object(s), remove them from our list, and send a
  2602. // message to the app
  2603. //
  2604. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2605. void
  2606. CTAPI::DoLineRemove( DWORD dwDeviceID )
  2607. {
  2608. HRESULT hr;
  2609. ITAddress * pAddress;
  2610. CAddress * pCAddress;
  2611. int iCount;
  2612. #if DBG
  2613. BOOL bFound = FALSE;
  2614. #endif
  2615. LOG((TL_TRACE, "DoLineRemove - enter - dwDeviceID %d", dwDeviceID));
  2616. Lock();
  2617. //
  2618. // go through the addresses
  2619. //
  2620. for(iCount = 0; iCount < m_AddressArray.GetSize(); iCount++)
  2621. {
  2622. pAddress = m_AddressArray[iCount];
  2623. pCAddress = dynamic_cast<CAddress *>(pAddress);
  2624. if (pCAddress != NULL)
  2625. {
  2626. //
  2627. // does the device ID match?
  2628. //
  2629. if ( dwDeviceID == pCAddress->GetDeviceID() )
  2630. {
  2631. LOG((TL_INFO, "DoLineRemove - found matching address - %p", pAddress));
  2632. //
  2633. // make sure the address is in the correct state
  2634. //
  2635. pCAddress->OutOfService(LINEDEVSTATE_REMOVED);
  2636. //
  2637. // fire event
  2638. //
  2639. CTapiObjectEvent::FireEvent(
  2640. this,
  2641. TE_ADDRESSREMOVE,
  2642. pAddress,
  2643. 0,
  2644. NULL
  2645. );
  2646. //
  2647. // remove from our list
  2648. //
  2649. LOG((TL_INFO, "DoLineRemove - removing address %p", pAddress));
  2650. m_AddressArray.RemoveAt(iCount);
  2651. iCount--;
  2652. #if DBG
  2653. bFound = TRUE;
  2654. #endif
  2655. }
  2656. }
  2657. }
  2658. #if DBG
  2659. if ( !bFound )
  2660. {
  2661. LOG((TL_WARN, "Receive LINE_REMOVE but couldn't find address object"));
  2662. }
  2663. #endif
  2664. LOG((TL_TRACE, "DoLineRemove - exiting"));
  2665. Unlock();
  2666. }
  2667. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2668. //
  2669. // DoPhoneCreate
  2670. //
  2671. // handles PHONE_CREATE message. basically, creates a new
  2672. // phone object
  2673. //
  2674. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2675. void
  2676. CTAPI::DoPhoneCreate( DWORD dwDeviceID )
  2677. {
  2678. HRESULT hr;
  2679. Lock();
  2680. CreatePhone( dwDeviceID, TRUE );
  2681. Unlock();
  2682. }
  2683. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2684. //
  2685. // DoPhoneRemove( DWORD dwDeviceID )
  2686. //
  2687. // tapisrv has sent a PHONE_REMOVE message. find the corresponding
  2688. // phone object(s), remove them from our list, and send a
  2689. // message to the app
  2690. //
  2691. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2692. void
  2693. CTAPI::DoPhoneRemove( DWORD dwDeviceID )
  2694. {
  2695. HRESULT hr;
  2696. ITPhone * pPhone;
  2697. CPhone * pCPhone;
  2698. int iPhoneCount;
  2699. int iAddressCount;
  2700. #if DBG
  2701. BOOL bFound;
  2702. #endif
  2703. LOG((TL_TRACE, "DoPhoneRemove - enter - dwDeviceID %d", dwDeviceID));
  2704. Lock();
  2705. //
  2706. // go through the phones
  2707. //
  2708. for(iPhoneCount = 0; iPhoneCount < m_PhoneArray.GetSize(); iPhoneCount++)
  2709. {
  2710. pPhone = m_PhoneArray[iPhoneCount];
  2711. pCPhone = dynamic_cast<CPhone *>(pPhone);
  2712. if (NULL == pCPhone)
  2713. {
  2714. //
  2715. // something went terribly wrong
  2716. //
  2717. LOG((TL_ERROR, "DoPhoneRemove - failed to cast ptr %p to a phone object", pPhone));
  2718. _ASSERTE(FALSE);
  2719. continue;
  2720. }
  2721. //
  2722. // does the device ID match?
  2723. //
  2724. if ( dwDeviceID == pCPhone->GetDeviceID() )
  2725. {
  2726. LOG((TL_INFO, "DoPhoneRemove - found matching phone - %p", pPhone));
  2727. //
  2728. // fire event
  2729. //
  2730. CTapiObjectEvent::FireEvent(this,
  2731. TE_PHONEREMOVE,
  2732. NULL,
  2733. 0,
  2734. pPhone
  2735. );
  2736. //
  2737. // remove from our list
  2738. //
  2739. LOG((TL_INFO, "DoPhoneRemove - removing phone %p", pPhone));
  2740. m_PhoneArray.RemoveAt(iPhoneCount);
  2741. iPhoneCount--;
  2742. #if DBG
  2743. bFound = TRUE;
  2744. #endif
  2745. }
  2746. }
  2747. #if DBG
  2748. if ( !bFound )
  2749. {
  2750. LOG((TL_WARN, "Receive PHONE_REMOVE but couldn't find phone object"));
  2751. }
  2752. #endif
  2753. LOG((TL_TRACE, "DoPhoneRemove - exiting"));
  2754. Unlock();
  2755. }
  2756. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2757. //
  2758. //
  2759. //
  2760. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2761. BOOL
  2762. CTAPI::FindTapiObject( CTAPI * pTapi )
  2763. {
  2764. PtrList::iterator iter, end;
  2765. BOOL bFound = FALSE;
  2766. int iReturn = -1;
  2767. EnterCriticalSection( &gcsTapiObjectArray );
  2768. //
  2769. // go through the list
  2770. //
  2771. iReturn = m_sTAPIObjectArray.Find( pTapi );
  2772. if (iReturn != -1)
  2773. {
  2774. pTapi->AddRef();
  2775. bFound = TRUE;
  2776. }
  2777. LeaveCriticalSection ( &gcsTapiObjectArray );
  2778. return bFound;
  2779. }
  2780. ////////////////////////////////////////////////////////////////////////////
  2781. //
  2782. // GetTapiObjectFromAsyncEventMSG
  2783. //
  2784. // this method attempts to get tapi object pointer from PASYNCEVENTMSG
  2785. //
  2786. // it returns NULL on failure or addref'ed tapi object on success
  2787. //
  2788. ////////////////////////////////////////////////////////////////////////////
  2789. CTAPI *GetTapiObjectFromAsyncEventMSG(PASYNCEVENTMSG pParams)
  2790. {
  2791. LOG((TL_TRACE, "GetTapiObjectFromAsyncEventMSG - entered"));
  2792. //
  2793. // get pInitData from the structure we have
  2794. //
  2795. PT3INIT_DATA pInitData = (PT3INIT_DATA) GetHandleTableEntry(pParams->InitContext);
  2796. if (IsBadReadPtr(pInitData, sizeof(T3INIT_DATA)))
  2797. {
  2798. LOG((TL_WARN, "GetTapiObjectFromAsyncEventMSG - could not recover pInitData"));
  2799. return NULL;
  2800. }
  2801. //
  2802. // get tapi object from pInitData
  2803. //
  2804. CTAPI *pTapi = pInitData->pTAPI;
  2805. //
  2806. // is it any good?
  2807. //
  2808. if (IsBadReadPtr(pTapi, sizeof(CTAPI)))
  2809. {
  2810. LOG((TL_WARN,
  2811. "GetTapiObjectFromAsyncEventMSG - tapi pointer [%p] does not point to readable memory",
  2812. pTapi));
  2813. return NULL;
  2814. }
  2815. //
  2816. // double check that this is a known tapi object...
  2817. //
  2818. if (!CTAPI::FindTapiObject(pTapi))
  2819. {
  2820. //
  2821. // the object is not in the list of tapi objects
  2822. //
  2823. LOG((TL_WARN,
  2824. "GetTapiObjectFromAsyncEventMSG - CTAPI::FindTapiObject did not find the tapi object [%p]",
  2825. pTapi));
  2826. return NULL;
  2827. }
  2828. LOG((TL_TRACE, "GetTapiObjectFromAsyncEventMSG - exit. pTapi %p", pTapi));
  2829. return pTapi;
  2830. }
  2831. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2832. //
  2833. //
  2834. //
  2835. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2836. void
  2837. HandleLineCreate( PASYNCEVENTMSG pParams )
  2838. {
  2839. LOG((TL_TRACE, "HandleLineCreate - enter"));
  2840. //
  2841. // get tapi object
  2842. //
  2843. CTAPI *pTapi = GetTapiObjectFromAsyncEventMSG(pParams);
  2844. if (NULL == pTapi)
  2845. {
  2846. LOG((TL_WARN,
  2847. "HandleLineCreate - tapi object not present [%p]",
  2848. pTapi));
  2849. return;
  2850. }
  2851. //
  2852. // we have tapi object, do what we have to do.
  2853. //
  2854. pTapi->DoLineCreate( pParams->Param1 );
  2855. //
  2856. // GetTapiObjectFromAsyncEventMSG returned a addref'ed tapi object. release
  2857. //
  2858. pTapi->Release();
  2859. pTapi = NULL;
  2860. LOG((TL_TRACE, "HandleLineCreate - exit"));
  2861. }
  2862. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2863. //
  2864. //
  2865. //
  2866. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2867. void
  2868. HandleLineRemove( PASYNCEVENTMSG pParams )
  2869. {
  2870. LOG((TL_TRACE, "HandleLineRemove - enter"));
  2871. //
  2872. // get tapi object
  2873. //
  2874. CTAPI *pTapi = GetTapiObjectFromAsyncEventMSG(pParams);
  2875. if (NULL == pTapi)
  2876. {
  2877. LOG((TL_WARN,
  2878. "HandleLineRemove - tapi object not present [%p]",
  2879. pTapi));
  2880. return;
  2881. }
  2882. //
  2883. // we have tapi object, do what we have to do.
  2884. //
  2885. pTapi->DoLineRemove( pParams->Param1 );
  2886. //
  2887. // GetTapiObjectFromAsyncEventMSG returned a addref'ed tapi object. release
  2888. //
  2889. pTapi->Release();
  2890. pTapi = NULL;
  2891. LOG((TL_TRACE, "HandleLineRemove - exit"));
  2892. }
  2893. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2894. //
  2895. //
  2896. //
  2897. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2898. void
  2899. HandlePhoneCreate( PASYNCEVENTMSG pParams )
  2900. {
  2901. LOG((TL_TRACE, "HandlePhoneCreate - enter"));
  2902. //
  2903. // get tapi object
  2904. //
  2905. CTAPI *pTapi = GetTapiObjectFromAsyncEventMSG(pParams);
  2906. if (NULL == pTapi)
  2907. {
  2908. LOG((TL_WARN,
  2909. "HandlePhoneCreate - tapi object not present [%p]",
  2910. pTapi));
  2911. return;
  2912. }
  2913. //
  2914. // we have tapi object, do what we have to do.
  2915. //
  2916. pTapi->DoPhoneCreate( pParams->Param1 );
  2917. //
  2918. // GetTapiObjectFromAsyncEventMSG returned a addref'ed tapi object. release
  2919. //
  2920. pTapi->Release();
  2921. pTapi = NULL;
  2922. LOG((TL_TRACE, "HandlePhoneCreate - exit"));
  2923. }
  2924. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2925. //
  2926. //
  2927. //
  2928. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2929. void
  2930. HandlePhoneRemove( PASYNCEVENTMSG pParams )
  2931. {
  2932. LOG((TL_TRACE, "HandlePhoneRemove - enter"));
  2933. //
  2934. // get tapi object
  2935. //
  2936. CTAPI *pTapi = GetTapiObjectFromAsyncEventMSG(pParams);
  2937. if (NULL == pTapi)
  2938. {
  2939. LOG((TL_WARN,
  2940. "HandlePhoneRemove - tapi object not present [%p]",
  2941. pTapi));
  2942. return;
  2943. }
  2944. //
  2945. // we have tapi object, do what we have to do.
  2946. //
  2947. pTapi->DoPhoneRemove(pParams->Param1);
  2948. //
  2949. // GetTapiObjectFromAsyncEventMSG returned a addref'ed tapi object. release
  2950. //
  2951. pTapi->Release();
  2952. pTapi = NULL;
  2953. LOG((TL_TRACE, "HandlePhoneRemove - exit"));
  2954. }
  2955. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2956. //
  2957. //
  2958. //
  2959. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  2960. HRESULT
  2961. CTapiObjectEvent::FireEvent(
  2962. CTAPI * pTapi,
  2963. TAPIOBJECT_EVENT Event,
  2964. ITAddress * pAddress,
  2965. long lCallbackInstance,
  2966. ITPhone * pPhone
  2967. )
  2968. {
  2969. HRESULT hr = S_OK;
  2970. CComObject<CTapiObjectEvent> * p;
  2971. IDispatch * pDisp;
  2972. //
  2973. // Check the event filter mask
  2974. // This event is not filtered by TapiSrv because is
  2975. // related with TE_TAPIOBJECT, a specific TAPI3 event.
  2976. //
  2977. DWORD dwEventFilterMask = Event;
  2978. long nTapiEventFilter = 0;
  2979. pTapi->get_EventFilter( &nTapiEventFilter );
  2980. STATICLOG((TL_INFO, " TapiObjectEventMask ---> %ld", dwEventFilterMask ));
  2981. if( !( nTapiEventFilter & TE_TAPIOBJECT))
  2982. {
  2983. STATICLOG((TL_WARN, "FireEvent - filtering out this event [%lx]", Event));
  2984. return S_OK;
  2985. }
  2986. //
  2987. // create event
  2988. //
  2989. hr = CComObject<CTapiObjectEvent>::CreateInstance( &p );
  2990. if ( !SUCCEEDED(hr) )
  2991. {
  2992. STATICLOG((TL_ERROR, "Could not create TapiObjectEvent object - %lx", hr));
  2993. return hr;
  2994. }
  2995. //
  2996. // initialize
  2997. //
  2998. p->m_Event = Event;
  2999. p->m_pTapi = dynamic_cast<ITTAPI *>(pTapi);
  3000. p->m_pTapi->AddRef();
  3001. p->m_pAddress = pAddress;
  3002. p->m_lCallbackInstance = lCallbackInstance;
  3003. p->m_pPhone = pPhone;
  3004. if ( NULL != pAddress )
  3005. {
  3006. pAddress->AddRef();
  3007. }
  3008. if ( NULL != pPhone )
  3009. {
  3010. pPhone->AddRef();
  3011. }
  3012. #if DBG
  3013. p->m_pDebug = (PWSTR) ClientAlloc( 1 );
  3014. #endif
  3015. //
  3016. // get idisp interface
  3017. //
  3018. hr = p->QueryInterface(
  3019. IID_IDispatch,
  3020. (void **)&pDisp
  3021. );
  3022. if ( !SUCCEEDED(hr) )
  3023. {
  3024. STATICLOG((TL_ERROR, "Could not get disp interface of TapiObjectEvent object %lx", hr));
  3025. delete p;
  3026. return hr;
  3027. }
  3028. //
  3029. // fire event
  3030. //
  3031. pTapi->Event(
  3032. TE_TAPIOBJECT,
  3033. pDisp
  3034. );
  3035. //
  3036. // release stuff
  3037. //
  3038. pDisp->Release();
  3039. return S_OK;
  3040. }
  3041. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3042. //
  3043. //
  3044. //
  3045. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3046. void
  3047. CTapiObjectEvent::FinalRelease(void)
  3048. {
  3049. m_pTapi->Release();
  3050. if ( NULL != m_pAddress )
  3051. {
  3052. m_pAddress->Release();
  3053. }
  3054. if ( NULL != m_pPhone )
  3055. {
  3056. m_pPhone->Release();
  3057. }
  3058. #if DBG
  3059. ClientFree( m_pDebug );
  3060. #endif
  3061. }
  3062. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3063. //
  3064. //
  3065. //
  3066. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3067. STDMETHODIMP
  3068. CTapiObjectEvent::get_TAPIObject( ITTAPI ** ppTapi )
  3069. {
  3070. if ( TAPIIsBadWritePtr( ppTapi, sizeof( ITTAPI *) ) )
  3071. {
  3072. return E_POINTER;
  3073. }
  3074. *ppTapi = m_pTapi;
  3075. (*ppTapi)->AddRef();
  3076. return S_OK;
  3077. }
  3078. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3079. //
  3080. //
  3081. //
  3082. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3083. STDMETHODIMP
  3084. CTapiObjectEvent::get_Event( TAPIOBJECT_EVENT * pEvent )
  3085. {
  3086. if ( TAPIIsBadWritePtr( pEvent, sizeof( TAPIOBJECT_EVENT ) ) )
  3087. {
  3088. return E_POINTER;
  3089. }
  3090. *pEvent = m_Event;
  3091. return S_OK;
  3092. }
  3093. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3094. //
  3095. //
  3096. //
  3097. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3098. STDMETHODIMP
  3099. CTapiObjectEvent::get_Address( ITAddress ** ppAddress )
  3100. {
  3101. if ( TAPIIsBadWritePtr( ppAddress, sizeof( ITAddress *) ) )
  3102. {
  3103. return E_POINTER;
  3104. }
  3105. if ((m_Event != TE_ADDRESSCREATE) && (m_Event != TE_ADDRESSREMOVE) &&
  3106. (m_Event != TE_ADDRESSCLOSE))
  3107. {
  3108. return TAPI_E_WRONGEVENT;
  3109. }
  3110. *ppAddress = m_pAddress;
  3111. if ( NULL != m_pAddress )
  3112. {
  3113. m_pAddress->AddRef();
  3114. }
  3115. return S_OK;
  3116. }
  3117. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3118. //
  3119. //
  3120. //
  3121. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3122. STDMETHODIMP
  3123. CTapiObjectEvent::get_CallbackInstance( long * plCallbackInstance )
  3124. {
  3125. if ( TAPIIsBadWritePtr( plCallbackInstance, sizeof( long ) ) )
  3126. {
  3127. return E_POINTER;
  3128. }
  3129. *plCallbackInstance = m_lCallbackInstance;
  3130. return S_OK;
  3131. }
  3132. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3133. //
  3134. // get_Phone
  3135. //
  3136. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3137. STDMETHODIMP
  3138. CTapiObjectEvent::get_Phone(
  3139. ITPhone ** ppPhone
  3140. )
  3141. {
  3142. if ( TAPIIsBadWritePtr( ppPhone , sizeof(ITPhone *) ) )
  3143. {
  3144. return E_POINTER;
  3145. }
  3146. if ((m_Event != TE_PHONECREATE) && (m_Event != TE_PHONEREMOVE))
  3147. {
  3148. return TAPI_E_WRONGEVENT;
  3149. }
  3150. *ppPhone = m_pPhone;
  3151. if ( NULL != m_pPhone )
  3152. {
  3153. m_pPhone->AddRef();
  3154. }
  3155. return S_OK;
  3156. }
  3157. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3158. //
  3159. // HandleReinit
  3160. //
  3161. // we got a reinit message, so go through all the tapi objects, and
  3162. // fire the event
  3163. //
  3164. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3165. void
  3166. CTAPI::HandleReinit()
  3167. {
  3168. LOG((TL_TRACE, "HandleReinit - enter"));
  3169. //
  3170. // Fire the event
  3171. //
  3172. CTapiObjectEvent::FireEvent(
  3173. this,
  3174. TE_REINIT,
  3175. NULL,
  3176. 0,
  3177. NULL
  3178. );
  3179. Lock();
  3180. m_dwFlags |= TAPIFLAG_REINIT;
  3181. Unlock();
  3182. }
  3183. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3184. //
  3185. //
  3186. //
  3187. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3188. HRESULT
  3189. CTAPI::GetBuffer(
  3190. DWORD dwType,
  3191. UINT_PTR pObject,
  3192. LPVOID * ppBuffer
  3193. )
  3194. {
  3195. switch (dwType)
  3196. {
  3197. case BUFFERTYPE_ADDRCAP:
  3198. return m_pAddressCapCache->GetBuffer(
  3199. pObject,
  3200. ppBuffer
  3201. );
  3202. break;
  3203. case BUFFERTYPE_LINEDEVCAP:
  3204. return m_pLineCapCache->GetBuffer(
  3205. pObject,
  3206. ppBuffer
  3207. );
  3208. break;
  3209. case BUFFERTYPE_PHONECAP:
  3210. return m_pPhoneCapCache->GetBuffer(
  3211. pObject,
  3212. ppBuffer
  3213. );
  3214. break;
  3215. default:
  3216. return E_FAIL;
  3217. }
  3218. return E_UNEXPECTED;
  3219. }
  3220. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3221. //
  3222. //
  3223. //
  3224. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3225. HRESULT
  3226. CTAPI::SetBuffer(
  3227. DWORD dwType,
  3228. UINT_PTR pObject,
  3229. LPVOID pBuffer
  3230. )
  3231. {
  3232. switch (dwType)
  3233. {
  3234. case BUFFERTYPE_ADDRCAP:
  3235. return m_pAddressCapCache->SetBuffer(
  3236. pObject,
  3237. pBuffer
  3238. );
  3239. break;
  3240. case BUFFERTYPE_LINEDEVCAP:
  3241. return m_pLineCapCache->SetBuffer(
  3242. pObject,
  3243. pBuffer
  3244. );
  3245. break;
  3246. case BUFFERTYPE_PHONECAP:
  3247. return m_pPhoneCapCache->SetBuffer(
  3248. pObject,
  3249. pBuffer
  3250. );
  3251. break;
  3252. default:
  3253. return E_FAIL;
  3254. }
  3255. return E_UNEXPECTED;
  3256. }
  3257. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3258. //
  3259. //
  3260. //
  3261. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3262. HRESULT
  3263. CTAPI::InvalidateBuffer(
  3264. DWORD dwType,
  3265. UINT_PTR pObject
  3266. )
  3267. {
  3268. switch (dwType)
  3269. {
  3270. case BUFFERTYPE_ADDRCAP:
  3271. return m_pAddressCapCache->InvalidateBuffer(
  3272. pObject
  3273. );
  3274. break;
  3275. case BUFFERTYPE_LINEDEVCAP:
  3276. return m_pLineCapCache->InvalidateBuffer(
  3277. pObject
  3278. );
  3279. break;
  3280. case BUFFERTYPE_PHONECAP:
  3281. return m_pPhoneCapCache->InvalidateBuffer(
  3282. pObject
  3283. );
  3284. break;
  3285. default:
  3286. return E_FAIL;
  3287. }
  3288. return E_UNEXPECTED;
  3289. }
  3290. BOOL
  3291. CTAPI::FindRegistration( PVOID pRegistration )
  3292. {
  3293. PtrList::iterator iter, end;
  3294. Lock();
  3295. iter = m_RegisterItemPtrList.begin();
  3296. end = m_RegisterItemPtrList.end();
  3297. for ( ; iter != end; iter++ )
  3298. {
  3299. REGISTERITEM * pItem;
  3300. pItem = (REGISTERITEM *)(*iter);
  3301. if ( pRegistration == pItem->pRegister )
  3302. {
  3303. Unlock();
  3304. return TRUE;
  3305. }
  3306. }
  3307. Unlock();
  3308. return FALSE;
  3309. }
  3310. /////////////////////////////////////////////////////////////////////////////
  3311. // IDispatch implementation
  3312. //
  3313. typedef IDispatchImpl<ITapi2Vtbl<CTAPI>, &IID_ITTAPI2, &LIBID_TAPI3Lib> TapiType;
  3314. typedef IDispatchImpl<ICallCenterVtbl<CTAPI>, &IID_ITTAPICallCenter, &LIBID_TAPI3Lib> CallCenterType;
  3315. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3316. //
  3317. // CTAPI::GetIDsOfNames
  3318. //
  3319. // Overide if IDispatch method
  3320. //
  3321. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3322. STDMETHODIMP CTAPI::GetIDsOfNames(REFIID riid,
  3323. LPOLESTR* rgszNames,
  3324. UINT cNames,
  3325. LCID lcid,
  3326. DISPID* rgdispid
  3327. )
  3328. {
  3329. HRESULT hr = DISP_E_UNKNOWNNAME;
  3330. // See if the requsted method belongs to the default interface
  3331. hr = TapiType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  3332. if (SUCCEEDED(hr))
  3333. {
  3334. LOG((TL_INFO, "GetIDsOfNames - found %S on ITTAPI", *rgszNames));
  3335. rgdispid[0] |= IDISPTAPI;
  3336. return hr;
  3337. }
  3338. // If not, then try the Call Center interface
  3339. hr = CallCenterType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  3340. if (SUCCEEDED(hr))
  3341. {
  3342. LOG((TL_TRACE, "GetIDsOfNames - found %S on ITTAPICallCenter", *rgszNames));
  3343. Lock();
  3344. if (!( m_dwFlags & TAPIFLAG_CALLCENTER_INITIALIZED ) )
  3345. {
  3346. LOG((TL_INFO, "GetIDsOfNames - Call Center not initialized" ));
  3347. UpdateAgentHandlerArray();
  3348. m_dwFlags |= TAPIFLAG_CALLCENTER_INITIALIZED;
  3349. LOG((TL_INFO, "GetIDsOfNames - Call Center initialized" ));
  3350. }
  3351. Unlock();
  3352. rgdispid[0] |= IDISPTAPICALLCENTER;
  3353. return hr;
  3354. }
  3355. LOG((TL_INFO, "GetIDsOfNames - Didn't find %S on our iterfaces", *rgszNames));
  3356. return hr;
  3357. }
  3358. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3359. //
  3360. // CTAPI::Invoke
  3361. //
  3362. // Overide if IDispatch method
  3363. //
  3364. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3365. STDMETHODIMP CTAPI::Invoke(DISPID dispidMember,
  3366. REFIID riid,
  3367. LCID lcid,
  3368. WORD wFlags,
  3369. DISPPARAMS* pdispparams,
  3370. VARIANT* pvarResult,
  3371. EXCEPINFO* pexcepinfo,
  3372. UINT* puArgErr
  3373. )
  3374. {
  3375. HRESULT hr = DISP_E_MEMBERNOTFOUND;
  3376. DWORD dwInterface = (dispidMember & INTERFACEMASK);
  3377. LOG((TL_TRACE, "Invoke - dispidMember %X", dispidMember));
  3378. // Call invoke for the required interface
  3379. switch (dwInterface)
  3380. {
  3381. case IDISPTAPI:
  3382. {
  3383. hr = TapiType::Invoke(dispidMember,
  3384. riid,
  3385. lcid,
  3386. wFlags,
  3387. pdispparams,
  3388. pvarResult,
  3389. pexcepinfo,
  3390. puArgErr
  3391. );
  3392. break;
  3393. }
  3394. case IDISPTAPICALLCENTER:
  3395. {
  3396. hr = CallCenterType::Invoke(dispidMember,
  3397. riid,
  3398. lcid,
  3399. wFlags,
  3400. pdispparams,
  3401. pvarResult,
  3402. pexcepinfo,
  3403. puArgErr
  3404. );
  3405. break;
  3406. }
  3407. } // end switch (dwInterface)
  3408. LOG((TL_TRACE, hr, "Invoke - exit" ));
  3409. return hr;
  3410. }
  3411. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3412. //
  3413. // CTAPI::SetEventFilterToAddresses
  3414. //
  3415. // Copy the event filter down to all addresses
  3416. // It's called by put_EventFilter() method
  3417. //
  3418. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  3419. HRESULT CTAPI::SetEventFilterToAddresses(
  3420. DWORD dwEventFilterMask
  3421. )
  3422. {
  3423. LOG((TL_TRACE, "CopyEventFilterMaskToAddresses enter"));
  3424. CAddress* pAddress = NULL;
  3425. HRESULT hr = S_OK;
  3426. //
  3427. // Enumerate the addresses
  3428. //
  3429. for ( int iAddress = 0; iAddress < m_AddressArray.GetSize(); iAddress++ )
  3430. {
  3431. pAddress = dynamic_cast<CAddress *>(m_AddressArray[iAddress]);
  3432. if( pAddress != NULL )
  3433. {
  3434. hr = pAddress->SetEventFilterMask(
  3435. dwEventFilterMask
  3436. );
  3437. if( FAILED(hr) )
  3438. {
  3439. break;
  3440. }
  3441. }
  3442. }
  3443. LOG((TL_TRACE, "CopyEventFilterMaskToAddresses exit 0x%08x", hr));
  3444. return hr;
  3445. }
  3446. ///////////////////////////////////////////////////////////////////////////////
  3447. //
  3448. // CTAPI::IsValidTapiObject
  3449. //
  3450. // a helper static function that checks if it was passed a valid tapi object
  3451. //
  3452. // if the object is valid, the function addrefs it and returns TRUE
  3453. // if the object is not valid, the function returns true
  3454. //
  3455. // static
  3456. BOOL CTAPI::IsValidTapiObject(CTAPI *pTapiObject)
  3457. {
  3458. STATICLOG((TL_TRACE, "CTAPI::IsValidTapiObject enter[%p]", pTapiObject));
  3459. //
  3460. // before we go into trouble of checking tapi object array see if the ptr
  3461. // is readable at all
  3462. //
  3463. if ( IsBadReadPtr(pTapiObject, sizeof(CTAPI) ) )
  3464. {
  3465. STATICLOG((TL_WARN, "CTAPI::IsValidTapiObject - object not readabe"));
  3466. return FALSE;
  3467. }
  3468. //
  3469. // see if this object is in the array of tapi objects
  3470. //
  3471. EnterCriticalSection( &gcsTapiObjectArray );
  3472. if (-1 == m_sTAPIObjectArray.Find(pTapiObject) )
  3473. {
  3474. LeaveCriticalSection ( &gcsTapiObjectArray );
  3475. STATICLOG((TL_WARN, "CTAPI::IsValidTapiObject - object not in the array"));
  3476. return FALSE;
  3477. }
  3478. //
  3479. // the object is in the array, so it must be valid, addref it
  3480. //
  3481. try
  3482. {
  3483. //
  3484. // inside try, in case something else went bad
  3485. //
  3486. pTapiObject->AddRef();
  3487. }
  3488. catch(...)
  3489. {
  3490. //
  3491. // the object is in the array, but we had problems addrefing.
  3492. // something's not kosher.
  3493. //
  3494. STATICLOG((TL_ERROR,
  3495. "CTAPI::IsValidTapiObject - object in in the array but addref threw"));
  3496. LeaveCriticalSection ( &gcsTapiObjectArray );
  3497. _ASSERTE(FALSE);
  3498. return FALSE;
  3499. }
  3500. LeaveCriticalSection ( &gcsTapiObjectArray );
  3501. STATICLOG((TL_TRACE, "CTAPI::IsValidTapiObject -- finish. the object is valid"));
  3502. return TRUE;
  3503. }