Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5197 lines
132 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. mspaddr.cpp
  5. Abstract:
  6. This module contains implementation of CMSPAddress.
  7. --*/
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. ///////////////////////////////////////////////////////////////////////////////
  11. //
  12. // AllocateEventItem and FreeEventItem are MSPEVENTITEM allocation routines.
  13. // they are be used to allocate and deallocate MSPEVENTITEM structures
  14. //
  15. ///////////////////////////////////////////////////////////////////////////////
  16. //////////////////////////////////////////////////////////////////////////////
  17. //
  18. // AllocateEventItem
  19. //
  20. // allocate an MSPEVENTITEM. Since the structure is of variable size, the
  21. // number of extra bytes to be allocated (in addition to the size of
  22. // MSPEVENTITEM) is optionally passed as the function's argument
  23. //
  24. // the function returns a pointer to the newly created structure or NULL in
  25. // the case of failure. the caller can then call GetLastError to get more
  26. // information on the failure
  27. //
  28. MSPEVENTITEM *AllocateEventItem(SIZE_T nExtraBytes)
  29. {
  30. LOG((MSP_TRACE, "AllocateEventItem - enter, extra bytes = 0x%p", nExtraBytes));
  31. //
  32. // if the caller passes us too big a number, fail.
  33. //
  34. if ( ( MAXULONG_PTR - sizeof(MSPEVENTITEM) ) < nExtraBytes )
  35. {
  36. SetLastError(ERROR_OUTOFMEMORY);
  37. LOG((MSP_ERROR,
  38. "AllocateEventItem - the caller requested an unreasonably large memory block"));
  39. return NULL;
  40. }
  41. //
  42. // allocate on the process' heap. get the current process' heap handle.
  43. //
  44. HANDLE hHeapHandle = GetProcessHeap();
  45. if (NULL == hHeapHandle)
  46. {
  47. //
  48. // failed to get process's heap. nothing much we can do here.
  49. // this will cause a leak.
  50. //
  51. LOG((MSP_ERROR,
  52. "AllocateEventItem - failed to get current process heap. LastError [%ld]",
  53. GetLastError()));
  54. return NULL;
  55. }
  56. //
  57. // calculate the number of bytes to allocate
  58. //
  59. SIZE_T nTotalAllocationSize = sizeof(MSPEVENTITEM) + nExtraBytes;
  60. //
  61. // attempt to allocate memory and return result of the allocation
  62. //
  63. MSPEVENTITEM *pMspEventItem =
  64. (MSPEVENTITEM *)HeapAlloc(hHeapHandle, 0, nTotalAllocationSize);
  65. if (NULL == pMspEventItem)
  66. {
  67. LOG((MSP_ERROR,
  68. "AllocateEventItem - failed to allocate [0x%p] bytes. Heap Handle [%p] LastError [%ld]",
  69. nTotalAllocationSize, hHeapHandle, GetLastError()));
  70. }
  71. else
  72. {
  73. LOG((MSP_TRACE, "AllocateEventItem - exit. pMspEventItem = [%p]", pMspEventItem));
  74. }
  75. return pMspEventItem;
  76. }
  77. //////////////////////////////////////////////////////////////////////////////
  78. //
  79. // FreeEventItem
  80. //
  81. // deallocate the MSPEVENTITEM passed as an argument. The memory must have
  82. // been previously allocated by AllocateEventItem.
  83. //
  84. // the function eturns FALSE in case of failure. The caller can use
  85. // GetLastError to get a more specific error code.
  86. //
  87. BOOL FreeEventItem(MSPEVENTITEM *pEventItemToBeFreed)
  88. {
  89. LOG((MSP_TRACE, "FreeEventItem - enter. pEventItemToBeFreed = [%p]",
  90. pEventItemToBeFreed));
  91. //
  92. // always allow freeing NULL
  93. //
  94. if (NULL == pEventItemToBeFreed)
  95. {
  96. LOG((MSP_TRACE, "FreeEventItem - finish. NULL -- nothing to do"));
  97. return TRUE;
  98. }
  99. //
  100. // the event item should have been allocated on the process' heap.
  101. // get the current process' heap hadle.
  102. //
  103. HANDLE hHeapHandle = GetProcessHeap();
  104. if (NULL == hHeapHandle)
  105. {
  106. //
  107. // failed to get process's heap. nothing much we can do here.
  108. // this will cause a leak.
  109. //
  110. LOG((MSP_ERROR,
  111. "FreeEventItem - failed to get current process heap. LastError = %ld",
  112. GetLastError()));
  113. return FALSE;
  114. }
  115. //
  116. // attempt to free memory and return result of the operation
  117. //
  118. BOOL bFreeSuccess = HeapFree( hHeapHandle, 0, pEventItemToBeFreed );
  119. if (bFreeSuccess)
  120. {
  121. LOG((MSP_TRACE, "FreeEventItem - exit."));
  122. }
  123. else
  124. {
  125. LOG((MSP_ERROR,
  126. "FreeEventItem - failed to free. Heap Handle [%p] LastError = %ld",
  127. hHeapHandle, GetLastError()));
  128. }
  129. return bFreeSuccess;
  130. }
  131. //////////////////////////////////////////////////////////////////////////////
  132. HRESULT CPlugTerminalClassInfo::FinalConstruct(void)
  133. {
  134. LOG((MSP_TRACE, "CPlugTerminalClassInfo::FinalConstruct - enter"));
  135. HRESULT hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(),
  136. & m_pFTM );
  137. if ( FAILED(hr) )
  138. {
  139. LOG((MSP_ERROR, "CPlugTerminalClassInfo::FinalConstruct - "
  140. "create FTM returned 0x%08x; exit", hr));
  141. return hr;
  142. }
  143. LOG((MSP_TRACE, "CPlugTerminalClassInfo::FinalConstruct - exit S_OK"));
  144. return S_OK;
  145. }
  146. //////////////////////////////////////////////////////////////////////////////
  147. STDMETHODIMP CPlugTerminalClassInfo::get_Name(
  148. /*[out, retval]*/ BSTR* pName
  149. )
  150. {
  151. //
  152. // Critical section
  153. //
  154. CLock lock(m_CritSect);
  155. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_Name - enter"));
  156. //
  157. // Validates argument
  158. //
  159. if( MSPB_IsBadWritePtr( pName, sizeof(BSTR)) )
  160. {
  161. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_Name exit -"
  162. "pName invalid, returns E_POINTER"));
  163. return E_POINTER;
  164. }
  165. //
  166. // Validates the name
  167. //
  168. if( IsBadStringPtr( m_bstrName, (UINT)-1) )
  169. {
  170. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_Name exit -"
  171. "m_bstrName invalid, returns E_UNEXPECTED"));
  172. return E_UNEXPECTED;
  173. }
  174. //
  175. // Return the name
  176. //
  177. *pName = SysAllocString( m_bstrName );
  178. //
  179. // Validates SysAllocString
  180. //
  181. if( *pName == NULL )
  182. {
  183. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_Name exit -"
  184. "SysAllocString failed, returns E_OUTOFMEMORY"));
  185. return E_OUTOFMEMORY;
  186. }
  187. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_Name - exit"));
  188. return S_OK;
  189. }
  190. //////////////////////////////////////////////////////////////////////////////
  191. STDMETHODIMP CPlugTerminalClassInfo::put_Name(
  192. /*[in]*/ BSTR bstrName
  193. )
  194. {
  195. //
  196. // Critical section
  197. //
  198. CLock lock(m_CritSect);
  199. LOG((MSP_TRACE, "CPlugTerminalClassInfo::put_Name - enter"));
  200. //
  201. // Validates argument
  202. //
  203. if(IsBadStringPtr( bstrName, (UINT)-1) )
  204. {
  205. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_Name exit -"
  206. "bstrName invalid, returns E_POINTER"));
  207. return E_POINTER;
  208. }
  209. //
  210. // Clean-up the old name
  211. //
  212. if(!IsBadStringPtr( m_bstrName, (UINT)-1) )
  213. {
  214. SysFreeString( m_bstrName );
  215. m_bstrName = NULL;
  216. }
  217. //
  218. // Set the new name
  219. //
  220. m_bstrName = SysAllocString( bstrName );
  221. //
  222. // Validates SysAllocString
  223. //
  224. if( NULL == m_bstrName )
  225. {
  226. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_Name exit -"
  227. "SysAllocString failed, returns E_OUTOFMEMORY"));
  228. return E_OUTOFMEMORY;
  229. }
  230. LOG((MSP_TRACE, "CPlugTerminalClassInfo::put_Name - exit"));
  231. return S_OK;
  232. }
  233. //////////////////////////////////////////////////////////////////////////////
  234. STDMETHODIMP CPlugTerminalClassInfo::get_Company(
  235. /*[out, retval]*/ BSTR* pCompany
  236. )
  237. {
  238. //
  239. // Critical section
  240. //
  241. CLock lock(m_CritSect);
  242. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_Company - enter"));
  243. //
  244. // Validates argument
  245. //
  246. if( MSPB_IsBadWritePtr( pCompany, sizeof(BSTR)) )
  247. {
  248. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_Company exit -"
  249. "pCompany invalid, returns E_POINTER"));
  250. return E_POINTER;
  251. }
  252. //
  253. // Validates the name
  254. //
  255. if( IsBadStringPtr( m_bstrCompany, (UINT)-1) )
  256. {
  257. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_Company exit -"
  258. "m_bstrName invalid, returns E_UNEXPECTED"));
  259. return E_UNEXPECTED;
  260. }
  261. //
  262. // Return the name
  263. //
  264. *pCompany = SysAllocString( m_bstrCompany );
  265. //
  266. // Validates SysAllocString
  267. //
  268. if( *pCompany == NULL )
  269. {
  270. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_Company exit -"
  271. "SysAllocString failed, returns E_OUTOFMEMORY"));
  272. return E_OUTOFMEMORY;
  273. }
  274. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_Company - exit"));
  275. return S_OK;
  276. }
  277. //////////////////////////////////////////////////////////////////////////////
  278. STDMETHODIMP CPlugTerminalClassInfo::put_Company(
  279. /*[in]*/ BSTR bstrCompany
  280. )
  281. {
  282. //
  283. // Critical section
  284. //
  285. CLock lock(m_CritSect);
  286. LOG((MSP_TRACE, "CPlugTerminalClassInfo::put_Company - enter"));
  287. //
  288. // Validates argument
  289. //
  290. if(IsBadStringPtr( bstrCompany, (UINT)-1) )
  291. {
  292. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_Company exit -"
  293. "bstrCompany invalid, returns E_POINTER"));
  294. return E_POINTER;
  295. }
  296. //
  297. // Clean-up the old name
  298. //
  299. if(!IsBadStringPtr( m_bstrCompany, (UINT)-1) )
  300. {
  301. SysFreeString( m_bstrCompany );
  302. m_bstrCompany = NULL;
  303. }
  304. //
  305. // Set the new name
  306. //
  307. m_bstrCompany = SysAllocString( bstrCompany );
  308. //
  309. // Validates SysAllocString
  310. //
  311. if( NULL == m_bstrCompany )
  312. {
  313. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_Company exit -"
  314. "SysAllocString failed, returns E_OUTOFMEMORY"));
  315. return E_OUTOFMEMORY;
  316. }
  317. LOG((MSP_TRACE, "CPlugTerminalClassInfo::put_Company - exit"));
  318. return S_OK;
  319. }
  320. //////////////////////////////////////////////////////////////////////////////
  321. STDMETHODIMP CPlugTerminalClassInfo::get_Version(
  322. /*[out, retval]*/ BSTR* pVersion
  323. )
  324. {
  325. //
  326. // Critical section
  327. //
  328. CLock lock(m_CritSect);
  329. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_Version - enter"));
  330. //
  331. // Validates argument
  332. //
  333. if( MSPB_IsBadWritePtr( pVersion, sizeof(BSTR)) )
  334. {
  335. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_Version exit -"
  336. "pVersion invalid, returns E_POINTER"));
  337. return E_POINTER;
  338. }
  339. //
  340. // Validates the name
  341. //
  342. if( IsBadStringPtr( m_bstrVersion, (UINT)-1) )
  343. {
  344. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_Version exit -"
  345. "m_bstrName invalid, returns E_UNEXPECTED"));
  346. return E_UNEXPECTED;
  347. }
  348. //
  349. // Return the name
  350. //
  351. *pVersion = SysAllocString( m_bstrVersion );
  352. //
  353. // Validates SysAllocString
  354. //
  355. if( *pVersion == NULL )
  356. {
  357. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_Version exit -"
  358. "SysAllocString failed, returns E_OUTOFMEMORY"));
  359. return E_OUTOFMEMORY;
  360. }
  361. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_Version - exit"));
  362. return S_OK;
  363. }
  364. //////////////////////////////////////////////////////////////////////////////
  365. STDMETHODIMP CPlugTerminalClassInfo::put_Version(
  366. /*[in]*/ BSTR bstrVersion
  367. )
  368. {
  369. //
  370. // Critical section
  371. //
  372. CLock lock(m_CritSect);
  373. LOG((MSP_TRACE, "CPlugTerminalClassInfo::put_Version - enter"));
  374. //
  375. // Validates argument
  376. //
  377. if(IsBadStringPtr( bstrVersion, (UINT)-1) )
  378. {
  379. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_Version exit -"
  380. "bstrVersion invalid, returns E_POINTER"));
  381. return E_POINTER;
  382. }
  383. //
  384. // Clean-up the old name
  385. //
  386. if(!IsBadStringPtr( m_bstrVersion, (UINT)-1) )
  387. {
  388. SysFreeString( m_bstrVersion );
  389. m_bstrVersion = NULL;
  390. }
  391. //
  392. // Set the new name
  393. //
  394. m_bstrVersion = SysAllocString( bstrVersion );
  395. //
  396. // Validates SysAllocString
  397. //
  398. if( NULL == m_bstrVersion )
  399. {
  400. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_Version exit -"
  401. "SysAllocString failed, returns E_OUTOFMEMORY"));
  402. return E_OUTOFMEMORY;
  403. }
  404. LOG((MSP_TRACE, "CPlugTerminalClassInfo::put_Version - exit"));
  405. return S_OK;
  406. }
  407. //////////////////////////////////////////////////////////////////////////////
  408. STDMETHODIMP CPlugTerminalClassInfo::get_TerminalClass(
  409. /*[out, retval]*/ BSTR* pTerminalClass
  410. )
  411. {
  412. //
  413. // Critical section
  414. //
  415. CLock lock(m_CritSect);
  416. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_TerminalClass - enter"));
  417. //
  418. // Validates argument
  419. //
  420. if( MSPB_IsBadWritePtr( pTerminalClass, sizeof(BSTR)) )
  421. {
  422. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_TerminalClass exit -"
  423. "pVersion invalid, returns E_POINTER"));
  424. return E_POINTER;
  425. }
  426. //
  427. // Validates the name
  428. //
  429. if( IsBadStringPtr( m_bstrTerminalClass, (UINT)-1) )
  430. {
  431. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_TerminalClass exit -"
  432. "m_bstrName invalid, returns E_UNEXPECTED"));
  433. return E_UNEXPECTED;
  434. }
  435. //
  436. // Return the name
  437. //
  438. *pTerminalClass = SysAllocString( m_bstrTerminalClass );
  439. //
  440. // Validates SysAllocString
  441. //
  442. if( *pTerminalClass == NULL )
  443. {
  444. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_TerminalClass exit -"
  445. "SysAllocString failed, returns E_OUTOFMEMORY"));
  446. return E_OUTOFMEMORY;
  447. }
  448. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_TerminalClass - exit"));
  449. return S_OK;
  450. }
  451. //////////////////////////////////////////////////////////////////////////////
  452. STDMETHODIMP CPlugTerminalClassInfo::put_TerminalClass(
  453. /*[in]*/ BSTR bstrTerminalClass
  454. )
  455. {
  456. //
  457. // Critical section
  458. //
  459. CLock lock(m_CritSect);
  460. LOG((MSP_TRACE, "CPlugTerminalClassInfo::put_TerminalClass - enter"));
  461. //
  462. // Validates argument
  463. //
  464. if(IsBadStringPtr( bstrTerminalClass, (UINT)-1) )
  465. {
  466. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_TerminalClass exit -"
  467. "bstrTerminalClass invalid, returns E_POINTER"));
  468. return E_POINTER;
  469. }
  470. //
  471. // Is a real CLSID?
  472. //
  473. CLSID clsid;
  474. HRESULT hr = CLSIDFromString(bstrTerminalClass, &clsid);
  475. if( FAILED(hr) )
  476. {
  477. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_TerminalClass exit -"
  478. "bstrTerminalClass is not a CLSID, returns E_INVALIDARG"));
  479. return E_INVALIDARG;
  480. }
  481. //
  482. // Clean-up the old name
  483. //
  484. if(!IsBadStringPtr( m_bstrTerminalClass, (UINT)-1) )
  485. {
  486. SysFreeString( m_bstrTerminalClass );
  487. m_bstrTerminalClass = NULL;
  488. }
  489. //
  490. // Set the new name
  491. //
  492. m_bstrTerminalClass = SysAllocString( bstrTerminalClass );
  493. //
  494. // Validates SysAllocString
  495. //
  496. if( NULL == m_bstrTerminalClass )
  497. {
  498. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_TerminalClass exit -"
  499. "SysAllocString failed, returns E_OUTOFMEMORY"));
  500. return E_OUTOFMEMORY;
  501. }
  502. LOG((MSP_TRACE, "CPlugTerminalClassInfo::put_TerminalClass - exit"));
  503. return S_OK;
  504. }
  505. //////////////////////////////////////////////////////////////////////////////
  506. STDMETHODIMP CPlugTerminalClassInfo::get_CLSID(
  507. /*[out, retval]*/ BSTR* pCLSID
  508. )
  509. {
  510. //
  511. // Critical section
  512. //
  513. CLock lock(m_CritSect);
  514. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_CLSID - enter"));
  515. //
  516. // Validates argument
  517. //
  518. if( MSPB_IsBadWritePtr( pCLSID, sizeof(BSTR)) )
  519. {
  520. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_CLSID exit -"
  521. "pVersion invalid, returns E_POINTER"));
  522. return E_POINTER;
  523. }
  524. //
  525. // Validates the name
  526. //
  527. if( IsBadStringPtr( m_bstrCLSID, (UINT)-1) )
  528. {
  529. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_CLSID exit -"
  530. "m_bstrName invalid, returns E_UNEXPECTED"));
  531. return E_UNEXPECTED;
  532. }
  533. //
  534. // Return the name
  535. //
  536. *pCLSID = SysAllocString( m_bstrCLSID );
  537. //
  538. // Validates SysAllocString
  539. //
  540. if( *pCLSID == NULL )
  541. {
  542. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_CLSID exit -"
  543. "SysAllocString failed, returns E_OUTOFMEMORY"));
  544. return E_OUTOFMEMORY;
  545. }
  546. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_CLSID - exit"));
  547. return S_OK;
  548. }
  549. //////////////////////////////////////////////////////////////////////////////
  550. STDMETHODIMP CPlugTerminalClassInfo::put_CLSID(
  551. /*[in]*/ BSTR bstrCLSID
  552. )
  553. {
  554. //
  555. // Critical section
  556. //
  557. CLock lock(m_CritSect);
  558. LOG((MSP_TRACE, "CPlugTerminalClassInfo::put_CLSID - enter"));
  559. //
  560. // Validates argument
  561. //
  562. if(IsBadStringPtr( bstrCLSID, (UINT)-1) )
  563. {
  564. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_CLSID exit -"
  565. "bstrCLSID invalid, returns E_POINTER"));
  566. return E_POINTER;
  567. }
  568. //
  569. // Is a real CLSID?
  570. //
  571. CLSID clsid;
  572. HRESULT hr = CLSIDFromString(bstrCLSID, &clsid);
  573. if( FAILED(hr) )
  574. {
  575. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_CLSID exit -"
  576. "bstrCLSID is not a CLSID, returns E_INVALIDARG"));
  577. return E_INVALIDARG;
  578. }
  579. //
  580. // Clean-up the old name
  581. //
  582. if(!IsBadStringPtr( m_bstrCLSID, (UINT)-1) )
  583. {
  584. SysFreeString( m_bstrCLSID );
  585. m_bstrCLSID = NULL;
  586. }
  587. //
  588. // Set the new name
  589. //
  590. m_bstrCLSID = SysAllocString( bstrCLSID );
  591. //
  592. // Validates SysAllocString
  593. //
  594. if( NULL == m_bstrCLSID )
  595. {
  596. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_CLSID exit -"
  597. "SysAllocString failed, returns E_OUTOFMEMORY"));
  598. return E_OUTOFMEMORY;
  599. }
  600. LOG((MSP_TRACE, "CPlugTerminalClassInfo::put_CLSID - exit"));
  601. return S_OK;
  602. }
  603. //////////////////////////////////////////////////////////////////////////////
  604. STDMETHODIMP CPlugTerminalClassInfo::get_Direction(
  605. /*[out, retval]*/ TERMINAL_DIRECTION* pDirection
  606. )
  607. {
  608. //
  609. // Critical section
  610. //
  611. CLock lock(m_CritSect);
  612. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_Direction - enter"));
  613. //
  614. // Validates argument
  615. //
  616. if( MSPB_IsBadWritePtr( pDirection, sizeof(long)) )
  617. {
  618. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_Direction exit -"
  619. "pDirection invalid, returns E_POINTER"));
  620. return E_POINTER;
  621. }
  622. //
  623. // Return the name
  624. //
  625. *pDirection = m_Direction;
  626. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_Direction - exit"));
  627. return S_OK;
  628. }
  629. //////////////////////////////////////////////////////////////////////////////
  630. STDMETHODIMP CPlugTerminalClassInfo::put_Direction(
  631. /*[in]*/ TERMINAL_DIRECTION nDirection
  632. )
  633. {
  634. //
  635. // Critical section
  636. //
  637. CLock lock(m_CritSect);
  638. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::put_Direction - enter"));
  639. //
  640. // Set the new name
  641. //
  642. m_Direction = nDirection;
  643. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::put_Direction - exit"));
  644. return S_OK;
  645. }
  646. //////////////////////////////////////////////////////////////////////////////
  647. STDMETHODIMP CPlugTerminalClassInfo::get_MediaTypes(
  648. /*[out, retval]*/ long* pMediaTypes
  649. )
  650. {
  651. //
  652. // Critical section
  653. //
  654. CLock lock(m_CritSect);
  655. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_MediaTypes - enter"));
  656. //
  657. // Validates argument
  658. //
  659. if( MSPB_IsBadWritePtr( pMediaTypes, sizeof(long)) )
  660. {
  661. LOG((MSP_ERROR, "CPlugTerminalClassInfo::get_MediaTypes exit -"
  662. "pMediaTypes invalid, returns E_POINTER"));
  663. return E_POINTER;
  664. }
  665. //
  666. // Return the name
  667. //
  668. *pMediaTypes = m_lMediaType;
  669. LOG((MSP_TRACE, "CPlugTerminalClassInfo::get_MediaTypes - exit"));
  670. return S_OK;
  671. }
  672. //////////////////////////////////////////////////////////////////////////////
  673. STDMETHODIMP CPlugTerminalClassInfo::put_MediaTypes(
  674. /*[in]*/ long nMediaTypes
  675. )
  676. {
  677. //
  678. // Critical section
  679. //
  680. CLock lock(m_CritSect);
  681. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::put_MediaTypes - enter"));
  682. //
  683. // Set the new name
  684. //
  685. m_lMediaType = nMediaTypes;
  686. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::put_MediaTypes - exit"));
  687. return S_OK;
  688. }
  689. //////////////////////////////////////////////////////////////////////////////
  690. HRESULT CPlugTerminalSuperclassInfo::FinalConstruct(void)
  691. {
  692. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::FinalConstruct - enter"));
  693. HRESULT hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(),
  694. & m_pFTM );
  695. if ( FAILED(hr) )
  696. {
  697. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::FinalConstruct - "
  698. "create FTM returned 0x%08x; exit", hr));
  699. return hr;
  700. }
  701. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::FinalConstruct - exit S_OK"));
  702. return S_OK;
  703. }
  704. //////////////////////////////////////////////////////////////////////////////
  705. STDMETHODIMP CPlugTerminalSuperclassInfo::get_Name(
  706. /*[out, retval]*/ BSTR* pName
  707. )
  708. {
  709. //
  710. // Critical section
  711. //
  712. CLock lock(m_CritSect);
  713. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::get_Name - enter"));
  714. //
  715. // Validates argument
  716. //
  717. if( MSPB_IsBadWritePtr( pName, sizeof(BSTR)) )
  718. {
  719. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::get_Name exit -"
  720. "pVersion invalid, returns E_POINTER"));
  721. return E_POINTER;
  722. }
  723. //
  724. // Validates the name
  725. //
  726. if( IsBadStringPtr( m_bstrName, (UINT)-1) )
  727. {
  728. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::get_Name exit -"
  729. "m_bstrName invalid, returns E_UNEXPECTED"));
  730. return E_UNEXPECTED;
  731. }
  732. //
  733. // Return the name
  734. //
  735. *pName = SysAllocString( m_bstrName );
  736. //
  737. // Validates SysAllocString
  738. //
  739. if( *pName == NULL )
  740. {
  741. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::get_Name exit -"
  742. "SysAllocString failed, returns E_OUTOFMEMORY"));
  743. return E_OUTOFMEMORY;
  744. }
  745. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::get_Name - exit"));
  746. return S_OK;
  747. }
  748. //////////////////////////////////////////////////////////////////////////////
  749. STDMETHODIMP CPlugTerminalSuperclassInfo::put_Name(
  750. /*[in]*/ BSTR bstrName
  751. )
  752. {
  753. //
  754. // Critical section
  755. //
  756. CLock lock(m_CritSect);
  757. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::put_Name - enter"));
  758. //
  759. // Validates argument
  760. //
  761. if(IsBadStringPtr( bstrName, (UINT)-1) )
  762. {
  763. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::put_Name exit -"
  764. "bstrName invalid, returns E_POINTER"));
  765. return E_POINTER;
  766. }
  767. //
  768. // Clean-up the old name
  769. //
  770. if(!IsBadStringPtr( m_bstrName, (UINT)-1) )
  771. {
  772. SysFreeString( m_bstrName );
  773. m_bstrName = NULL;
  774. }
  775. //
  776. // Set the new name
  777. //
  778. m_bstrName = SysAllocString( bstrName );
  779. //
  780. // Validates SysAllocString
  781. //
  782. if( NULL == m_bstrName )
  783. {
  784. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::put_Name exit -"
  785. "SysAllocString failed, returns E_OUTOFMEMORY"));
  786. return E_OUTOFMEMORY;
  787. }
  788. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::put_Name - exit"));
  789. return S_OK;
  790. }
  791. //////////////////////////////////////////////////////////////////////////////
  792. STDMETHODIMP CPlugTerminalSuperclassInfo::get_CLSID(
  793. /*[out, retval]*/ BSTR* pCLSID
  794. )
  795. {
  796. //
  797. // Critical section
  798. //
  799. CLock lock(m_CritSect);
  800. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::get_CLSID - enter"));
  801. //
  802. // Validates argument
  803. //
  804. if( MSPB_IsBadWritePtr( pCLSID, sizeof(BSTR)) )
  805. {
  806. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::get_CLSID exit -"
  807. "pVersion invalid, returns E_POINTER"));
  808. return E_POINTER;
  809. }
  810. //
  811. // Validates the name
  812. //
  813. if( IsBadStringPtr( m_bstrCLSID, (UINT)-1) )
  814. {
  815. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::get_CLSID exit -"
  816. "m_bstrName invalid, returns E_UNEXPECTED"));
  817. return E_UNEXPECTED;
  818. }
  819. //
  820. // Return the name
  821. //
  822. *pCLSID = SysAllocString( m_bstrCLSID );
  823. //
  824. // Validates SysAllocString
  825. //
  826. if( *pCLSID == NULL )
  827. {
  828. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::get_CLSID exit -"
  829. "SysAllocString failed, returns E_OUTOFMEMORY"));
  830. return E_OUTOFMEMORY;
  831. }
  832. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::get_CLSID - exit"));
  833. return S_OK;
  834. }
  835. //////////////////////////////////////////////////////////////////////////////
  836. STDMETHODIMP CPlugTerminalSuperclassInfo::put_CLSID(
  837. /*[in]*/ BSTR bstrCLSID
  838. )
  839. {
  840. //
  841. // Critical section
  842. //
  843. CLock lock(m_CritSect);
  844. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::put_CLSID - enter"));
  845. //
  846. // Validates argument
  847. //
  848. if(IsBadStringPtr( bstrCLSID, (UINT)-1) )
  849. {
  850. LOG((MSP_ERROR, "CPlugTerminalClassInfo::put_CLSID exit -"
  851. "bstrCLSID invalid, returns E_POINTER"));
  852. return E_POINTER;
  853. }
  854. //
  855. // Is a real CLSID?
  856. //
  857. CLSID clsid;
  858. HRESULT hr = CLSIDFromString(bstrCLSID, &clsid);
  859. if( FAILED(hr) )
  860. {
  861. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::put_CLSID exit -"
  862. "bstrCLSID is not a CLSID, returns E_INVALIDARG"));
  863. return E_INVALIDARG;
  864. }
  865. //
  866. // Clean-up the old name
  867. //
  868. if(!IsBadStringPtr( m_bstrCLSID, (UINT)-1) )
  869. {
  870. SysFreeString( m_bstrCLSID );
  871. m_bstrCLSID = NULL;
  872. }
  873. //
  874. // Set the new name
  875. //
  876. m_bstrCLSID = SysAllocString( bstrCLSID );
  877. //
  878. // Validates SysAllocString
  879. //
  880. if( NULL == m_bstrCLSID )
  881. {
  882. LOG((MSP_ERROR, "CPlugTerminalSuperclassInfo::put_CLSID exit -"
  883. "SysAllocString failed, returns E_OUTOFMEMORY"));
  884. return E_OUTOFMEMORY;
  885. }
  886. LOG((MSP_TRACE, "CPlugTerminalSuperclassInfo::put_CLSID - exit"));
  887. return S_OK;
  888. }
  889. //////////////////////////////////////////////////////////////////////////////
  890. //
  891. // Our available static terminal types.
  892. //
  893. const STATIC_TERMINAL_TYPE CMSPAddress::m_saTerminalTypes[] =
  894. {
  895. {
  896. (DWORD) TAPIMEDIATYPE_AUDIO,
  897. &CLSID_CWaveinClassManager,
  898. CAudioCaptureTerminal::CreateTerminal
  899. },
  900. {
  901. (DWORD) TAPIMEDIATYPE_AUDIO,
  902. &CLSID_CWaveOutClassManager,
  903. CAudioRenderTerminal::CreateTerminal
  904. },
  905. {
  906. (DWORD) TAPIMEDIATYPE_VIDEO,
  907. &CLSID_CVidCapClassManager,
  908. CVideoCaptureTerminal::CreateTerminal
  909. }
  910. };
  911. const DWORD CMSPAddress::m_sdwTerminalTypesCount = sizeof(m_saTerminalTypes)
  912. / sizeof (STATIC_TERMINAL_TYPE);
  913. /////////////////////////////////////////////////////////////////////////////
  914. // CMSPAddress
  915. /////////////////////////////////////////////////////////////////////////////
  916. //
  917. // Check to see if the mediatype is non-zero and is in the mask.
  918. // Your MSP can override this if it needs to do atypically complex
  919. // checks on specific combinations of media types (e.g., can never
  920. // have more than one media type on a call, can have video with audio
  921. // but not video alone, etc.). The default implementation accepts any
  922. // nonempty set of media types that is a subset of the set of types
  923. // in the mask.
  924. //
  925. BOOL CMSPAddress::IsValidSetOfMediaTypes(DWORD dwMediaType, DWORD dwMask)
  926. {
  927. return (dwMediaType != 0) && ((dwMediaType & dwMask) == dwMediaType);
  928. }
  929. CMSPAddress::CMSPAddress()
  930. : m_htEvent(NULL),
  931. m_fTerminalsUpToDate(FALSE),
  932. m_pITTerminalManager(NULL)
  933. {
  934. LOG((MSP_TRACE, "CMSPAddress::CMSPAddress[%p] - enter", this));
  935. LOG((MSP_TRACE, "CMSPAddress::CMSPAddress - finished"));
  936. }
  937. CMSPAddress::~CMSPAddress()
  938. {
  939. LOG((MSP_TRACE, "CMSPAddress::~CMSPAddress[%p] - enter", this));
  940. //
  941. // this should have been taken care of in Shutdown,
  942. // but just in case shutdown was never called, do this again, since
  943. // we need to make sure the thread does not have any stale entries in
  944. // its pnp notification list
  945. //
  946. // the call is likely to return error (since the object is likely to have been
  947. // unregisted earlier) -- so ignore return code
  948. //
  949. g_Thread.UnregisterPnpNotification(this);
  950. LOG((MSP_TRACE, "CMSPAddress::~CMSPAddress - finished"));
  951. }
  952. STDMETHODIMP CMSPAddress::Initialize(
  953. IN MSP_HANDLE htEvent
  954. )
  955. /*++
  956. Routine Description:
  957. This method is called by TAPI3 when this MSP is first created. The method
  958. initiailzes data members and creates the terminal manager. It also tells
  959. the global thread object to Start().
  960. Arguments:
  961. htEvent
  962. Event the MSP signals when passing an event structure back to TAPI.
  963. Return Value:
  964. S_OK
  965. E_INVALIDARG
  966. E_OUTOFMEMORY
  967. TAPI_E_REGISTERCALLBACK
  968. --*/
  969. {
  970. LOG((MSP_TRACE,
  971. "MSP address %x initialize entered, htEvent:%x",
  972. this, htEvent));
  973. if ( htEvent == NULL )
  974. {
  975. LOG((MSP_ERROR, " bad handle: htEvent:%x", htEvent));
  976. return E_INVALIDARG;
  977. }
  978. // lock the event related data
  979. m_EventDataLock.Lock();
  980. if (m_htEvent != NULL)
  981. {
  982. m_EventDataLock.Unlock();
  983. LOG((MSP_ERROR, "Initialze called twice."));
  984. return E_UNEXPECTED;
  985. }
  986. // save handles.
  987. m_htEvent = htEvent;
  988. InitializeListHead(&m_EventList);
  989. HRESULT hr;
  990. // release the lock on the event related data
  991. m_EventDataLock.Unlock();
  992. // lock the terminal related data. This is a auto lock that will unlock
  993. // when the function returns.
  994. CLock lock(m_TerminalDataLock);
  995. // Create the terminal manager.
  996. hr = CoCreateInstance(
  997. CLSID_TerminalManager,
  998. NULL,
  999. CLSCTX_INPROC_SERVER,
  1000. IID_ITTerminalManager,
  1001. (void **) &m_pITTerminalManager
  1002. );
  1003. if (FAILED(hr))
  1004. {
  1005. LOG((MSP_ERROR,
  1006. "Creating terminal manager failed. return: %x", hr));
  1007. return hr;
  1008. }
  1009. hr = g_Thread.Start();
  1010. if (FAILED(hr))
  1011. {
  1012. m_pITTerminalManager->Release();
  1013. m_pITTerminalManager = NULL;
  1014. LOG((MSP_ERROR,
  1015. "Creating thread failed. return: %x", hr));
  1016. return hr;
  1017. }
  1018. hr = g_Thread.RegisterPnpNotification(this);
  1019. if (FAILED(hr))
  1020. {
  1021. LOG((MSP_ERROR,
  1022. "Unable to register for PNP notification. return: %x", hr));
  1023. }
  1024. LOG((MSP_TRACE,
  1025. "MSP address %x initialize exited S_OK, htEvent:%x",
  1026. this, htEvent));
  1027. return S_OK;
  1028. }
  1029. STDMETHODIMP CMSPAddress::Shutdown ()
  1030. /*++
  1031. Routine Description:
  1032. This method is called by TAPI3 when this address in not in use any more.
  1033. This function releases the terminals and releases the terminal manager.
  1034. It releases all unprocessed events, and also stops the worker thread.
  1035. When this functions is called, no call should be alive. However, bugs in
  1036. the app may keep calls or terminals around. Currently this function
  1037. does not attempt to solve this problem. The calls will have their own
  1038. refcounts on the terminals, so it shouldn't fail anyway.
  1039. Arguments:
  1040. None.
  1041. Return Value:
  1042. S_OK
  1043. --*/
  1044. {
  1045. LOG((MSP_TRACE, "CMSPAddress::Shutdown - "
  1046. "MSP address %x is shutting down", this));
  1047. HRESULT hr;
  1048. //
  1049. // Unregister for PNP notification
  1050. //
  1051. hr = g_Thread.UnregisterPnpNotification(this);
  1052. if (FAILED(hr))
  1053. {
  1054. LOG((MSP_ERROR,
  1055. "Unable to unregister for PNP notification. return: %x", hr));
  1056. }
  1057. //
  1058. // Tell the worker thread to stop.
  1059. //
  1060. g_Thread.Stop();
  1061. LOG((MSP_INFO, "CMSPAddress::Shutdown - thread has stopped"));
  1062. // acquire the lock on the terminal data because we are writing to it.
  1063. m_TerminalDataLock.Lock();
  1064. // Release the terminal manager.
  1065. if (m_pITTerminalManager != NULL)
  1066. {
  1067. m_pITTerminalManager->Release();
  1068. m_pITTerminalManager = NULL;
  1069. }
  1070. // release all the terminals.
  1071. for (int i = 0; i < m_Terminals.GetSize(); i ++)
  1072. {
  1073. //
  1074. // Clear its CMSPAddress pointer
  1075. //
  1076. CBaseTerminal * pCTerminal = static_cast<CBaseTerminal *> (m_Terminals[i]);
  1077. m_Terminals[i]->Release();
  1078. }
  1079. m_Terminals.RemoveAll();
  1080. // We are done with terminal related data, release the lock.
  1081. m_TerminalDataLock.Unlock();
  1082. LOG((MSP_INFO, "CMSPAddress::Shutdown - terminals released"));
  1083. // acquire the lock on the event data because we are writing to it.
  1084. m_EventDataLock.Lock();
  1085. m_htEvent = NULL;
  1086. // release all the unprocessed events in the list.
  1087. while (!IsListEmpty(&m_EventList))
  1088. {
  1089. // retrieve first entry
  1090. PLIST_ENTRY pLE = RemoveHeadList(&m_EventList);
  1091. // convert list entry to structure pointer
  1092. PMSPEVENTITEM pItem = CONTAINING_RECORD(pLE, MSPEVENTITEM, Link);
  1093. // release the refcount in the event.
  1094. LOG((MSP_INFO,
  1095. "CMSPAddress::Shutdown:releasing event still in the queue: %x",
  1096. pItem->MSPEventInfo.Event
  1097. ));
  1098. switch (pItem->MSPEventInfo.Event)
  1099. {
  1100. case ME_ADDRESS_EVENT:
  1101. if (pItem->MSPEventInfo.MSP_ADDRESS_EVENT_INFO.pTerminal)
  1102. {
  1103. pItem->MSPEventInfo.MSP_ADDRESS_EVENT_INFO.pTerminal->Release();
  1104. }
  1105. break;
  1106. case ME_CALL_EVENT:
  1107. if (pItem->MSPEventInfo.MSP_CALL_EVENT_INFO.pStream)
  1108. {
  1109. pItem->MSPEventInfo.MSP_CALL_EVENT_INFO.pStream->Release();
  1110. }
  1111. if (pItem->MSPEventInfo.MSP_CALL_EVENT_INFO.pTerminal)
  1112. {
  1113. pItem->MSPEventInfo.MSP_CALL_EVENT_INFO.pTerminal->Release();
  1114. }
  1115. break;
  1116. case ME_PRIVATE_EVENT:
  1117. if (pItem->MSPEventInfo.MSP_PRIVATE_EVENT_INFO.pEvent)
  1118. {
  1119. pItem->MSPEventInfo.MSP_PRIVATE_EVENT_INFO.pEvent->Release();
  1120. }
  1121. break;
  1122. case ME_TSP_DATA:
  1123. // nothing inside the structure that we need to free
  1124. break;
  1125. case ME_FILE_TERMINAL_EVENT:
  1126. if( NULL != pItem->MSPEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal)
  1127. {
  1128. (pItem->MSPEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal)->Release();
  1129. pItem->MSPEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal = NULL;
  1130. }
  1131. if( NULL != pItem->MSPEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack )
  1132. {
  1133. (pItem->MSPEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack)->Release();
  1134. pItem->MSPEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack = NULL;
  1135. }
  1136. break;
  1137. case ME_ASR_TERMINAL_EVENT:
  1138. if( NULL != pItem->MSPEventInfo.MSP_ASR_TERMINAL_EVENT_INFO.pASRTerminal)
  1139. {
  1140. (pItem->MSPEventInfo.MSP_ASR_TERMINAL_EVENT_INFO.pASRTerminal)->Release();
  1141. }
  1142. break;
  1143. case ME_TTS_TERMINAL_EVENT:
  1144. if( NULL != pItem->MSPEventInfo.MSP_TTS_TERMINAL_EVENT_INFO.pTTSTerminal)
  1145. {
  1146. (pItem->MSPEventInfo.MSP_TTS_TERMINAL_EVENT_INFO.pTTSTerminal)->Release();
  1147. }
  1148. break;
  1149. case ME_TONE_TERMINAL_EVENT:
  1150. if( NULL != pItem->MSPEventInfo.MSP_TONE_TERMINAL_EVENT_INFO.pToneTerminal)
  1151. {
  1152. (pItem->MSPEventInfo.MSP_TONE_TERMINAL_EVENT_INFO.pToneTerminal)->Release();
  1153. }
  1154. break;
  1155. default:
  1156. LOG((MSP_WARN, "CMSPAddress::Shutdown: unknown event type: %x",
  1157. pItem->MSPEventInfo.Event));
  1158. break;
  1159. }
  1160. FreeEventItem(pItem);
  1161. }
  1162. // We are done with event related data, release the lcok.
  1163. m_EventDataLock.Unlock();
  1164. LOG((MSP_TRACE, "CMSPAddress::Shutdown - exit S_OK"));
  1165. return S_OK;
  1166. }
  1167. STDMETHODIMP CMSPAddress::ReceiveTSPData(
  1168. IN IUnknown * pMSPCall,
  1169. IN LPBYTE pBuffer,
  1170. IN DWORD dwBufferSize
  1171. )
  1172. /*++
  1173. Routine Description:
  1174. This method is called by TAPI3 when the TSP address sends data to this
  1175. MSP address object. The semantics of the data passed in the buffer are
  1176. specific to each TSP - MSP pair. This method dispatches the received
  1177. buffer to the address (call == NULL) or call (call != NULL).
  1178. Arguments:
  1179. pMSPCall
  1180. The call object that the data is for. If it is NULL, the data is for
  1181. this address.
  1182. pBuffer
  1183. Opaque buffer from TSP.
  1184. dwBufferSize
  1185. Size in bytes of pBuffer
  1186. Return Value:
  1187. S_OK
  1188. --*/
  1189. {
  1190. LOG((MSP_TRACE, "CMSPAddress::ReceiveTSPData entered. pMSPCall:%x",
  1191. pMSPCall));
  1192. _ASSERTE(dwBufferSize > 0);
  1193. _ASSERTE(!IsBadReadPtr(pBuffer, sizeof(BYTE) * (dwBufferSize) ) );
  1194. HRESULT hr;
  1195. if ( NULL == pMSPCall )
  1196. {
  1197. hr = ReceiveTSPAddressData(pBuffer, dwBufferSize);
  1198. if ( FAILED(hr) )
  1199. {
  1200. LOG((MSP_ERROR, "CMSPAddress::ReceiveTSPData - "
  1201. "ReceiveTSPAddressData failed - exit 0x%08x", hr));
  1202. return hr;
  1203. }
  1204. LOG((MSP_TRACE, "CMSPAddress::ReceiveTSPData - "
  1205. "exit S_OK (dispatched to address)"));
  1206. return S_OK;
  1207. }
  1208. //
  1209. // We have a call to dispatch to.
  1210. //
  1211. _ASSERTE(!IsBadReadPtr(pMSPCall, sizeof(IUnknown) ) );
  1212. ITStreamControl * pIStreamControl;
  1213. hr = pMSPCall->QueryInterface(IID_ITStreamControl,
  1214. (void **)&pIStreamControl);
  1215. if ( FAILED(hr) )
  1216. {
  1217. LOG((MSP_ERROR, "CMSPAddress::ReceiveTSPData - "
  1218. "can't get the ITStream Control interface - exit 0x%08x", hr));
  1219. return hr;
  1220. }
  1221. CMSPCallBase * pCall = static_cast<CMSPCallBase *> (pIStreamControl);
  1222. if (pCall == NULL)
  1223. {
  1224. LOG((MSP_ERROR, "CMSPAddress::ReceiveTSPData - "
  1225. "invalid msp call pointer: %x", pMSPCall));
  1226. pIStreamControl->Release();
  1227. return E_UNEXPECTED;
  1228. }
  1229. hr = pCall->ReceiveTSPCallData(pBuffer, dwBufferSize);
  1230. pIStreamControl->Release();
  1231. if ( FAILED(hr) )
  1232. {
  1233. LOG((MSP_ERROR, "CMSPAddress::ReceiveTSPData - "
  1234. "method on call failed - exit 0x%08x", hr));
  1235. return hr;
  1236. }
  1237. LOG((MSP_TRACE, "CMSPAddress::ReceiveTSPData - "
  1238. "exit S_OK (dispatched to call)"));
  1239. return S_OK;
  1240. }
  1241. HRESULT CMSPAddress::GetStaticTerminals(
  1242. IN OUT DWORD * pdwNumTerminals,
  1243. OUT ITTerminal ** ppTerminals
  1244. )
  1245. /*++
  1246. Routine Description:
  1247. This method is called by TAPI3 to get a list of static terminals that can
  1248. be used on this address. If our list is not empty, just return the list.
  1249. If our list is still empty, create the static terminals and return the list.
  1250. Derived class can override this method to have their own terminals. Locks
  1251. the terminal lists.
  1252. Arguments:
  1253. pdwNumTerminals
  1254. Pointer to a DWORD. On entry, indicates the size of the buffer pointed
  1255. to in ppTerminals. On success, it will be filled in with the actual number
  1256. of terminals returned. If the buffer is not big enough, the method will
  1257. return TAPI_E_NOTENOUGHMEMORY, and it will be filled in the with number
  1258. of terminals needed.
  1259. ppTerminals
  1260. On success, filled in with an array of terminals object pointers that are
  1261. supported by the MSP for this address. This value may be NULL, in which
  1262. case pdwNumTerminals will return the needed buffer size.
  1263. Return Value:
  1264. S_OK
  1265. E_OUTOFMEMORY
  1266. TAPI_E_NOTENOUGHMEMORY
  1267. --*/
  1268. {
  1269. LOG((MSP_TRACE,
  1270. "GetStaticTerminals entered. NumTerminals:%x, ppTerminals:%x",
  1271. *pdwNumTerminals, ppTerminals
  1272. ));
  1273. // lock the terminal related data. This is a auto lock that will unlock
  1274. // when the function returns.
  1275. CLock lock(m_TerminalDataLock);
  1276. if (!m_fTerminalsUpToDate)
  1277. {
  1278. HRESULT hr = UpdateTerminalList();
  1279. if (FAILED(hr))
  1280. {
  1281. LOG((MSP_ERROR,
  1282. "CMSPAddress::GetStaticTerminals - "
  1283. "UpdateTerminalList failed - returning 0x%08x", hr));
  1284. return hr;
  1285. }
  1286. }
  1287. //
  1288. // Check if initialized.
  1289. //
  1290. if ( m_htEvent == NULL )
  1291. {
  1292. LOG((MSP_ERROR, "CMSPAddress::GetStaticTerminals - "
  1293. "not initialized - returning E_UNEXPECTED"));
  1294. return E_UNEXPECTED;
  1295. }
  1296. //
  1297. // Check parameters.
  1298. //
  1299. if ( MSPB_IsBadWritePtr(pdwNumTerminals, sizeof(DWORD) ) )
  1300. {
  1301. LOG((MSP_ERROR, "CMSPAddress::GetStaticTerminals - "
  1302. "bad pdwNumTerminals pointer - exit E_POINTER"));
  1303. return E_POINTER;
  1304. }
  1305. if ( ppTerminals != NULL )
  1306. {
  1307. if ( MSPB_IsBadWritePtr(ppTerminals,
  1308. *pdwNumTerminals * sizeof(ITTerminal *) ) )
  1309. {
  1310. LOG((MSP_ERROR, "CMSPAddress::GetStaticTerminals - "
  1311. "bad ppTerminals pointer - exit E_POINTER"));
  1312. return E_POINTER;
  1313. }
  1314. }
  1315. //
  1316. // Grab the size of the terminals list.
  1317. //
  1318. int iSize = m_Terminals.GetSize();
  1319. _ASSERTE( iSize >= 0 );
  1320. //
  1321. // Add our terminals to the output list if the caller wants an output
  1322. // list, and provided there is enough room in the output list.
  1323. //
  1324. if ( ( ppTerminals != NULL ) &&
  1325. ( (DWORD) iSize <= *pdwNumTerminals ) )
  1326. {
  1327. //
  1328. // For each terminal in the list of terminals we created,
  1329. // AddRef and copy the terminal pointer.
  1330. //
  1331. for (int i = 0; i < iSize; i++)
  1332. {
  1333. m_Terminals[i]->AddRef();
  1334. ppTerminals[i] = m_Terminals[i];
  1335. }
  1336. }
  1337. //
  1338. // If there was no output list then we just have to report the number
  1339. // of terminals available.
  1340. //
  1341. if ( ppTerminals == NULL )
  1342. {
  1343. *pdwNumTerminals = (DWORD) iSize;
  1344. LOG((MSP_TRACE,
  1345. "CMSPAddress::GetStaticTerminals - just returned number of "
  1346. "terminals available - exit S_OK"));
  1347. return S_OK;
  1348. }
  1349. //
  1350. // If there was an output list but it was not large enough, then
  1351. // return the appropriate error.
  1352. //
  1353. if ( (DWORD) iSize > *pdwNumTerminals )
  1354. {
  1355. *pdwNumTerminals = (DWORD) iSize;
  1356. LOG((MSP_ERROR,
  1357. "CMSPAddress::GetStaticTerminals - passed-in array not "
  1358. "large enough - exit TAPI_E_NOTENOUGHMEMORY"));
  1359. return TAPI_E_NOTENOUGHMEMORY;
  1360. }
  1361. //
  1362. // Otherwise, everything was fine. We just need to report the actual
  1363. // number of terminals we copied and return S_OK.
  1364. //
  1365. *pdwNumTerminals = (DWORD) iSize;
  1366. LOG((MSP_TRACE,
  1367. "CMSPAddress::GetStaticTerminals - "
  1368. "returned terminals - exit S_OK"));
  1369. return S_OK;
  1370. }
  1371. HRESULT CMSPAddress::IsMonikerInTerminalList(IMoniker* pMoniker)
  1372. {
  1373. CSingleFilterStaticTerminal *pCSingleFilterStaticTerminal;
  1374. //
  1375. // Grab the size of the terminals list.
  1376. //
  1377. int iSize = m_Terminals.GetSize();
  1378. _ASSERTE( iSize >= 0 );
  1379. //
  1380. // Add our terminals to the output list if the caller wants an output
  1381. // list, and provided there is enough room in the output list.
  1382. //
  1383. for (int i = 0; i < iSize; i++)
  1384. {
  1385. pCSingleFilterStaticTerminal = static_cast<CSingleFilterStaticTerminal *>(m_Terminals[i]);
  1386. if ( pCSingleFilterStaticTerminal->CompareMoniker( pMoniker ) == S_OK )
  1387. {
  1388. LOG((MSP_TRACE, "CMSPAddress::IsMonikerInTerminalList - "
  1389. "moniker found in terminal list"));
  1390. pCSingleFilterStaticTerminal->m_bMark = TRUE; // mark this terminal so we don't remove it
  1391. return S_OK;
  1392. }
  1393. }
  1394. LOG((MSP_TRACE, "CMSPAddress::IsMonikerInTerminalList - "
  1395. "moniker not found in terminal list"));
  1396. return S_FALSE;
  1397. }
  1398. HRESULT CMSPAddress::UpdateTerminalListForPnp(
  1399. IN BOOL bDeviceArrival
  1400. )
  1401. {
  1402. CSingleFilterStaticTerminal *pCSingleFilterStaticTerminal;
  1403. //
  1404. // Clear all marks in the terminal list
  1405. //
  1406. int iSize = m_Terminals.GetSize();
  1407. _ASSERTE( iSize >= 0 );
  1408. for (int i = 0; i < iSize; i++)
  1409. {
  1410. pCSingleFilterStaticTerminal = static_cast<CSingleFilterStaticTerminal *>(m_Terminals[i]);
  1411. if (pCSingleFilterStaticTerminal == NULL)
  1412. {
  1413. LOG((MSP_ERROR, "CMSPAddress::IsMonikerInTerminalList - "
  1414. "bad terminal pointer"));
  1415. return E_FAIL;
  1416. }
  1417. pCSingleFilterStaticTerminal->m_bMark = FALSE;
  1418. }
  1419. //
  1420. // Create DevEnum, which is the DirectShow Category Enumerator Creator
  1421. //
  1422. HRESULT hr;
  1423. ICreateDevEnum * pCreateDevEnum;
  1424. hr = CoCreateInstance(CLSID_SystemDeviceEnum,
  1425. NULL,
  1426. CLSCTX_INPROC_SERVER,
  1427. IID_ICreateDevEnum,
  1428. (void**)&pCreateDevEnum);
  1429. if (FAILED(hr))
  1430. {
  1431. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalListForPnp "
  1432. "can't CoCreate DevEnum - returning 0x%08x", hr));
  1433. return hr;
  1434. }
  1435. IEnumMoniker * pCatEnum;
  1436. for ( i = 0; i < m_sdwTerminalTypesCount; i++ )
  1437. {
  1438. //
  1439. // Skip any terminal types that don't use one of the supported media
  1440. // modes.
  1441. //
  1442. if ( ! IsValidSingleMediaType(
  1443. m_saTerminalTypes[i].dwMediaType, GetCallMediaTypes() ) )
  1444. {
  1445. continue;
  1446. }
  1447. //
  1448. // Create the actual category enumerator.
  1449. //
  1450. hr = pCreateDevEnum->CreateClassEnumerator(
  1451. *(m_saTerminalTypes[i].clsidClassManager),
  1452. &pCatEnum,
  1453. 0);
  1454. if ( hr != S_OK ) // S_FALSE means the category does not exist!
  1455. {
  1456. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalListForPnp "
  1457. "can't create class enumerator - returning 0x%08x", hr));
  1458. continue;
  1459. }
  1460. IMoniker * pMoniker;
  1461. while ((hr = pCatEnum->Next(1, &pMoniker, NULL)) == S_OK)
  1462. {
  1463. if (IsMonikerInTerminalList(pMoniker) == S_FALSE)
  1464. {
  1465. //
  1466. // Create a terminal and give it its moniker.
  1467. //
  1468. ITTerminal * pTerminal;
  1469. hr = (m_saTerminalTypes[i].pfnCreateTerm)(pMoniker,
  1470. (MSP_HANDLE) this,
  1471. &pTerminal);
  1472. //
  1473. // The terminal keeps a reference to the moniker if it needs to.
  1474. //
  1475. pMoniker->Release();
  1476. if (SUCCEEDED(hr))
  1477. {
  1478. //
  1479. // Add this terminal pointer to our list. Don't release it; we
  1480. // keep this one reference to it in the list.
  1481. //
  1482. BOOL fSuccess = m_Terminals.Add(pTerminal);
  1483. if ( ! fSuccess )
  1484. {
  1485. pCatEnum->Release();
  1486. pTerminal->Release();
  1487. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalListForPnp - "
  1488. "can't add terminal to list; returning E_OUTOFMEMORY"));
  1489. return E_OUTOFMEMORY;
  1490. }
  1491. //
  1492. // Set its CMSPAddress pointer
  1493. //
  1494. CBaseTerminal * pCTerminal = static_cast<CBaseTerminal *> (pTerminal);
  1495. //
  1496. // Mark this terminal so we don't remove it
  1497. //
  1498. pCSingleFilterStaticTerminal = static_cast<CSingleFilterStaticTerminal *>(pTerminal);
  1499. if (pCSingleFilterStaticTerminal == NULL)
  1500. {
  1501. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalListForPnp - "
  1502. "bad terminal pointer"));
  1503. return E_FAIL;
  1504. }
  1505. pCSingleFilterStaticTerminal->m_bMark = TRUE;
  1506. //
  1507. // Post a TAPI message about the new terminal's arrival
  1508. //
  1509. pTerminal->AddRef();
  1510. MSPEVENTITEM *pEventItem;
  1511. pEventItem = AllocateEventItem();
  1512. if (pEventItem == NULL)
  1513. {
  1514. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalListForPnp - "
  1515. "can't allocate event item; returning E_OUTOFMEMORY"));
  1516. pTerminal->Release();
  1517. return E_OUTOFMEMORY;
  1518. }
  1519. pEventItem->MSPEventInfo.dwSize = sizeof(MSP_EVENT_INFO);
  1520. pEventItem->MSPEventInfo.Event = ME_ADDRESS_EVENT;
  1521. pEventItem->MSPEventInfo.MSP_ADDRESS_EVENT_INFO.Type = ADDRESS_TERMINAL_AVAILABLE;
  1522. pEventItem->MSPEventInfo.MSP_ADDRESS_EVENT_INFO.pTerminal = pTerminal;
  1523. hr = PostEvent(pEventItem);
  1524. if (FAILED(hr))
  1525. {
  1526. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalListForPnp - "
  1527. "post event failed"));
  1528. pTerminal->Release();
  1529. FreeEventItem(pEventItem);
  1530. }
  1531. }
  1532. }
  1533. //
  1534. // If it failed, that either means we skipped the device because it
  1535. // was unsuitable (a routine occurance) or something failed, like
  1536. // out of memory. I should come up with a way to differentiate and
  1537. // handle this well.
  1538. //
  1539. }
  1540. //
  1541. // We are done with the enumerator.
  1542. //
  1543. pCatEnum->Release();
  1544. }
  1545. //
  1546. // Release DevEnum.
  1547. //
  1548. pCreateDevEnum->Release();
  1549. //
  1550. // Sweep the terminal list and clean up any terminals which are no longer present
  1551. //
  1552. iSize = m_Terminals.GetSize();
  1553. _ASSERTE( iSize >= 0 );
  1554. for (i = 0; i < iSize; i++)
  1555. {
  1556. pCSingleFilterStaticTerminal = static_cast<CSingleFilterStaticTerminal *>(m_Terminals[i]);
  1557. if (pCSingleFilterStaticTerminal == NULL)
  1558. {
  1559. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalListForPnp - "
  1560. "bad terminal pointer"));
  1561. return E_FAIL;
  1562. }
  1563. if (!pCSingleFilterStaticTerminal->m_bMark)
  1564. {
  1565. //
  1566. // This terminal has is no longer present, lets remove it from the list
  1567. //
  1568. LOG((MSP_TRACE, "CMSPAddress::UpdateTerminalListForPnp "
  1569. "found a terminal to be removed"));
  1570. ITTerminal * pTerminal = m_Terminals[i];
  1571. if (m_Terminals.RemoveAt(i))
  1572. {
  1573. //
  1574. // Clear its CMSPAddress pointer
  1575. //
  1576. CBaseTerminal * pCTerminal = static_cast<CBaseTerminal *> (pTerminal);
  1577. //
  1578. // We don't release the terminal here even though we are removing
  1579. // it from the terminal list because TAPI3.dll will release it
  1580. // when it releases the event.
  1581. //
  1582. //
  1583. // Post a TAPI message about the new terminal's removal
  1584. //
  1585. MSPEVENTITEM *pEventItem;
  1586. pEventItem = AllocateEventItem();
  1587. if (pEventItem == NULL)
  1588. {
  1589. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalListForPnp - "
  1590. "can't allocate event item; returning E_OUTOFMEMORY"));
  1591. pTerminal->Release();
  1592. return E_OUTOFMEMORY;
  1593. }
  1594. pEventItem->MSPEventInfo.dwSize = sizeof(MSP_EVENT_INFO);
  1595. pEventItem->MSPEventInfo.Event = ME_ADDRESS_EVENT;
  1596. pEventItem->MSPEventInfo.MSP_ADDRESS_EVENT_INFO.Type = ADDRESS_TERMINAL_UNAVAILABLE;
  1597. pEventItem->MSPEventInfo.MSP_ADDRESS_EVENT_INFO.pTerminal = pTerminal;
  1598. hr = PostEvent(pEventItem);
  1599. if (FAILED(hr))
  1600. {
  1601. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalListForPnp - "
  1602. "post event failed"));
  1603. pTerminal->Release();
  1604. FreeEventItem(pEventItem);
  1605. }
  1606. //
  1607. // fix up our search indices to account for a removal
  1608. //
  1609. iSize--;
  1610. i--;
  1611. }
  1612. }
  1613. }
  1614. //
  1615. // Our list is now complete.
  1616. //
  1617. m_fTerminalsUpToDate = TRUE;
  1618. LOG((MSP_TRACE, "CMSPAddress::UpdateTerminalListForPnp - exit S_OK"));
  1619. return S_OK;
  1620. }
  1621. HRESULT CMSPAddress::UpdateTerminalList(void)
  1622. {
  1623. //
  1624. // Create DevEnum, which is the DirectShow Category Enumerator Creator
  1625. //
  1626. HRESULT hr;
  1627. ICreateDevEnum * pCreateDevEnum;
  1628. hr = CoCreateInstance(CLSID_SystemDeviceEnum,
  1629. NULL,
  1630. CLSCTX_INPROC_SERVER,
  1631. IID_ICreateDevEnum,
  1632. (void**)&pCreateDevEnum);
  1633. if (FAILED(hr))
  1634. {
  1635. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalList "
  1636. "can't CoCreate DevEnum - returning 0x%08x", hr));
  1637. return hr;
  1638. }
  1639. IEnumMoniker * pCatEnum;
  1640. for ( DWORD i = 0; i < m_sdwTerminalTypesCount; i++ )
  1641. {
  1642. //
  1643. // Skip any terminal types that don't use one of the supported media
  1644. // modes.
  1645. //
  1646. if ( ! IsValidSingleMediaType(
  1647. m_saTerminalTypes[i].dwMediaType, GetCallMediaTypes() ) )
  1648. {
  1649. continue;
  1650. }
  1651. //
  1652. // Create the actual category enumerator.
  1653. //
  1654. hr = pCreateDevEnum->CreateClassEnumerator(
  1655. *(m_saTerminalTypes[i].clsidClassManager),
  1656. &pCatEnum,
  1657. 0);
  1658. if ( hr != S_OK ) // S_FALSE means the category does not exist!
  1659. {
  1660. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalList "
  1661. "can't create class enumerator - returning 0x%08x", hr));
  1662. continue;
  1663. }
  1664. IMoniker * pMoniker;
  1665. while ((hr = pCatEnum->Next(1, &pMoniker, NULL)) == S_OK)
  1666. {
  1667. //
  1668. // Create a terminal and give it its moniker.
  1669. //
  1670. ITTerminal * pTerminal;
  1671. hr = (m_saTerminalTypes[i].pfnCreateTerm)(pMoniker,
  1672. (MSP_HANDLE) this,
  1673. &pTerminal);
  1674. //
  1675. // The terminal keeps a reference to the moniker if it needs to.
  1676. //
  1677. pMoniker->Release();
  1678. if (SUCCEEDED(hr))
  1679. {
  1680. //
  1681. // Add this terminal pointer to our list. Don't release it; we
  1682. // keep this one reference to it in the list.
  1683. //
  1684. BOOL fSuccess = m_Terminals.Add(pTerminal);
  1685. if ( ! fSuccess )
  1686. {
  1687. pCatEnum->Release();
  1688. LOG((MSP_ERROR, "CMSPAddress::UpdateTerminalList - "
  1689. "can't add terminal to list; returning E_OUTOFMEMORY"));
  1690. return E_OUTOFMEMORY;
  1691. }
  1692. //
  1693. // Set its CMSPAddress pointer
  1694. //
  1695. CBaseTerminal * pCTerminal = static_cast<CBaseTerminal *> (pTerminal);
  1696. }
  1697. //
  1698. // If it failed, that either means we skipped the device because it
  1699. // was unsuitable (a routine occurance) or something failed, like
  1700. // out of memory. I should come up with a way to differentiate and
  1701. // handle this well.
  1702. //
  1703. }
  1704. //
  1705. // We are done with the enumerator.
  1706. //
  1707. pCatEnum->Release();
  1708. }
  1709. //
  1710. // Release DevEnum.
  1711. //
  1712. pCreateDevEnum->Release();
  1713. //
  1714. // Our list is now complete.
  1715. //
  1716. m_fTerminalsUpToDate = TRUE;
  1717. LOG((MSP_TRACE, "CMSPAddress::UpdateTerminalList - exit S_OK"));
  1718. return S_OK;
  1719. }
  1720. HRESULT CMSPAddress::GetDynamicTerminalClasses(
  1721. IN OUT DWORD * pdwNumClasses,
  1722. OUT IID * pTerminalClasses
  1723. )
  1724. /*++
  1725. Routine Description:
  1726. This method is called by TAPI3 to get a list of dynamic terminal guids
  1727. that can be used on this address. It asks the terminal manager for the
  1728. list of guids and returns them. Derived class can override this method
  1729. to have their own guids.
  1730. Arguments:
  1731. pdwNumClasses
  1732. Pointer to a DWORD. On entry, indicates the size of the buffer
  1733. pointed to in pTerminalClasses. On success, it will be filled in
  1734. with the actual number of class IIDs returned. If the buffer is
  1735. not big enough, the method will return TAPI_E_NOTENOUGHMEMORY,
  1736. and it will be filled in the with number of IIDs needed.
  1737. pTerminalClasses
  1738. On success, filled in with an array of terminal class IIDs that
  1739. are supported by the MSP for this address. This value may be NULL,
  1740. in which case pdwNumClasses will return the needed buffer size.
  1741. Return Value:
  1742. S_OK
  1743. E_OUTOFMEMORY
  1744. TAPI_E_NOTENOUGHMEMORY
  1745. --*/
  1746. {
  1747. LOG((MSP_TRACE,
  1748. "CMSPAddress::GetDynamicTerminalClasses - enter"));
  1749. //
  1750. // Check if initialized.
  1751. //
  1752. // lock the event related data
  1753. m_EventDataLock.Lock();
  1754. if ( m_htEvent == NULL )
  1755. {
  1756. // unlock the event related data
  1757. m_EventDataLock.Unlock();
  1758. LOG((MSP_ERROR,
  1759. "CMSPAddress::GetDynamicTerminalClasses - "
  1760. "not initialized - returning E_UNEXPECTED"));
  1761. return E_UNEXPECTED;
  1762. }
  1763. // unlock the event related data
  1764. m_EventDataLock.Unlock();
  1765. //
  1766. // Ask the Terminal Manager for the dynamic terminals that apply to
  1767. // all of our supported media types. Since the mapping is
  1768. // direct, the Terminal Manager takes care of all argument checking.
  1769. //
  1770. HRESULT hr;
  1771. hr = m_pITTerminalManager->GetDynamicTerminalClasses(
  1772. GetCallMediaTypes(),
  1773. pdwNumClasses,
  1774. pTerminalClasses);
  1775. LOG((MSP_TRACE,
  1776. "CMSPAddress::GetDynamicTerminalClasses - exit 0x%08x", hr));
  1777. return hr;
  1778. }
  1779. STDMETHODIMP CMSPAddress::CreateTerminal(
  1780. IN BSTR pTerminalClass,
  1781. IN long lMediaType,
  1782. IN TERMINAL_DIRECTION Direction,
  1783. OUT ITTerminal ** ppTerminal
  1784. )
  1785. /*++
  1786. Routine Description:
  1787. This method is called by TAPI3 to create a dynamic terminal. It asks the
  1788. terminal manager to create a dynamic terminal. Derived class can
  1789. override this method to have their own way of creating a dynamic terminal.
  1790. Arguments:
  1791. iidTerminalClass
  1792. IID of the terminal class to be created.
  1793. dwMediaType
  1794. TAPI media type of the terminal to be created.
  1795. Direction
  1796. Terminal direction of the terminal to be created.
  1797. ppTerminal
  1798. Returned created terminal object
  1799. Return Value:
  1800. S_OK
  1801. E_OUTOFMEMORY
  1802. TAPI_E_INVALIDMEDIATYPE
  1803. TAPI_E_INVALIDTERMINALDIRECTION
  1804. TAPI_E_INVALIDTERMINALCLASS
  1805. --*/
  1806. {
  1807. LOG((MSP_TRACE,
  1808. "CMSPAddress::CreateTerminal - enter"));
  1809. //
  1810. // Check if initialized.
  1811. //
  1812. // lock the event related data
  1813. m_EventDataLock.Lock();
  1814. if ( m_htEvent == NULL )
  1815. {
  1816. // unlock the event related data
  1817. m_EventDataLock.Unlock();
  1818. LOG((MSP_ERROR,
  1819. "CMSPAddress::CreateTerminal - "
  1820. "not initialized - returning E_UNEXPECTED"));
  1821. return E_UNEXPECTED;
  1822. }
  1823. // unlock the event related data
  1824. m_EventDataLock.Unlock();
  1825. //
  1826. // Get the IID from the BSTR representation.
  1827. //
  1828. HRESULT hr;
  1829. IID iidTerminalClass;
  1830. hr = CLSIDFromString(pTerminalClass, &iidTerminalClass);
  1831. if ( FAILED(hr) )
  1832. {
  1833. LOG((MSP_ERROR, "CMSPAddress::CreateTerminal - "
  1834. "bad CLSID string - returning E_INVALIDARG"));
  1835. return E_INVALIDARG;
  1836. }
  1837. //
  1838. // Make sure we support the requested media type.
  1839. // The terminal manager checks the terminal class, terminal direction,
  1840. // and return pointer.
  1841. //
  1842. //
  1843. // requested media type may be aggregated, but it must still be valid
  1844. //
  1845. if ( !IsValidAggregatedMediaType(lMediaType) )
  1846. {
  1847. LOG((MSP_ERROR, "CMSPAddress::CreateTerminal - "
  1848. "unrecognized media type requested - returning E_INVALIDARG"));
  1849. return E_INVALIDARG;
  1850. }
  1851. //
  1852. // Use the terminal manager to create the dynamic terminal.
  1853. //
  1854. _ASSERTE( m_pITTerminalManager != NULL );
  1855. hr = m_pITTerminalManager->CreateDynamicTerminal(NULL,
  1856. iidTerminalClass,
  1857. (DWORD) lMediaType,
  1858. Direction,
  1859. (MSP_HANDLE) this,
  1860. ppTerminal);
  1861. if ( FAILED(hr) )
  1862. {
  1863. LOG((MSP_ERROR, "CMSPAddress::CreateTerminal - "
  1864. "create dynamic terminal failed - returning 0x%08x", hr));
  1865. return hr;
  1866. }
  1867. LOG((MSP_TRACE, "CMSPAddress::CreateTerminal - exit S_OK"));
  1868. return S_OK;
  1869. }
  1870. STDMETHODIMP CMSPAddress::GetDefaultStaticTerminal(
  1871. IN long lMediaType,
  1872. IN TERMINAL_DIRECTION Direction,
  1873. OUT ITTerminal ** ppTerminal
  1874. )
  1875. /*++
  1876. Routine Description:
  1877. This method is called by TAPI3 to get the default static terminal
  1878. for a certain type and direction. It updates the list if needed, then
  1879. figures out which terminal is the first of the appropriate type in our
  1880. list. Derived classes can override this method to have
  1881. their own way of deciding which terminal is the default. Locks the
  1882. terminal lists.
  1883. Arguments:
  1884. dwMediaType
  1885. The TAPIMEDIATYPE of the terminal to retrieve. Only one bit will be set.
  1886. Direction
  1887. TERMINAL_DIRECTION of the terminal to retrieve.
  1888. ppTerminal
  1889. Default terminal returned
  1890. Return Value:
  1891. S_OK
  1892. E_POINTER
  1893. E_OUTOFMEMORY
  1894. TAPI_E_NOTSUPPORTED
  1895. TAPI_E_INVALIDMEDIATYPE
  1896. TAPI_E_INVALIDTERMINALDIRECTION
  1897. --*/
  1898. {
  1899. LOG((MSP_TRACE,
  1900. "CMSPAddress::GetDefaultStaticTerminal - enter"));
  1901. //
  1902. // Check if initialized.
  1903. //
  1904. // lock the event related data
  1905. m_EventDataLock.Lock();
  1906. if ( m_htEvent == NULL )
  1907. {
  1908. // unlock the event related data
  1909. m_EventDataLock.Unlock();
  1910. LOG((MSP_ERROR,
  1911. "CMSPAddress::GetDefaultStaticTerminal - "
  1912. "not initialized - returning E_UNEXPECTED"));
  1913. return E_UNEXPECTED;
  1914. }
  1915. // unlock the event related data
  1916. m_EventDataLock.Unlock();
  1917. //
  1918. // Make sure we support this media type.
  1919. //
  1920. if ( ! IsValidSingleMediaType( (DWORD) lMediaType, GetCallMediaTypes() ) )
  1921. {
  1922. LOG((MSP_ERROR,
  1923. "CMSPAddress::GetDefaultStaticTerminal - "
  1924. "non-audio terminal requested - returning E_INVALIDARG"));
  1925. return E_INVALIDARG;
  1926. }
  1927. //
  1928. // Check the direction.
  1929. //
  1930. if ( ( Direction != TD_CAPTURE ) && ( Direction != TD_RENDER ) )
  1931. {
  1932. LOG((MSP_ERROR,
  1933. "CMSPAddress::GetDefaultStaticTerminal - "
  1934. "invalid direction - returning E_INVALIDARG"));
  1935. return E_INVALIDARG;
  1936. }
  1937. //
  1938. // Check return pointer.
  1939. //
  1940. if ( MSPB_IsBadWritePtr(ppTerminal, sizeof(ITTerminal *) ) )
  1941. {
  1942. LOG((MSP_ERROR,
  1943. "CMSPAddress::GetDefaultStaticTerminal - "
  1944. "bad terminal return pointer - returning E_POINTER"));
  1945. return E_POINTER;
  1946. }
  1947. // lock the terminal related data. This is a auto lock that will unlock
  1948. // when the function returns.
  1949. CLock lock(m_TerminalDataLock);
  1950. if (!m_fTerminalsUpToDate)
  1951. {
  1952. HRESULT hr = UpdateTerminalList();
  1953. if (FAILED(hr))
  1954. {
  1955. LOG((MSP_ERROR,
  1956. "CMSPAddress::GetDefaultStaticTerminal - "
  1957. "UpdateTerminalList failed - returning 0x%08x", hr));
  1958. return hr;
  1959. }
  1960. }
  1961. //
  1962. // For each terminal in the list of terminals we created...
  1963. //
  1964. int iSize = m_Terminals.GetSize();
  1965. for (int i = 0; i < iSize; i++)
  1966. {
  1967. ITTerminal * pTerminal = m_Terminals[i];
  1968. HRESULT hr;
  1969. //
  1970. // Make sure this is the right direction.
  1971. //
  1972. TERMINAL_DIRECTION dir;
  1973. hr = pTerminal->get_Direction(&dir);
  1974. if (FAILED(hr))
  1975. {
  1976. LOG((MSP_WARN,
  1977. "CMSPAddress::GetDefaultStaticTerminal - "
  1978. "could not get terminal direction - skipping"));
  1979. continue;
  1980. }
  1981. if ( dir != Direction )
  1982. {
  1983. continue;
  1984. }
  1985. //
  1986. // Make sure this is the right media type.
  1987. //
  1988. long lMediaTypeObserved;
  1989. hr = pTerminal->get_MediaType(&lMediaTypeObserved);
  1990. if (FAILED(hr))
  1991. {
  1992. LOG((MSP_WARN,
  1993. "CMSPAddress::GetDefaultStaticTerminal - "
  1994. "could not get terminal media type - skipping"));
  1995. continue;
  1996. }
  1997. if ( ( lMediaTypeObserved & lMediaType) == 0 )
  1998. {
  1999. continue;
  2000. }
  2001. //
  2002. // Ok, so this is the terminal we want. Addref it and give it to the
  2003. // caller.
  2004. //
  2005. pTerminal->AddRef();
  2006. *ppTerminal = pTerminal;
  2007. LOG((MSP_TRACE,
  2008. "CMSPAddress::GetDefaultStaticTerminal - "
  2009. "returned a terminal - exit S_OK"));
  2010. return S_OK;
  2011. }
  2012. //
  2013. // If we get here then we did not find any matching terminals.
  2014. //
  2015. LOG((MSP_TRACE,
  2016. "CMSPAddress::GetDefaultStaticTerminal - "
  2017. "no match - exit TAPI_E_NOITEMS"));
  2018. return TAPI_E_NOITEMS;
  2019. }
  2020. STDMETHODIMP CMSPAddress::get_PluggableSuperclasses(
  2021. OUT VARIANT * pVariant
  2022. )
  2023. {
  2024. LOG((MSP_TRACE,
  2025. "CMSPAddress::get_PluggableSuperclasses - enter"));
  2026. //
  2027. // Check parameters.
  2028. //
  2029. if ( MSPB_IsBadWritePtr(pVariant, sizeof(VARIANT) ) )
  2030. {
  2031. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2032. "bad pointer argument - exit E_POINTER"));
  2033. return E_POINTER;
  2034. }
  2035. //
  2036. // Get ITTemrinalManager2
  2037. //
  2038. ITTerminalManager2* pTermMgr2 = NULL;
  2039. HRESULT hr = E_FAIL;
  2040. hr = m_pITTerminalManager->QueryInterface(
  2041. IID_ITTerminalManager2, (void**)&pTermMgr2);
  2042. if( FAILED(hr) )
  2043. {
  2044. LOG((MSP_ERROR,
  2045. "CMSPAddress::get_PluggableSuperclasses - "
  2046. "QI for ITTerminalManager2 failed - returning 0x%08x", hr));
  2047. return hr;
  2048. }
  2049. //
  2050. // Create the collection object - see mspcoll.h
  2051. //
  2052. typedef CTapiIfCollection< ITPluggableTerminalSuperclassInfo* > SuperclassCollection;
  2053. CComObject<SuperclassCollection> * pCollection;
  2054. hr = CComObject<SuperclassCollection>::CreateInstance( &pCollection );
  2055. if ( FAILED(hr) )
  2056. {
  2057. //Clean-up
  2058. pTermMgr2->Release();
  2059. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2060. "can't create collection - exit 0x%08x", hr));
  2061. return hr;
  2062. }
  2063. //
  2064. // Get the Collection's IDispatch interface
  2065. //
  2066. IDispatch * pDispatch;
  2067. hr = pCollection->_InternalQueryInterface(
  2068. IID_IDispatch,
  2069. (void **) &pDispatch );
  2070. if ( FAILED(hr) )
  2071. {
  2072. //Clean-up
  2073. pTermMgr2->Release();
  2074. delete pCollection;
  2075. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2076. "QI for IDispatch on collection failed - exit 0x%08x", hr));
  2077. return hr;
  2078. }
  2079. //
  2080. // Find out how many superclasses are available.
  2081. //
  2082. DWORD dwNumSuperclasses = 0;
  2083. hr = pTermMgr2->GetPluggableSuperclasses(
  2084. &dwNumSuperclasses,
  2085. NULL);
  2086. if ( FAILED(hr) )
  2087. {
  2088. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2089. "can't get number of terminals - exit 0x%08x", hr));
  2090. //Clean-up
  2091. pTermMgr2->Release();
  2092. pDispatch->Release();
  2093. return hr;
  2094. }
  2095. //
  2096. // Allocate an array of IID.
  2097. //
  2098. IID* pSuperclassesIID = new IID[dwNumSuperclasses];
  2099. if ( pSuperclassesIID == NULL )
  2100. {
  2101. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2102. "can't allocate IIDs array - exit E_OUTOFMEMORY"));
  2103. //Clean-up
  2104. pTermMgr2->Release();
  2105. pDispatch->Release();
  2106. return E_OUTOFMEMORY;
  2107. }
  2108. //
  2109. // Fill in the array with actual pointers. We must do this before
  2110. // initializing the enumerator, because the enumerator may want to
  2111. // addref the interface pointers during initialize.
  2112. //
  2113. hr = pTermMgr2->GetPluggableSuperclasses(
  2114. &dwNumSuperclasses,
  2115. pSuperclassesIID
  2116. );
  2117. //
  2118. // Clean-up
  2119. //
  2120. pTermMgr2->Release();
  2121. if ( FAILED(hr) )
  2122. {
  2123. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2124. "can't get IIDs - exit 0x%08x", hr));
  2125. //Clean-up
  2126. pDispatch->Release();
  2127. delete[] pSuperclassesIID;
  2128. return hr;
  2129. }
  2130. //
  2131. // Allocate an array of ITPluggableTerminalSuperclassInfo
  2132. //
  2133. typedef ITPluggableTerminalSuperclassInfo* SuperclassPtr; // MS parser
  2134. SuperclassPtr * ppSuperclassesInfo = new SuperclassPtr[dwNumSuperclasses];
  2135. if ( ppSuperclassesInfo == NULL )
  2136. {
  2137. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2138. "can't allocate SuperclassPtr array - exit E_OUTOFMEMORY"));
  2139. //Clean-up
  2140. pDispatch->Release();
  2141. delete[] pSuperclassesIID;
  2142. return E_OUTOFMEMORY;
  2143. }
  2144. //
  2145. // Get ITPluggableTerminalSuperclassRegistration interface
  2146. //
  2147. ITPluggableTerminalSuperclassRegistration* pSuperclassReg = NULL;
  2148. hr = CoCreateInstance(
  2149. CLSID_PluggableSuperclassRegistration,
  2150. NULL,
  2151. CLSCTX_INPROC_SERVER,
  2152. IID_ITPluggableTerminalSuperclassRegistration,
  2153. (void**)&pSuperclassReg
  2154. );
  2155. if( FAILED(hr) )
  2156. {
  2157. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2158. "QI for ITPluggableTerminalSuperclassRegistration - exit 0x%08x",hr));
  2159. //Clean-up
  2160. pDispatch->Release();
  2161. delete[] pSuperclassesIID;
  2162. delete[] ppSuperclassesInfo;
  2163. return hr;
  2164. }
  2165. //
  2166. // Create the objects
  2167. //
  2168. for(DWORD dwIndex = 0; dwIndex < dwNumSuperclasses; dwIndex++)
  2169. {
  2170. //
  2171. // Get the string from the IID
  2172. //
  2173. LPOLESTR lpszCLSID = NULL;
  2174. hr = StringFromIID( pSuperclassesIID[dwIndex], &lpszCLSID);
  2175. if( FAILED(hr) )
  2176. {
  2177. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2178. "StringFromIID failed - exit 0x%08x",hr));
  2179. //Clean-up
  2180. pDispatch->Release();
  2181. delete[] pSuperclassesIID;
  2182. delete[] ppSuperclassesInfo;
  2183. pSuperclassReg->Release();
  2184. return hr;
  2185. }
  2186. //
  2187. // Get BSTR for IID
  2188. //
  2189. BSTR bstrCLSID = SysAllocString( lpszCLSID );
  2190. CoTaskMemFree( lpszCLSID ); // Clean-up
  2191. if( NULL == bstrCLSID)
  2192. {
  2193. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2194. "SysAllocString failed - exit E_OUTOFMEMORY"));
  2195. // Clean-up
  2196. pDispatch->Release();
  2197. delete[] pSuperclassesIID;
  2198. delete[] ppSuperclassesInfo;
  2199. pSuperclassReg->Release();
  2200. return E_OUTOFMEMORY;
  2201. }
  2202. //
  2203. // Read information from registry
  2204. //
  2205. hr = pSuperclassReg->put_CLSID( bstrCLSID);
  2206. if(FAILED(hr) )
  2207. {
  2208. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2209. "put_CLSID failed - exit 0x%08x",hr));
  2210. // Clean-up
  2211. pDispatch->Release();
  2212. delete[] pSuperclassesIID;
  2213. delete[] ppSuperclassesInfo;
  2214. pSuperclassReg->Release();
  2215. SysFreeString( bstrCLSID);
  2216. return hr;
  2217. }
  2218. hr = pSuperclassReg->GetTerminalSuperclassInfo();
  2219. if( FAILED(hr) )
  2220. {
  2221. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2222. "GetTerminalSuperclassInfo failed - exit 0x%08x",hr));
  2223. // Clean-up
  2224. pDispatch->Release();
  2225. delete[] pSuperclassesIID;
  2226. delete[] ppSuperclassesInfo;
  2227. pSuperclassReg->Release();
  2228. SysFreeString( bstrCLSID);
  2229. return hr;
  2230. }
  2231. //
  2232. // Get the name
  2233. //
  2234. BSTR bstrName = NULL;
  2235. pSuperclassReg->get_Name( &bstrName );
  2236. //
  2237. // Create the information object
  2238. //
  2239. CComObject<CPlugTerminalSuperclassInfo>* pSuperclassInfo = NULL;
  2240. hr = CComObject<CPlugTerminalSuperclassInfo>::CreateInstance(&pSuperclassInfo);
  2241. if( FAILED(hr) )
  2242. {
  2243. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2244. "CreateInstance failed - exit 0x%08x", hr));
  2245. //Clean-up
  2246. pDispatch->Release();
  2247. delete[] pSuperclassesIID;
  2248. delete[] ppSuperclassesInfo;
  2249. pSuperclassReg->Release();
  2250. SysFreeString( bstrCLSID );
  2251. SysFreeString( bstrName );
  2252. return hr;
  2253. }
  2254. //
  2255. // Get ITPluggableTerminalSuperclassInfo from this superclass
  2256. //
  2257. hr = pSuperclassInfo->QueryInterface(
  2258. IID_ITPluggableTerminalSuperclassInfo,
  2259. (void**)&ppSuperclassesInfo[dwIndex]
  2260. );
  2261. _ASSERTE(hr == S_OK);
  2262. //
  2263. // Set the fields
  2264. //
  2265. hr = pSuperclassInfo->put_Name( bstrName);
  2266. if( FAILED(hr) )
  2267. {
  2268. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2269. "put_Name failed - exit 0x%08x", hr));
  2270. //Clean-up
  2271. pDispatch->Release();
  2272. delete[] pSuperclassesIID;
  2273. delete[] ppSuperclassesInfo;
  2274. pSuperclassReg->Release();
  2275. SysFreeString( bstrCLSID );
  2276. SysFreeString( bstrName );
  2277. return hr;
  2278. }
  2279. hr = pSuperclassInfo->put_CLSID( bstrCLSID );
  2280. if( FAILED(hr) )
  2281. {
  2282. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - "
  2283. "put_CLSID failed - exit 0x%08x", hr));
  2284. //Clean-up
  2285. pDispatch->Release();
  2286. delete[] pSuperclassesIID;
  2287. delete[] ppSuperclassesInfo;
  2288. pSuperclassReg->Release();
  2289. SysFreeString( bstrCLSID );
  2290. SysFreeString( bstrName );
  2291. return hr;
  2292. }
  2293. //
  2294. // Clean-up
  2295. //
  2296. SysFreeString( bstrCLSID );
  2297. SysFreeString( bstrName );
  2298. }
  2299. //
  2300. // Clean-up the IIDs array
  2301. //
  2302. pSuperclassReg->Release();
  2303. delete[] pSuperclassesIID;
  2304. //
  2305. // Init the collection using an iterator -- pointers to the beginning and
  2306. // the ending element plus one. If it succeeds, this method addrefs each
  2307. // element of ppterminals by querying for IDispatch.
  2308. //
  2309. hr = pCollection->Initialize( dwNumSuperclasses,
  2310. ppSuperclassesInfo,
  2311. ppSuperclassesInfo + dwNumSuperclasses );
  2312. if( FAILED(hr) )
  2313. {
  2314. LOG((MSP_ERROR, "CMSPAddress::get_PluggableSuperclasses - exit "
  2315. "pCollection->Initialize failed. returns 0x%08x", hr));
  2316. delete[] ppSuperclassesInfo;
  2317. pDispatch->Release();
  2318. return hr;
  2319. }
  2320. //
  2321. // put the IDispatch interface pointer into the variant
  2322. //
  2323. LOG((MSP_INFO, "CMSPAddress::get_PluggableSuperclasses - "
  2324. "placing IDispatch value %08x in variant", pDispatch));
  2325. VariantInit(pVariant);
  2326. pVariant->vt = VT_DISPATCH;
  2327. pVariant->pdispVal = pDispatch;
  2328. LOG((MSP_TRACE, "CMSPAddress::get_PluggableSuperclasses - exit S_OK"));
  2329. return S_OK;
  2330. }
  2331. STDMETHODIMP CMSPAddress::EnumeratePluggableSuperclasses(
  2332. OUT IEnumPluggableSuperclassInfo** ppSuperclassEnumerator
  2333. )
  2334. {
  2335. LOG((MSP_TRACE,
  2336. "CMSPAddress::EnumeratePluggableSuperclasses - enter"));
  2337. //
  2338. // Check parameters.
  2339. //
  2340. if ( MSPB_IsBadWritePtr(ppSuperclassEnumerator, sizeof(IEnumPluggableTerminalClassInfo*) ) )
  2341. {
  2342. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2343. "bad pointer argument - exit E_POINTER"));
  2344. return E_POINTER;
  2345. }
  2346. //
  2347. // Get ITTemrinalManager2
  2348. //
  2349. ITTerminalManager2* pTermMgr2 = NULL;
  2350. HRESULT hr = E_FAIL;
  2351. hr = m_pITTerminalManager->QueryInterface(
  2352. IID_ITTerminalManager2, (void**)&pTermMgr2);
  2353. if( FAILED(hr) )
  2354. {
  2355. LOG((MSP_ERROR,
  2356. "CMSPAddress::EnumeratePluggableSuperclasses - "
  2357. "QI for ITTerminalManager2 failed - returning 0x%08x", hr));
  2358. return hr;
  2359. }
  2360. //
  2361. // Find out how many superclasses are available.
  2362. //
  2363. DWORD dwNumSuperclasses = 0;
  2364. hr = pTermMgr2->GetPluggableSuperclasses(
  2365. &dwNumSuperclasses,
  2366. NULL);
  2367. if ( FAILED(hr) )
  2368. {
  2369. // Clean-up
  2370. pTermMgr2->Release();
  2371. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2372. "can't get number of terminals - exit 0x%08x", hr));
  2373. return hr;
  2374. }
  2375. //
  2376. // Allocate an array of IID.
  2377. //
  2378. IID* pSuperclassesIID = new IID[dwNumSuperclasses];
  2379. if ( pSuperclassesIID == NULL )
  2380. {
  2381. // Clean-up
  2382. pTermMgr2->Release();
  2383. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2384. "can't allocate IIDs array - exit E_OUTOFMEMORY"));
  2385. return E_OUTOFMEMORY;
  2386. }
  2387. //
  2388. // Fill in the array with actual pointers. We must do this before
  2389. // initializing the enumerator, because the enumerator may want to
  2390. // addref the interface pointers during initialize.
  2391. //
  2392. hr = pTermMgr2->GetPluggableSuperclasses(
  2393. &dwNumSuperclasses,
  2394. pSuperclassesIID
  2395. );
  2396. //
  2397. // Clean-up
  2398. //
  2399. pTermMgr2->Release();
  2400. if ( FAILED(hr) )
  2401. {
  2402. //Clean-up
  2403. delete[] pSuperclassesIID;
  2404. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2405. "can't get IIDs - exit 0x%08x", hr));
  2406. return hr;
  2407. }
  2408. //
  2409. // Allocate an array of ITPluggableTerminalSuperclassInfo
  2410. //
  2411. typedef ITPluggableTerminalSuperclassInfo* SuperclassPtr; // MS parser
  2412. SuperclassPtr * ppSuperclassesInfo = new SuperclassPtr[dwNumSuperclasses];
  2413. if ( ppSuperclassesInfo == NULL )
  2414. {
  2415. // Clean-up
  2416. delete[] pSuperclassesIID;
  2417. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2418. "can't allocate SuperclassPtr array - exit E_OUTOFMEMORY"));
  2419. return E_OUTOFMEMORY;
  2420. }
  2421. //
  2422. // Get ITPluggableTerminalSuperclassRegistration interface
  2423. //
  2424. ITPluggableTerminalSuperclassRegistration* pSuperclassReg = NULL;
  2425. hr = CoCreateInstance(
  2426. CLSID_PluggableSuperclassRegistration,
  2427. NULL,
  2428. CLSCTX_INPROC_SERVER,
  2429. IID_ITPluggableTerminalSuperclassRegistration,
  2430. (void**)&pSuperclassReg
  2431. );
  2432. if( FAILED(hr) )
  2433. {
  2434. // Clean-up
  2435. delete[] pSuperclassesIID;
  2436. delete[] ppSuperclassesInfo;
  2437. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2438. "QI for ITPluggableTerminalSuperclassRegistration - exit 0x%08x",hr));
  2439. return hr;
  2440. }
  2441. //
  2442. // Create the objects
  2443. //
  2444. for(DWORD dwIndex = 0; dwIndex < dwNumSuperclasses; dwIndex++)
  2445. {
  2446. //
  2447. // Get the string from the IID
  2448. //
  2449. LPOLESTR lpszCLSID = NULL;
  2450. hr = StringFromIID( pSuperclassesIID[dwIndex], &lpszCLSID);
  2451. if( FAILED(hr) )
  2452. {
  2453. //Clean-up
  2454. delete[] pSuperclassesIID;
  2455. delete[] ppSuperclassesInfo;
  2456. pSuperclassReg->Release();
  2457. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2458. "StringFromIID failed - exit 0x%08x",hr));
  2459. return hr;
  2460. }
  2461. //
  2462. // Get BSTR for IID
  2463. //
  2464. BSTR bstrCLSID = SysAllocString( lpszCLSID );
  2465. CoTaskMemFree( lpszCLSID ); // Clean-up
  2466. if( NULL == bstrCLSID)
  2467. {
  2468. //Clean-up
  2469. delete[] pSuperclassesIID;
  2470. delete[] ppSuperclassesInfo;
  2471. pSuperclassReg->Release();
  2472. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2473. "SysAllocString failed - exit E_OUTOFMEMORY"));
  2474. return E_OUTOFMEMORY;
  2475. }
  2476. //
  2477. // Read information from registry
  2478. //
  2479. pSuperclassReg->put_CLSID( bstrCLSID);
  2480. hr = pSuperclassReg->GetTerminalSuperclassInfo();
  2481. if( FAILED(hr) )
  2482. {
  2483. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2484. "GetTerminalSuperclassInfo failed - exit 0x%08x",hr));
  2485. // Clean-up
  2486. delete[] pSuperclassesIID;
  2487. delete[] ppSuperclassesInfo;
  2488. pSuperclassReg->Release();
  2489. SysFreeString( bstrCLSID);
  2490. return hr;
  2491. }
  2492. //
  2493. // Get the name
  2494. //
  2495. BSTR bstrName = NULL;
  2496. pSuperclassReg->get_Name( &bstrName );
  2497. //
  2498. // Create the information object
  2499. //
  2500. CComObject<CPlugTerminalSuperclassInfo>* pSuperclassInfo = NULL;
  2501. hr = CComObject<CPlugTerminalSuperclassInfo>::CreateInstance(&pSuperclassInfo);
  2502. if( FAILED(hr) )
  2503. {
  2504. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2505. "CreateInstance failed - exit 0x%08x", hr));
  2506. // Clean-up
  2507. delete[] pSuperclassesIID;
  2508. delete[] ppSuperclassesInfo;
  2509. pSuperclassReg->Release();
  2510. SysFreeString( bstrCLSID );
  2511. SysFreeString( bstrName );
  2512. return hr;
  2513. }
  2514. //
  2515. // Get ITPluggableTerminalSuperclassInfo from this superclass
  2516. //
  2517. hr = pSuperclassInfo->QueryInterface(
  2518. IID_ITPluggableTerminalSuperclassInfo,
  2519. (void**)&ppSuperclassesInfo[dwIndex]
  2520. );
  2521. _ASSERTE( hr == S_OK );
  2522. //
  2523. // Set the fields
  2524. //
  2525. hr = pSuperclassInfo->put_Name( bstrName);
  2526. if(FAILED(hr) )
  2527. {
  2528. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2529. "put_Name failed - exit 0x%08x", hr));
  2530. // Clean-up
  2531. delete[] pSuperclassesIID;
  2532. delete[] ppSuperclassesInfo;
  2533. pSuperclassReg->Release();
  2534. SysFreeString( bstrCLSID );
  2535. SysFreeString( bstrName );
  2536. return hr;
  2537. }
  2538. hr = pSuperclassInfo->put_CLSID( bstrCLSID );
  2539. if(FAILED(hr) )
  2540. {
  2541. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2542. "put_CLSID failed - exit 0x%08x", hr));
  2543. // Clean-up
  2544. delete[] pSuperclassesIID;
  2545. delete[] ppSuperclassesInfo;
  2546. pSuperclassReg->Release();
  2547. SysFreeString( bstrCLSID );
  2548. SysFreeString( bstrName );
  2549. return hr;
  2550. }
  2551. //
  2552. // Clean-up
  2553. //
  2554. SysFreeString( bstrCLSID );
  2555. SysFreeString( bstrName );
  2556. }
  2557. //
  2558. // Clean-up the IIDs array
  2559. //
  2560. pSuperclassReg->Release();
  2561. delete[] pSuperclassesIID;
  2562. //
  2563. // Create the enumerator object.
  2564. //
  2565. typedef CSafeComEnum<IEnumPluggableSuperclassInfo,
  2566. &IID_IEnumPluggableSuperclassInfo,
  2567. ITPluggableTerminalSuperclassInfo*,
  2568. _CopyInterface<ITPluggableTerminalSuperclassInfo> > CEnumerator;
  2569. CComObject<CEnumerator> *pEnum = NULL;
  2570. hr = CComObject<CEnumerator>::CreateInstance(&pEnum);
  2571. if ( FAILED(hr) )
  2572. {
  2573. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2574. "can't create enumerator - exit 0x%08x", hr));
  2575. delete[] ppSuperclassesInfo;
  2576. return hr;
  2577. }
  2578. //
  2579. // Query for the desired interface.
  2580. //
  2581. hr = pEnum->_InternalQueryInterface(
  2582. IID_IEnumPluggableSuperclassInfo,
  2583. (void**) ppSuperclassEnumerator
  2584. );
  2585. if ( FAILED(hr) )
  2586. {
  2587. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2588. "can't get enumerator interface - exit 0x%08x", hr));
  2589. delete pEnum;
  2590. delete[] ppSuperclassesInfo;
  2591. return hr;
  2592. }
  2593. //
  2594. // Init the enumerator object.
  2595. //
  2596. hr = pEnum->Init(ppSuperclassesInfo,
  2597. ppSuperclassesInfo + dwNumSuperclasses,
  2598. NULL,
  2599. AtlFlagTakeOwnership);
  2600. if ( FAILED(hr) )
  2601. {
  2602. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableSuperclasses - "
  2603. "can't init enumerator - exit 0x%08x", hr));
  2604. (*ppSuperclassEnumerator)->Release();
  2605. delete[] ppSuperclassesInfo;
  2606. return hr;
  2607. }
  2608. LOG((MSP_TRACE, "CMSPAddress::EnumeratePluggableSuperclasses - exit S_OK"));
  2609. return S_OK;
  2610. }
  2611. STDMETHODIMP CMSPAddress::get_PluggableTerminalClasses(
  2612. IN BSTR bstrTerminalSuperclass,
  2613. IN long lMediaType,
  2614. OUT VARIANT * pVariant
  2615. )
  2616. {
  2617. LOG((MSP_TRACE,
  2618. "CMSPAddress::get_PluggableTerminalClasses - enter"));
  2619. //
  2620. // Check parameters.
  2621. //
  2622. if ( MSPB_IsBadWritePtr(pVariant, sizeof(VARIANT) ) )
  2623. {
  2624. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2625. "bad pointer argument - exit E_POINTER"));
  2626. return E_POINTER;
  2627. }
  2628. if( IsBadStringPtr( bstrTerminalSuperclass, (UINT)-1))
  2629. {
  2630. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2631. "bad pointer argument - exit E_INVALIDARG"));
  2632. return E_INVALIDARG;
  2633. }
  2634. IID iidSuperclass = IID_NULL;
  2635. HRESULT hr = IIDFromString( bstrTerminalSuperclass, &iidSuperclass);
  2636. if( FAILED(hr) )
  2637. {
  2638. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2639. "bad pointer argument - exit E_INVALIDARG"));
  2640. return E_INVALIDARG;
  2641. }
  2642. //
  2643. // Get ITTemrinalManager2
  2644. //
  2645. ITTerminalManager2* pTermMgr2 = NULL;
  2646. hr = m_pITTerminalManager->QueryInterface(
  2647. IID_ITTerminalManager2, (void**)&pTermMgr2);
  2648. if( FAILED(hr) )
  2649. {
  2650. LOG((MSP_ERROR,
  2651. "CMSPAddress::get_PluggableTerminalClasses - "
  2652. "QI for ITTerminalManager2 failed - returning 0x%08x", hr));
  2653. return hr;
  2654. }
  2655. //
  2656. // Create the collection object - see mspcoll.h
  2657. //
  2658. typedef CTapiIfCollection< ITPluggableTerminalClassInfo* > ClassCollection;
  2659. CComObject<ClassCollection> * pCollection;
  2660. hr = CComObject<ClassCollection>::CreateInstance( &pCollection );
  2661. if ( FAILED(hr) )
  2662. {
  2663. //Clean-up
  2664. pTermMgr2->Release();
  2665. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2666. "can't create collection - exit 0x%08x", hr));
  2667. return hr;
  2668. }
  2669. //
  2670. // Get the Collection's IDispatch interface
  2671. //
  2672. IDispatch * pDispatch;
  2673. hr = pCollection->_InternalQueryInterface(
  2674. IID_IDispatch,
  2675. (void **) &pDispatch );
  2676. if ( FAILED(hr) )
  2677. {
  2678. // Clean-up
  2679. pTermMgr2->Release();
  2680. delete pCollection;
  2681. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2682. "QI for IDispatch on collection failed - exit 0x%08x", hr));
  2683. return hr;
  2684. }
  2685. //
  2686. // Find out how many superclasses are available.
  2687. //
  2688. DWORD dwNumClasses = 0;
  2689. hr = pTermMgr2->GetPluggableTerminalClasses(
  2690. iidSuperclass,
  2691. lMediaType,
  2692. &dwNumClasses,
  2693. NULL);
  2694. if ( FAILED(hr) )
  2695. {
  2696. //Clean-up
  2697. pTermMgr2->Release();
  2698. pDispatch->Release();
  2699. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2700. "can't get number of terminals - exit 0x%08x", hr));
  2701. return hr;
  2702. }
  2703. //
  2704. // Allocate an array of IID.
  2705. //
  2706. IID* pClassesIID = new IID[dwNumClasses];
  2707. if ( pClassesIID == NULL )
  2708. {
  2709. //Clean-up
  2710. pTermMgr2->Release();
  2711. pDispatch->Release();
  2712. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2713. "can't allocate IIDs array - exit E_OUTOFMEMORY"));
  2714. return E_OUTOFMEMORY;
  2715. }
  2716. //
  2717. // Fill in the array with actual pointers. We must do this before
  2718. // initializing the enumerator, because the enumerator may want to
  2719. // addref the interface pointers during initialize.
  2720. //
  2721. hr = pTermMgr2->GetPluggableTerminalClasses(
  2722. iidSuperclass,
  2723. lMediaType,
  2724. &dwNumClasses,
  2725. pClassesIID
  2726. );
  2727. //
  2728. // Clean-up
  2729. //
  2730. pTermMgr2->Release();
  2731. if ( FAILED(hr) )
  2732. {
  2733. //Clean-up
  2734. pDispatch->Release();
  2735. delete[] pClassesIID;
  2736. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2737. "can't get IIDs - exit 0x%08x", hr));
  2738. return hr;
  2739. }
  2740. //
  2741. // Allocate an array of ITPluggableTerminalClassInfo
  2742. //
  2743. typedef ITPluggableTerminalClassInfo* ClassPtr;
  2744. ClassPtr * ppClassesInfo = new ClassPtr[dwNumClasses];
  2745. if ( ppClassesInfo == NULL )
  2746. {
  2747. //Clean-up
  2748. pDispatch->Release();
  2749. delete[] pClassesIID;
  2750. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2751. "can't allocate ClassPtr array - exit E_OUTOFMEMORY"));
  2752. return E_OUTOFMEMORY;
  2753. }
  2754. //
  2755. // Get ITPluggableTerminalClassRegistration interface
  2756. //
  2757. ITPluggableTerminalClassRegistration* pClassReg = NULL;
  2758. hr = CoCreateInstance(
  2759. CLSID_PluggableTerminalRegistration,
  2760. NULL,
  2761. CLSCTX_INPROC_SERVER,
  2762. IID_ITPluggableTerminalClassRegistration,
  2763. (void**)&pClassReg
  2764. );
  2765. if( FAILED(hr) )
  2766. {
  2767. //Clean-up
  2768. pDispatch->Release();
  2769. delete[] pClassesIID;
  2770. delete[] ppClassesInfo;
  2771. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2772. "QI for ITPluggableTerminalClassRegistration - exit 0x%08x",hr));
  2773. return hr;
  2774. }
  2775. //
  2776. // Create the objects
  2777. //
  2778. for(DWORD dwIndex = 0; dwIndex < dwNumClasses; dwIndex++)
  2779. {
  2780. //
  2781. // Get the string from the IID
  2782. //
  2783. LPOLESTR lpszPublicCLSID = NULL;
  2784. hr = StringFromIID( pClassesIID[dwIndex], &lpszPublicCLSID);
  2785. if( FAILED(hr) )
  2786. {
  2787. //Clean-up
  2788. pDispatch->Release();
  2789. delete[] pClassesIID;
  2790. delete[] ppClassesInfo;
  2791. pClassReg->Release();
  2792. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2793. "StringFromIID failed - exit 0x%08x",hr));
  2794. return hr;
  2795. }
  2796. //
  2797. // Get BSTR for IID
  2798. //
  2799. BSTR bstrPublicCLSID = SysAllocString( lpszPublicCLSID );
  2800. CoTaskMemFree( lpszPublicCLSID ); // Clean-up
  2801. if( NULL == bstrPublicCLSID)
  2802. {
  2803. //Clean-up
  2804. pDispatch->Release();
  2805. delete[] pClassesIID;
  2806. delete[] ppClassesInfo;
  2807. pClassReg->Release();
  2808. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2809. "SysAllocString failed - exit E_OUTOFMEMORY"));
  2810. return E_OUTOFMEMORY;
  2811. }
  2812. //
  2813. // Read information from registry
  2814. //
  2815. pClassReg->put_TerminalClass( bstrPublicCLSID);
  2816. hr = pClassReg->GetTerminalClassInfo(
  2817. bstrTerminalSuperclass);
  2818. if( FAILED(hr) )
  2819. {
  2820. // Clean-up
  2821. pDispatch->Release();
  2822. delete[] pClassesIID;
  2823. delete[] ppClassesInfo;
  2824. pClassReg->Release();
  2825. SysFreeString( bstrPublicCLSID);
  2826. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2827. "GetTerminalInfo failed - exit 0x%08x",hr));
  2828. return hr;
  2829. }
  2830. //
  2831. // Get the name
  2832. //
  2833. BSTR bstrName = NULL;
  2834. pClassReg->get_Name( &bstrName );
  2835. BSTR bstrCompany = NULL;
  2836. pClassReg->get_Company( &bstrCompany );
  2837. BSTR bstrVersion = NULL;
  2838. pClassReg->get_Version( &bstrVersion );
  2839. BSTR bstrCLSID = NULL;
  2840. pClassReg->get_CLSID( &bstrCLSID );
  2841. TMGR_DIRECTION Direction = TMGR_TD_CAPTURE;
  2842. pClassReg->get_Direction( &Direction );
  2843. long lMediaType = 0;
  2844. pClassReg->get_MediaTypes( &lMediaType );
  2845. //
  2846. // Create the information object
  2847. //
  2848. CComObject<CPlugTerminalClassInfo>* pClassInfo = NULL;
  2849. hr = CComObject<CPlugTerminalClassInfo>::CreateInstance(&pClassInfo);
  2850. if( FAILED(hr) )
  2851. {
  2852. //Clean-up
  2853. pDispatch->Release();
  2854. delete[] pClassesIID;
  2855. delete[] ppClassesInfo;
  2856. pClassReg->Release();
  2857. SysFreeString( bstrPublicCLSID );
  2858. SysFreeString( bstrName );
  2859. SysFreeString( bstrCompany );
  2860. SysFreeString( bstrVersion );
  2861. SysFreeString( bstrCLSID );
  2862. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - "
  2863. "CreateInstance failed - exit 0x%08x", hr));
  2864. return hr;
  2865. }
  2866. //
  2867. // Get ITPluggableTerminalClassInfo from this superclass
  2868. //
  2869. pClassInfo->QueryInterface(
  2870. IID_ITPluggableTerminalClassInfo,
  2871. (void**)&ppClassesInfo[dwIndex]
  2872. );
  2873. //
  2874. // Set the fields
  2875. //
  2876. if( NULL == bstrName)
  2877. {
  2878. bstrName = SysAllocString(L"");
  2879. }
  2880. pClassInfo->put_Name( bstrName);
  2881. pClassInfo->put_TerminalClass( bstrPublicCLSID );
  2882. if( NULL == bstrCompany)
  2883. {
  2884. bstrCompany = SysAllocString(L"");
  2885. }
  2886. pClassInfo->put_Company( bstrCompany );
  2887. if( NULL == bstrVersion)
  2888. {
  2889. bstrVersion = SysAllocString(L"");
  2890. }
  2891. pClassInfo->put_Version( bstrVersion );
  2892. if( NULL == bstrCLSID)
  2893. {
  2894. LPOLESTR lpszCLSID = NULL;
  2895. StringFromCLSID( CLSID_NULL, &lpszCLSID);
  2896. bstrCLSID = SysAllocString(lpszCLSID);
  2897. CoTaskMemFree( lpszCLSID);
  2898. }
  2899. pClassInfo->put_CLSID( bstrCLSID );
  2900. TERMINAL_DIRECTION TermDirection = TD_CAPTURE;
  2901. switch( Direction )
  2902. {
  2903. case TMGR_TD_RENDER:
  2904. TermDirection = TD_RENDER;
  2905. break;
  2906. case TMGR_TD_BOTH:
  2907. TermDirection = TD_BIDIRECTIONAL;
  2908. break;
  2909. case TMGR_TD_CAPTURE:
  2910. default:
  2911. TermDirection = TD_CAPTURE;
  2912. break;
  2913. }
  2914. hr = pClassInfo->put_Direction( TermDirection );
  2915. _ASSERTE(hr == S_OK );
  2916. hr = pClassInfo->put_MediaTypes( lMediaType );
  2917. _ASSERTE(hr == S_OK );
  2918. //
  2919. // Clean-up
  2920. //
  2921. SysFreeString( bstrPublicCLSID );
  2922. SysFreeString( bstrName );
  2923. SysFreeString( bstrCompany );
  2924. SysFreeString( bstrVersion );
  2925. SysFreeString( bstrCLSID );
  2926. }
  2927. //
  2928. // Clean-up the IIDs array
  2929. //
  2930. pClassReg->Release();
  2931. delete[] pClassesIID;
  2932. //
  2933. // Init the collection using an iterator -- pointers to the beginning and
  2934. // the ending element plus one. If it succeeds, this method addrefs each
  2935. // element of ppterminals by querying for IDispatch.
  2936. //
  2937. hr = pCollection->Initialize( dwNumClasses,
  2938. ppClassesInfo,
  2939. ppClassesInfo + dwNumClasses );
  2940. if( FAILED(hr) )
  2941. {
  2942. LOG((MSP_ERROR, "CMSPAddress::get_PluggableTerminalClasses - exit "
  2943. "pCollection->Initialize failed. returns 0x%08x", hr));
  2944. delete[] ppClassesInfo;
  2945. pDispatch->Release();
  2946. return hr;
  2947. }
  2948. //
  2949. // put the IDispatch interface pointer into the variant
  2950. //
  2951. LOG((MSP_INFO, "CMSPAddress::get_PluggableTerminalClasses - "
  2952. "placing IDispatch value %08x in variant", pDispatch));
  2953. VariantInit(pVariant);
  2954. pVariant->vt = VT_DISPATCH;
  2955. pVariant->pdispVal = pDispatch;
  2956. LOG((MSP_TRACE, "CMSPAddress::get_PluggableTerminalClasses - exit S_OK"));
  2957. return S_OK;
  2958. }
  2959. STDMETHODIMP CMSPAddress::EnumeratePluggableTerminalClasses(
  2960. IN CLSID iidTerminalSuperclass,
  2961. IN long lMediaType,
  2962. OUT IEnumPluggableTerminalClassInfo ** ppClassEnumerator
  2963. )
  2964. {
  2965. LOG((MSP_TRACE,
  2966. "CMSPAddress::EnumeratePluggableTerminalClasses - enter"));
  2967. //
  2968. // Check parameters.
  2969. //
  2970. if ( MSPB_IsBadWritePtr(ppClassEnumerator, sizeof(IEnumPluggableTerminalClassInfo *) ) )
  2971. {
  2972. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  2973. "bad pointer argument - exit E_POINTER"));
  2974. return E_POINTER;
  2975. }
  2976. LPOLESTR lpszCLSID = NULL;
  2977. HRESULT hr = StringFromCLSID( iidTerminalSuperclass, &lpszCLSID);
  2978. if( FAILED(hr) )
  2979. {
  2980. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  2981. "StringFromCLSID failed - exit 0x%08x", hr));
  2982. return hr;
  2983. }
  2984. BSTR bstrTerminalSuperclass = SysAllocString( lpszCLSID );
  2985. // Clean-up
  2986. CoTaskMemFree(lpszCLSID);
  2987. lpszCLSID = NULL;
  2988. if( NULL == bstrTerminalSuperclass )
  2989. {
  2990. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  2991. "SysAllocString failed - exit E_OUTOFMEMORY"));
  2992. return E_OUTOFMEMORY;
  2993. }
  2994. //
  2995. // Get ITTemrinalManager2
  2996. //
  2997. ITTerminalManager2* pTermMgr2 = NULL;
  2998. hr = m_pITTerminalManager->QueryInterface(
  2999. IID_ITTerminalManager2, (void**)&pTermMgr2);
  3000. if( FAILED(hr) )
  3001. {
  3002. //Clean-up
  3003. SysFreeString( bstrTerminalSuperclass );
  3004. LOG((MSP_ERROR,
  3005. "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3006. "QI for ITTerminalManager2 failed - returning 0x%08x", hr));
  3007. return hr;
  3008. }
  3009. //
  3010. // Find out how many superclasses are available.
  3011. //
  3012. DWORD dwNumClasses = 0;
  3013. hr = pTermMgr2->GetPluggableTerminalClasses(
  3014. iidTerminalSuperclass,
  3015. lMediaType,
  3016. &dwNumClasses,
  3017. NULL);
  3018. if ( FAILED(hr) )
  3019. {
  3020. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3021. "can't get number of terminals - exit 0x%08x", hr));
  3022. // Clean-up
  3023. SysFreeString( bstrTerminalSuperclass );
  3024. pTermMgr2->Release();
  3025. return hr;
  3026. }
  3027. //
  3028. // Allocate an array of IID.
  3029. //
  3030. IID* pClassesIID = new IID[dwNumClasses];
  3031. if ( pClassesIID == NULL )
  3032. {
  3033. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3034. "can't allocate IIDs array - exit E_OUTOFMEMORY"));
  3035. // Clean-up
  3036. SysFreeString( bstrTerminalSuperclass );
  3037. pTermMgr2->Release();
  3038. return E_OUTOFMEMORY;
  3039. }
  3040. //
  3041. // Fill in the array with actual pointers. We must do this before
  3042. // initializing the enumerator, because the enumerator may want to
  3043. // addref the interface pointers during initialize.
  3044. //
  3045. hr = pTermMgr2->GetPluggableTerminalClasses(
  3046. iidTerminalSuperclass,
  3047. lMediaType,
  3048. &dwNumClasses,
  3049. pClassesIID
  3050. );
  3051. //
  3052. // Clean-up
  3053. //
  3054. pTermMgr2->Release();
  3055. if ( FAILED(hr) )
  3056. {
  3057. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3058. "can't get IIDs - exit 0x%08x", hr));
  3059. // Clean-up
  3060. SysFreeString( bstrTerminalSuperclass );
  3061. delete[] pClassesIID;
  3062. return hr;
  3063. }
  3064. //
  3065. // Allocate an array of ITPluggableTerminalClassInfo
  3066. //
  3067. typedef ITPluggableTerminalClassInfo* ClassPtr;
  3068. ClassPtr * ppClassesInfo = new ClassPtr[dwNumClasses];
  3069. if ( ppClassesInfo == NULL )
  3070. {
  3071. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3072. "can't allocate ClassPtr array - exit E_OUTOFMEMORY"));
  3073. // Clean-up
  3074. SysFreeString( bstrTerminalSuperclass );
  3075. delete[] pClassesIID;
  3076. return E_OUTOFMEMORY;
  3077. }
  3078. //
  3079. // Get ITPluggableTerminalClassRegistration interface
  3080. //
  3081. ITPluggableTerminalClassRegistration* pClassReg = NULL;
  3082. hr = CoCreateInstance(
  3083. CLSID_PluggableTerminalRegistration,
  3084. NULL,
  3085. CLSCTX_INPROC_SERVER,
  3086. IID_ITPluggableTerminalClassRegistration,
  3087. (void**)&pClassReg
  3088. );
  3089. if( FAILED(hr) )
  3090. {
  3091. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3092. "QI for ITPluggableTerminalClassRegistration - exit 0x%08x",hr));
  3093. // Clean-up
  3094. SysFreeString( bstrTerminalSuperclass );
  3095. delete[] ppClassesInfo;
  3096. delete[] pClassesIID;
  3097. return hr;
  3098. }
  3099. //
  3100. // Create the objects
  3101. //
  3102. for(DWORD dwIndex = 0; dwIndex < dwNumClasses; dwIndex++)
  3103. {
  3104. //
  3105. // Get the string from the IID
  3106. //
  3107. LPOLESTR lpszPublicCLSID = NULL;
  3108. hr = StringFromIID( pClassesIID[dwIndex], &lpszPublicCLSID);
  3109. if( FAILED(hr) )
  3110. {
  3111. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3112. "StringFromIID failed - exit 0x%08x",hr));
  3113. // Clean-up
  3114. SysFreeString( bstrTerminalSuperclass );
  3115. delete[] pClassesIID;
  3116. delete[] ppClassesInfo;
  3117. pClassReg->Release();
  3118. return hr;
  3119. }
  3120. //
  3121. // Get BSTR for IID
  3122. //
  3123. BSTR bstrPublicCLSID = SysAllocString( lpszPublicCLSID );
  3124. CoTaskMemFree( lpszPublicCLSID ); // Clean-up
  3125. if( NULL == bstrPublicCLSID)
  3126. {
  3127. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3128. "SysAllocString failed - exit E_OUTOFMEMORY"));
  3129. // Clean-up
  3130. SysFreeString( bstrTerminalSuperclass );
  3131. delete[] pClassesIID;
  3132. delete[] ppClassesInfo;
  3133. pClassReg->Release();
  3134. return E_OUTOFMEMORY;
  3135. }
  3136. //
  3137. // Read information from registry
  3138. //
  3139. pClassReg->put_TerminalClass( bstrPublicCLSID);
  3140. hr = pClassReg->GetTerminalClassInfo(
  3141. bstrTerminalSuperclass);
  3142. if( FAILED(hr) )
  3143. {
  3144. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3145. "GetTerminalInfo failed - exit 0x%08x",hr));
  3146. // Clean-up
  3147. SysFreeString( bstrTerminalSuperclass );
  3148. delete[] pClassesIID;
  3149. delete[] ppClassesInfo;
  3150. pClassReg->Release();
  3151. SysFreeString( bstrPublicCLSID);
  3152. return hr;
  3153. }
  3154. //
  3155. // Get the name
  3156. //
  3157. BSTR bstrName = NULL;
  3158. pClassReg->get_Name( &bstrName );
  3159. BSTR bstrCompany = NULL;
  3160. pClassReg->get_Company( &bstrCompany );
  3161. BSTR bstrVersion = NULL;
  3162. pClassReg->get_Version( &bstrVersion );
  3163. BSTR bstrCLSID = NULL;
  3164. pClassReg->get_CLSID( &bstrCLSID );
  3165. TMGR_DIRECTION Direction = TMGR_TD_CAPTURE;
  3166. pClassReg->get_Direction( &Direction );
  3167. long lMediaType = 0;
  3168. pClassReg->get_MediaTypes( &lMediaType );
  3169. //
  3170. // Create the information object
  3171. //
  3172. CComObject<CPlugTerminalClassInfo>* pClassInfo = NULL;
  3173. hr = CComObject<CPlugTerminalClassInfo>::CreateInstance(&pClassInfo);
  3174. if( FAILED(hr) )
  3175. {
  3176. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3177. "CreateInstance failed - exit 0x%08x", hr));
  3178. // Clean-up
  3179. SysFreeString( bstrTerminalSuperclass );
  3180. delete[] pClassesIID;
  3181. delete[] ppClassesInfo;
  3182. pClassReg->Release();
  3183. SysFreeString( bstrPublicCLSID );
  3184. SysFreeString( bstrName );
  3185. SysFreeString( bstrCompany );
  3186. SysFreeString( bstrVersion );
  3187. SysFreeString( bstrCLSID );
  3188. return hr;
  3189. }
  3190. //
  3191. // Get ITPluggableTerminalClassInfo from this superclass
  3192. //
  3193. hr = pClassInfo->QueryInterface(
  3194. IID_ITPluggableTerminalClassInfo,
  3195. (void**)&ppClassesInfo[dwIndex]
  3196. );
  3197. _ASSERTE(hr == S_OK);
  3198. //
  3199. // Set the fields
  3200. //
  3201. if( NULL == bstrName)
  3202. {
  3203. bstrName = SysAllocString(L"");
  3204. }
  3205. pClassInfo->put_Name( bstrName);
  3206. pClassInfo->put_TerminalClass( bstrPublicCLSID );
  3207. if( NULL == bstrCompany)
  3208. {
  3209. bstrCompany = SysAllocString(L"");
  3210. }
  3211. pClassInfo->put_Company( bstrCompany );
  3212. if( NULL == bstrVersion)
  3213. {
  3214. bstrVersion = SysAllocString(L"");
  3215. }
  3216. pClassInfo->put_Version( bstrVersion );
  3217. if( NULL == bstrCLSID)
  3218. {
  3219. LPOLESTR lpszCLSID = NULL;
  3220. StringFromCLSID( CLSID_NULL, &lpszCLSID);
  3221. bstrCLSID = SysAllocString(lpszCLSID);
  3222. CoTaskMemFree( lpszCLSID);
  3223. }
  3224. pClassInfo->put_CLSID( bstrCLSID );
  3225. TERMINAL_DIRECTION TermDirection = TD_CAPTURE;
  3226. switch( Direction )
  3227. {
  3228. case TMGR_TD_RENDER:
  3229. TermDirection = TD_RENDER;
  3230. break;
  3231. case TMGR_TD_BOTH:
  3232. TermDirection = TD_BIDIRECTIONAL;
  3233. break;
  3234. case TMGR_TD_CAPTURE:
  3235. default:
  3236. TermDirection = TD_CAPTURE;
  3237. break;
  3238. }
  3239. pClassInfo->put_Direction( TermDirection );
  3240. pClassInfo->put_MediaTypes( lMediaType );
  3241. //
  3242. // Clean-up
  3243. //
  3244. SysFreeString( bstrPublicCLSID );
  3245. SysFreeString( bstrName );
  3246. SysFreeString( bstrCompany );
  3247. SysFreeString( bstrVersion );
  3248. SysFreeString( bstrCLSID );
  3249. }
  3250. //
  3251. // Clean-up the IIDs array
  3252. //
  3253. SysFreeString( bstrTerminalSuperclass );
  3254. delete[] pClassesIID;
  3255. pClassReg->Release();
  3256. //
  3257. // Create the enumerator object.
  3258. //
  3259. typedef CSafeComEnum<IEnumPluggableTerminalClassInfo,
  3260. &IID_IEnumPluggableTerminalClassInfo,
  3261. ITPluggableTerminalClassInfo*,
  3262. _CopyInterface<ITPluggableTerminalClassInfo> > CEnumerator;
  3263. CComObject<CEnumerator> *pEnum = NULL;
  3264. hr = CComObject<CEnumerator>::CreateInstance(&pEnum);
  3265. if ( FAILED(hr) )
  3266. {
  3267. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3268. "can't create enumerator - exit 0x%08x", hr));
  3269. delete[] ppClassesInfo;
  3270. return hr;
  3271. }
  3272. //
  3273. // Query for the desired interface.
  3274. //
  3275. hr = pEnum->_InternalQueryInterface(
  3276. IID_IEnumPluggableTerminalClassInfo,
  3277. (void**) ppClassEnumerator
  3278. );
  3279. if ( FAILED(hr) )
  3280. {
  3281. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3282. "can't get enumerator interface - exit 0x%08x", hr));
  3283. delete pEnum;
  3284. delete[] ppClassesInfo;
  3285. return hr;
  3286. }
  3287. //
  3288. // Init the enumerator object.
  3289. //
  3290. hr = pEnum->Init(ppClassesInfo,
  3291. ppClassesInfo + dwNumClasses,
  3292. NULL,
  3293. AtlFlagTakeOwnership);
  3294. if ( FAILED(hr) )
  3295. {
  3296. LOG((MSP_ERROR, "CMSPAddress::EnumeratePluggableTerminalClasses - "
  3297. "can't init enumerator - exit 0x%08x", hr));
  3298. (*ppClassEnumerator)->Release();
  3299. delete[] ppClassesInfo;
  3300. return hr;
  3301. }
  3302. LOG((MSP_TRACE, "CMSPAddress::EnumeratePluggableTerminalClasses - exit S_OK"));
  3303. return S_OK;
  3304. }
  3305. STDMETHODIMP CMSPAddress::GetEvent(
  3306. IN OUT DWORD * pdwSize,
  3307. OUT BYTE * pBuffer
  3308. )
  3309. /*++
  3310. Routine Description:
  3311. This method is called by TAPI3 to get detailed information about the
  3312. event that just happened. TAPI3 will normally do this after its event
  3313. is signaled. Locks the event list.
  3314. Arguments:
  3315. pMSPEvent
  3316. The MSP_EVENT
  3317. pdwSize
  3318. Pointer to a DWORD. On entry, indicates the size in bytes of the
  3319. buffer pointed to in pbuffer. On success, it will be filled in with
  3320. the actual number of bytes returned. If the buffer is not big enough,
  3321. the method will return TAPI_E_NOTENOUGHMEMORY, and it will be filled
  3322. in the with number of bytes needed.
  3323. pBuffer
  3324. Event buffer filled in by MSP with the relevant events
  3325. Return Value:
  3326. S_OK
  3327. E_OUTOFMEMORY
  3328. TAPI_E_NOEVENT
  3329. TAPI_E_NOTENOUGHMEMORY
  3330. --*/
  3331. {
  3332. // We trust TAPI3 not to give us bad pointers.
  3333. _ASSERTE(!MSPB_IsBadWritePtr(pdwSize, sizeof (DWORD *)));
  3334. _ASSERTE((*pdwSize == 0) ? TRUE :
  3335. !MSPB_IsBadWritePtr(pBuffer, sizeof(BYTE) * (*pdwSize)));
  3336. LOG((MSP_TRACE, "CMSPAddress::GetEvent"));
  3337. CLock lock(m_EventDataLock);
  3338. if (IsListEmpty(&m_EventList))
  3339. {
  3340. return TAPI_E_NOEVENT;
  3341. }
  3342. // retrieve first entry
  3343. PLIST_ENTRY pLE = m_EventList.Flink;
  3344. // convert list entry to structure pointer
  3345. PMSPEVENTITEM pItem = CONTAINING_RECORD(pLE, MSPEVENTITEM, Link);
  3346. if (pItem->MSPEventInfo.dwSize > *pdwSize)
  3347. {
  3348. *pdwSize = pItem->MSPEventInfo.dwSize;
  3349. return TAPI_E_NOTENOUGHMEMORY;
  3350. }
  3351. CopyMemory(pBuffer, &pItem->MSPEventInfo, pItem->MSPEventInfo.dwSize);
  3352. *pdwSize = pItem->MSPEventInfo.dwSize;
  3353. // remove the first entry from the event list.
  3354. RemoveHeadList(&m_EventList);
  3355. // free the memory.
  3356. FreeEventItem(pItem);
  3357. return S_OK;
  3358. }
  3359. HRESULT CMSPAddress::PostEvent(
  3360. IN MSPEVENTITEM * pEventItem
  3361. )
  3362. /*++
  3363. Routine Description:
  3364. This method is called by MSPCalls to post an event to TAPI3. This method
  3365. puts the event at the end of the event list and singals TAPI3.
  3366. Locks the event list.
  3367. Arguments:
  3368. EventItem
  3369. The event to be queued.
  3370. Return Value:
  3371. S_OK
  3372. E_OUTOFMEMORY
  3373. --*/
  3374. {
  3375. CLock lock(m_EventDataLock);
  3376. if (m_htEvent == NULL)
  3377. {
  3378. return E_UNEXPECTED; // the address was shut down.
  3379. }
  3380. InsertTailList(&m_EventList, &pEventItem->Link);
  3381. SetEvent(m_htEvent);
  3382. return S_OK;
  3383. }
  3384. //////////////////////////////////////////////////////////////////////////////
  3385. //////////////////////////////////////////////////////////////////////////////
  3386. //////////////////////////////////////////////////////////////////////////////
  3387. //////////////////////////////////////////////////////////////////////////////
  3388. //////////////////////////////////////////////////////////////////////////////
  3389. // OLE Automation wrappers
  3390. STDMETHODIMP CMSPAddress::get_StaticTerminals (
  3391. OUT VARIANT * pVariant
  3392. )
  3393. {
  3394. LOG((MSP_TRACE, "CMSPAddress::get_StaticTerminals - enter"));
  3395. //
  3396. // Check parameters.
  3397. //
  3398. if ( MSPB_IsBadWritePtr(pVariant, sizeof(VARIANT) ) )
  3399. {
  3400. LOG((MSP_ERROR, "CMSPAddress::get_StaticTerminals - "
  3401. "bad pointer argument - exit E_POINTER"));
  3402. return E_POINTER;
  3403. }
  3404. //
  3405. // create the collection object - see mspcoll.h
  3406. //
  3407. typedef CTapiIfCollection< ITTerminal * > TerminalCollection;
  3408. CComObject<TerminalCollection> * pCollection;
  3409. HRESULT hr = CComObject<TerminalCollection>::CreateInstance( &pCollection );
  3410. if ( FAILED(hr) )
  3411. {
  3412. LOG((MSP_ERROR, "CMSPAddress::get_StaticTerminals - "
  3413. "can't create collection - exit 0x%08x", hr));
  3414. return hr;
  3415. }
  3416. //
  3417. // get the Collection's IDispatch interface
  3418. //
  3419. IDispatch * pDispatch;
  3420. hr = pCollection->_InternalQueryInterface(IID_IDispatch,
  3421. (void **) &pDispatch );
  3422. if ( FAILED(hr) )
  3423. {
  3424. LOG((MSP_ERROR, "CMSPAddress::get_StaticTerminals - "
  3425. "QI for IDispatch on collection failed - exit 0x%08x", hr));
  3426. delete pCollection;
  3427. return hr;
  3428. }
  3429. //
  3430. // Find out how many terminals are available.
  3431. //
  3432. DWORD dwNumTerminals;
  3433. hr = GetStaticTerminals(&dwNumTerminals,
  3434. NULL);
  3435. if ( FAILED(hr) )
  3436. {
  3437. LOG((MSP_ERROR, "CMSPAddress::get_StaticTerminals - "
  3438. "can't get number of terminals - exit 0x%08x", hr));
  3439. pDispatch->Release();
  3440. return hr;
  3441. }
  3442. //
  3443. // Allocate an array of terminal pointers.
  3444. //
  3445. typedef ITTerminal * TermPtr;
  3446. TermPtr * ppTerminals = new TermPtr[dwNumTerminals];
  3447. if ( ppTerminals == NULL )
  3448. {
  3449. LOG((MSP_ERROR, "CMSPAddress::get_StaticTerminals - "
  3450. "can't allocate terminals array - exit E_OUTOFMEMORY"));
  3451. pDispatch->Release();
  3452. return E_OUTOFMEMORY;
  3453. }
  3454. //
  3455. // Fill in the array with actual pointers. We must do this before
  3456. // initializing the enumerator, because the enumerator may want to
  3457. // addref the interface pointers during initialize.
  3458. //
  3459. hr = GetStaticTerminals(&dwNumTerminals,
  3460. ppTerminals);
  3461. if ( FAILED(hr) )
  3462. {
  3463. LOG((MSP_ERROR, "CMSPAddress::get_StaticTerminals - "
  3464. "can't get terminals - exit 0x%08x", hr));
  3465. pDispatch->Release();
  3466. delete ppTerminals;
  3467. return hr;
  3468. }
  3469. //
  3470. // Init the collection using an iterator -- pointers to the beginning and
  3471. // the ending element plus one. If it succeeds, this method addrefs each
  3472. // element of ppterminals by querying for IDispatch.
  3473. //
  3474. hr = pCollection->Initialize( dwNumTerminals,
  3475. ppTerminals,
  3476. ppTerminals + dwNumTerminals );
  3477. //
  3478. // Release the ITTerminal reference to each terminal (leaving the
  3479. // IDispatch reference, if any). Then delete the array; the
  3480. // collection is now storing the pointers.
  3481. //
  3482. for (DWORD i = 0; i < dwNumTerminals; i++)
  3483. {
  3484. ppTerminals[i]->Release();
  3485. }
  3486. delete ppTerminals;
  3487. if (FAILED(hr))
  3488. {
  3489. LOG((MSP_ERROR, "CMSPAddress::get_StaticTerminals - "
  3490. "Initialize on collection failed - exit 0x%08x", hr));
  3491. pDispatch->Release();
  3492. return hr;
  3493. }
  3494. //
  3495. // put the IDispatch interface pointer into the variant
  3496. //
  3497. LOG((MSP_ERROR, "CMSPAddress::get_StaticTerminals - "
  3498. "placing IDispatch value %08x in variant", pDispatch));
  3499. VariantInit(pVariant);
  3500. pVariant->vt = VT_DISPATCH;
  3501. pVariant->pdispVal = pDispatch;
  3502. LOG((MSP_TRACE, "CMSPAddress::get_StaticTerminals - exit S_OK"));
  3503. return S_OK;
  3504. }
  3505. //////////////////////////////////////////////////////////////////////////////
  3506. //////////////////////////////////////////////////////////////////////////////
  3507. STDMETHODIMP CMSPAddress::EnumerateStaticTerminals (
  3508. OUT IEnumTerminal ** ppTerminalEnumerator
  3509. )
  3510. {
  3511. LOG((MSP_TRACE, "CMSPAddress::EnumerateStaticTerminals - "
  3512. "enter"));
  3513. //
  3514. // Check the return pointer.
  3515. //
  3516. if ( MSPB_IsBadWritePtr(ppTerminalEnumerator, sizeof(IEnumTerminal *) ) )
  3517. {
  3518. LOG((MSP_ERROR, "CMSPAddress::EnumerateStaticTerminals - "
  3519. "bad return pointer - exit E_POINTER"));
  3520. return E_POINTER;
  3521. }
  3522. //
  3523. // Create the enumerator object.
  3524. //
  3525. typedef _CopyInterface<ITTerminal> CCopy;
  3526. typedef CSafeComEnum<IEnumTerminal, &IID_IEnumTerminal,
  3527. ITTerminal *, CCopy> CEnumerator;
  3528. HRESULT hr;
  3529. CComObject<CEnumerator> *pEnum = NULL;
  3530. hr = CComObject<CEnumerator>::CreateInstance(&pEnum);
  3531. if ( FAILED(hr) )
  3532. {
  3533. LOG((MSP_ERROR, "CMSPAddress::EnumerateStaticTerminals - "
  3534. "can't create enumerator - exit 0x%08x", hr));
  3535. return hr;
  3536. }
  3537. //
  3538. // Query for the desired interface.
  3539. //
  3540. hr = pEnum->_InternalQueryInterface(IID_IEnumTerminal,
  3541. (void**) ppTerminalEnumerator);
  3542. if ( FAILED(hr) )
  3543. {
  3544. LOG((MSP_ERROR, "CMSPAddress::EnumerateStaticTerminals - "
  3545. "can't get enumerator interface - exit 0x%08x", hr));
  3546. delete pEnum;
  3547. return hr;
  3548. }
  3549. //
  3550. // Find out how many terminals are available.
  3551. //
  3552. DWORD dwNumTerminals;
  3553. hr = GetStaticTerminals(&dwNumTerminals,
  3554. NULL);
  3555. if ( FAILED(hr) )
  3556. {
  3557. LOG((MSP_ERROR, "CMSPAddress::EnumerateStaticTerminals - "
  3558. "can't get number of terminals - exit 0x%08x", hr));
  3559. (*ppTerminalEnumerator)->Release();
  3560. return hr;
  3561. }
  3562. //
  3563. // Allocate an array of terminal pointers.
  3564. //
  3565. typedef ITTerminal * TermPtr;
  3566. TermPtr * ppTerminals = new TermPtr[dwNumTerminals];
  3567. if ( ppTerminals == NULL )
  3568. {
  3569. LOG((MSP_ERROR, "CMSPAddress::EnumerateStaticTerminals - "
  3570. "can't allocate terminals array - exit E_OUTOFMEMORY"));
  3571. (*ppTerminalEnumerator)->Release();
  3572. return E_OUTOFMEMORY;
  3573. }
  3574. //
  3575. // Fill in the array with actual pointers. We must do this before
  3576. // initializing the enumerator, because the enumerator may want to
  3577. // addref the interface pointers during initialize.
  3578. //
  3579. hr = GetStaticTerminals(&dwNumTerminals,
  3580. ppTerminals);
  3581. if ( FAILED(hr) )
  3582. {
  3583. LOG((MSP_ERROR, "CMSPAddress::EnumerateStaticTerminals - "
  3584. "can't get terminals - exit 0x%08x", hr));
  3585. (*ppTerminalEnumerator)->Release();
  3586. delete ppTerminals;
  3587. return hr;
  3588. }
  3589. //
  3590. // Initialize the object with the array of pointers.
  3591. //
  3592. hr = pEnum->Init(ppTerminals,
  3593. ppTerminals + dwNumTerminals,
  3594. NULL,
  3595. AtlFlagTakeOwnership);
  3596. if (FAILED(hr))
  3597. {
  3598. LOG((MSP_ERROR, "CMSPCallBase::EnumerateStaticTerminals - "
  3599. "init enumerator failed - exit 0x%08x", hr));
  3600. for (DWORD i = 0; i < dwNumTerminals; i++)
  3601. {
  3602. ppTerminals[i]->Release();
  3603. }
  3604. delete ppTerminals;
  3605. (*ppTerminalEnumerator)->Release();
  3606. return hr;
  3607. }
  3608. LOG((MSP_TRACE, "CMSPAddress::EnumerateStaticTerminals - exit S_OK"));
  3609. return S_OK;
  3610. }
  3611. //////////////////////////////////////////////////////////////////////////////
  3612. //////////////////////////////////////////////////////////////////////////////
  3613. STDMETHODIMP CMSPAddress::get_DynamicTerminalClasses (
  3614. OUT VARIANT * pVariant
  3615. )
  3616. {
  3617. LOG((MSP_TRACE, "CMSPAddress::get_DynamicTerminalClasses - enter"));
  3618. //
  3619. // Check parameters.
  3620. //
  3621. if ( MSPB_IsBadWritePtr(pVariant, sizeof(VARIANT) ) )
  3622. {
  3623. LOG((MSP_ERROR, "CMSPAddress::get_DynamicTerminalClasses - "
  3624. "bad pointer argument - exit E_POINTER"));
  3625. return E_POINTER;
  3626. }
  3627. //
  3628. // create the collection object - see mspcoll.h
  3629. //
  3630. CComObject<CTapiBstrCollection> * pCollection;
  3631. HRESULT hr = CComObject<CTapiBstrCollection>::CreateInstance( &pCollection );
  3632. if ( FAILED(hr) )
  3633. {
  3634. LOG((MSP_ERROR, "CMSPAddress::get_DynamicTerminalClasses - "
  3635. "can't create collection - exit 0x%08x", hr));
  3636. return hr;
  3637. }
  3638. //
  3639. // get the Collection's IDispatch interface
  3640. //
  3641. IDispatch * pDispatch;
  3642. hr = pCollection->_InternalQueryInterface(IID_IDispatch,
  3643. (void **) &pDispatch );
  3644. if ( FAILED(hr) )
  3645. {
  3646. LOG((MSP_ERROR, "CMSPAddress::get_DynamicTerminalClasses - "
  3647. "QI for IDispatch on collection failed - exit 0x%08x", hr));
  3648. delete pCollection;
  3649. return hr;
  3650. }
  3651. //
  3652. // Find out how many terminals classes are available.
  3653. //
  3654. DWORD dwNumClasses;
  3655. hr = GetDynamicTerminalClasses(&dwNumClasses,
  3656. NULL);
  3657. if ( FAILED(hr) )
  3658. {
  3659. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3660. "can't get number of terminal classes - exit 0x%08x", hr));
  3661. pDispatch->Release();
  3662. return hr;
  3663. }
  3664. //
  3665. // Allocate an array of GUIDs.
  3666. //
  3667. IID * pClassGuids = new IID[dwNumClasses];
  3668. if ( pClassGuids == NULL )
  3669. {
  3670. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3671. "can't allocate class guids array - exit E_OUTOFMEMORY"));
  3672. pDispatch->Release();
  3673. return E_OUTOFMEMORY;
  3674. }
  3675. //
  3676. // Fill in the array with actual pointers.
  3677. //
  3678. hr = GetDynamicTerminalClasses(&dwNumClasses,
  3679. pClassGuids);
  3680. if ( FAILED(hr) )
  3681. {
  3682. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3683. "can't get terminal class guids - exit 0x%08x", hr));
  3684. pDispatch->Release();
  3685. delete [] pClassGuids;
  3686. return hr;
  3687. }
  3688. //
  3689. // Allocate an array of BSTRs.
  3690. //
  3691. BSTR * pClassBstrs = new BSTR[dwNumClasses];
  3692. if ( pClassBstrs == NULL )
  3693. {
  3694. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3695. "can't allocate class bstrs array - exit E_OUTOFMEMORY"));
  3696. pDispatch->Release();
  3697. delete [] pClassGuids;
  3698. return E_OUTOFMEMORY;
  3699. }
  3700. //
  3701. // Allocate a string for each GUID and copy it to the array,
  3702. // then delete the array of GUIDs.
  3703. //
  3704. const int BUFSIZE = 100;
  3705. WCHAR wszBuffer[BUFSIZE];
  3706. for (DWORD i = 0; i < dwNumClasses; i++)
  3707. {
  3708. int ret = StringFromGUID2(pClassGuids[i], wszBuffer, BUFSIZE);
  3709. _ASSERTE(ret != 0);
  3710. pClassBstrs[i] = SysAllocString(wszBuffer);
  3711. if ( pClassBstrs[i] == NULL )
  3712. {
  3713. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3714. "can't allocate a bstr - exit E_OUTOFMEMORY"));
  3715. for (DWORD j = 0; j < i; j++)
  3716. {
  3717. SysFreeString(pClassBstrs[j]);
  3718. }
  3719. delete [] pClassBstrs;
  3720. delete [] pClassGuids;
  3721. pDispatch->Release();
  3722. return E_OUTOFMEMORY;
  3723. }
  3724. }
  3725. delete [] pClassGuids;
  3726. //
  3727. // Init the collection using an iterator -- pointers to the beginning and
  3728. // the ending element plus one.
  3729. //
  3730. hr = pCollection->Initialize( dwNumClasses,
  3731. pClassBstrs,
  3732. pClassBstrs + dwNumClasses );
  3733. if ( FAILED(hr) )
  3734. {
  3735. LOG((MSP_ERROR, "CMSPAddress::get_DynamicTerminalClasses - "
  3736. "Initialize on collection failed - exit 0x%08x", hr));
  3737. pDispatch->Release();
  3738. for (DWORD k = 0; k < dwNumClasses; k++)
  3739. {
  3740. SysFreeString(pClassBstrs[k]);
  3741. }
  3742. delete [] pClassBstrs;
  3743. return hr;
  3744. }
  3745. delete [] pClassBstrs;
  3746. //
  3747. // put the IDispatch interface pointer into the variant
  3748. //
  3749. LOG((MSP_ERROR, "CMSPAddress::get_DynamicTerminalClasses - "
  3750. "placing IDispatch value %08x in variant", pDispatch));
  3751. VariantInit(pVariant);
  3752. pVariant->vt = VT_DISPATCH;
  3753. pVariant->pdispVal = pDispatch;
  3754. LOG((MSP_TRACE, "CMSPAddress::get_DynamicTerminalClasses - exit S_OK"));
  3755. return S_OK;
  3756. }
  3757. //////////////////////////////////////////////////////////////////////////////
  3758. //////////////////////////////////////////////////////////////////////////////
  3759. STDMETHODIMP CMSPAddress::EnumerateDynamicTerminalClasses (
  3760. OUT IEnumTerminalClass ** ppTerminalClassEnumerator
  3761. )
  3762. {
  3763. LOG((MSP_TRACE, "CMSPAddress::EnumerateDynamicTerminalClasses - enter"));
  3764. //
  3765. // Check the return pointer.
  3766. //
  3767. if ( MSPB_IsBadWritePtr(ppTerminalClassEnumerator,
  3768. sizeof(IEnumTerminalClass *) ) )
  3769. {
  3770. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3771. "bad return pointer - exit E_POINTER"));
  3772. return E_POINTER;
  3773. }
  3774. //
  3775. // Find out how many terminals classes are available.
  3776. //
  3777. HRESULT hr;
  3778. DWORD dwNumClasses;
  3779. hr = GetDynamicTerminalClasses(&dwNumClasses,
  3780. NULL);
  3781. if ( FAILED(hr) )
  3782. {
  3783. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3784. "can't get number of terminal classes - exit 0x%08x", hr));
  3785. return hr;
  3786. }
  3787. //
  3788. // Allocate an array of GUIDs.
  3789. //
  3790. IID * pClassGuids = new IID[dwNumClasses];
  3791. if ( pClassGuids == NULL )
  3792. {
  3793. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3794. "can't allocate class guids array - exit E_OUTOFMEMORY"));
  3795. return E_OUTOFMEMORY;
  3796. }
  3797. //
  3798. // Fill in the array with actual pointers.
  3799. //
  3800. hr = GetDynamicTerminalClasses(&dwNumClasses,
  3801. pClassGuids);
  3802. if ( FAILED(hr) )
  3803. {
  3804. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3805. "can't get terminal class guids - exit 0x%08x", hr));
  3806. delete [] pClassGuids;
  3807. return hr;
  3808. }
  3809. //
  3810. // Create an enumerator to hold this array, and have it take ownership
  3811. // so that it will delete the array when it is released. The CSafeComEnum
  3812. // can handle zero-length arrays. This Fn also checks the return arg.
  3813. //
  3814. //
  3815. // Create the enumerator object.
  3816. //
  3817. typedef CSafeComEnum<IEnumTerminalClass,
  3818. &IID_IEnumTerminalClass,
  3819. GUID, _Copy<GUID> > CEnumerator;
  3820. CComObject<CEnumerator> *pEnum = NULL;
  3821. hr = CComObject<CEnumerator>::CreateInstance(&pEnum);
  3822. if ( FAILED(hr) )
  3823. {
  3824. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3825. "can't create enumerator - exit 0x%08x", hr));
  3826. delete [] pClassGuids;
  3827. return hr;
  3828. }
  3829. //
  3830. // Query for the desired interface.
  3831. //
  3832. hr = pEnum->_InternalQueryInterface(IID_IEnumTerminalClass,
  3833. (void**) ppTerminalClassEnumerator);
  3834. if ( FAILED(hr) )
  3835. {
  3836. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3837. "can't get enumerator interface - exit 0x%08x", hr));
  3838. delete pEnum;
  3839. delete [] pClassGuids;
  3840. return hr;
  3841. }
  3842. //
  3843. // Init the enumerator object.
  3844. //
  3845. hr = pEnum->Init(pClassGuids,
  3846. pClassGuids + dwNumClasses,
  3847. NULL,
  3848. AtlFlagTakeOwnership);
  3849. if ( FAILED(hr) )
  3850. {
  3851. LOG((MSP_ERROR, "CMSPAddress::EnumerateDynamicTerminalClasses - "
  3852. "can't init enumerator - exit 0x%08x", hr));
  3853. (*ppTerminalClassEnumerator)->Release();
  3854. delete [] pClassGuids;
  3855. return hr;
  3856. }
  3857. LOG((MSP_TRACE, "CMSPAddress::EnumerateDynamicTerminalClasses - exit S_OK"));
  3858. return S_OK;
  3859. }
  3860. HRESULT CMSPAddress::ReceiveTSPAddressData(
  3861. IN PBYTE pBuffer,
  3862. IN DWORD dwSize
  3863. )
  3864. /*++
  3865. Routine Description:
  3866. Base class receive TSP address data method... does nothing in base class.
  3867. Implemented so that MSP's that only communicate per-call don't have
  3868. to override it.
  3869. Arguments:
  3870. Return Value:
  3871. S_OK
  3872. --*/
  3873. {
  3874. LOG((MSP_TRACE, "CMSPAddress::ReceiveTSPAddressData - enter"));
  3875. LOG((MSP_TRACE, "CMSPAddress::ReceiveTSPAddressData - exit S_OK"));
  3876. return S_OK;
  3877. }
  3878. HRESULT CMSPAddress::PnpNotifHandler(
  3879. IN BOOL bDeviceArrival
  3880. )
  3881. {
  3882. LOG((MSP_TRACE, "CMSPAddress::PnpNotifHandler - enter"));
  3883. if (bDeviceArrival)
  3884. LOG((MSP_TRACE, "CMSPAddress::PnpNotifHandler - device arrival"));
  3885. else
  3886. LOG((MSP_TRACE, "CMSPAddress::PnpNotifHandler - device removal"));
  3887. // lock the terminal related data. This is a auto lock that will unlock
  3888. // when the function returns.
  3889. CLock lock(m_TerminalDataLock);
  3890. // if the terminal list hasn't been built yet, we can skip doing anything
  3891. if (m_fTerminalsUpToDate)
  3892. {
  3893. HRESULT hr = UpdateTerminalListForPnp( bDeviceArrival );
  3894. if (FAILED(hr))
  3895. {
  3896. LOG((MSP_ERROR,
  3897. "CMSPAddress::PnpNotifHandler - "
  3898. "UpdateTerminalList failed - returning 0x%08x", hr));
  3899. return hr;
  3900. }
  3901. }
  3902. LOG((MSP_TRACE, "CMSPAddress::PnpNotifHandler - exit S_OK"));
  3903. return S_OK;
  3904. }
  3905. // eof