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.

1766 lines
48 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. line.cpp
  5. Abstract:
  6. TAPI Service Provider functions related to manipulating lines.
  7. TSPI_lineClose
  8. TSPI_lineGetDevCaps
  9. TSPI_lineGetLineDevStatus
  10. TSPI_lineGetNumAddressIDs
  11. TSPI_lineOpen
  12. Author:
  13. Nikhil Bobde (NikhilB)
  14. Revision History:
  15. --*/
  16. //
  17. // Include files
  18. //
  19. #include "globals.h"
  20. #include "line.h"
  21. #include "call.h"
  22. #include "q931obj.h"
  23. #include "ras.h"
  24. static LONG g_CTCallIdentity;
  25. CH323Line g_H323Line;
  26. H323_OCTETSTRING g_ProductID =
  27. {
  28. (BYTE*)H323_PRODUCT_ID,
  29. sizeof(H323_PRODUCT_ID)
  30. };
  31. H323_OCTETSTRING g_ProductVersion =
  32. {
  33. (BYTE*)H323_PRODUCT_VERSION,
  34. sizeof(H323_PRODUCT_VERSION)
  35. };
  36. //Queues a request made by TAPI to the thread pool
  37. BOOL
  38. QueueTAPILineRequest(
  39. IN DWORD EventID,
  40. IN HDRVCALL hdCall1,
  41. IN HDRVCALL hdCall2,
  42. IN DWORD dwDisconnectMode,
  43. IN WORD wCallReference)
  44. {
  45. BOOL fResult = TRUE;
  46. TAPI_LINEREQUEST_DATA * pLineRequestData = new TAPI_LINEREQUEST_DATA;
  47. H323DBG(( DEBUG_LEVEL_TRACE, "QueueTAPILineRequest entered." ));
  48. if( pLineRequestData != NULL )
  49. {
  50. pLineRequestData -> EventID = EventID;
  51. pLineRequestData -> hdCall1 = hdCall1;
  52. if( hdCall2 != NULL )
  53. {
  54. pLineRequestData -> hdCall2 = hdCall2;
  55. }
  56. else
  57. {
  58. pLineRequestData -> dwDisconnectMode = dwDisconnectMode;
  59. }
  60. pLineRequestData -> wCallReference = wCallReference;
  61. if( !QueueUserWorkItem( ProcessTAPILineRequest, pLineRequestData,
  62. WT_EXECUTEDEFAULT) )
  63. {
  64. delete pLineRequestData;
  65. fResult = FALSE;
  66. }
  67. }
  68. else
  69. {
  70. fResult = FALSE;
  71. }
  72. H323DBG(( DEBUG_LEVEL_TRACE, "QueueTAPILineRequest exited." ));
  73. return fResult;
  74. }
  75. #if DBG
  76. DWORD
  77. ProcessTAPILineRequest(
  78. IN PVOID ContextParameter
  79. )
  80. {
  81. __try
  82. {
  83. return ProcessTAPILineRequestFre( ContextParameter );
  84. }
  85. __except( 1 )
  86. {
  87. TAPI_LINEREQUEST_DATA* pRequestData = (TAPI_LINEREQUEST_DATA*)ContextParameter;
  88. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI %s event threw exception: %p, %p, %d.",
  89. EventIDToString(pRequestData -> EventID),
  90. pRequestData -> hdCall1,
  91. pRequestData -> hdCall2,
  92. pRequestData -> wCallReference ));
  93. _ASSERTE( FALSE );
  94. return 0;
  95. }
  96. }
  97. #endif
  98. DWORD
  99. ProcessTAPILineRequestFre(
  100. IN PVOID ContextParam
  101. )
  102. {
  103. _ASSERTE( ContextParam );
  104. PH323_CALL pCall = NULL;
  105. PH323_CALL pConsultCall = NULL;
  106. TAPI_LINEREQUEST_DATA* pLineRequestData = (TAPI_LINEREQUEST_DATA*)ContextParam;
  107. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI %s event recvd.",
  108. EventIDToString(pLineRequestData -> EventID) ));
  109. switch( pLineRequestData -> EventID )
  110. {
  111. case TSPI_CLOSE_CALL:
  112. g_pH323Line -> H323ReleaseCall(
  113. pLineRequestData->hdCall1,
  114. pLineRequestData->dwDisconnectMode,
  115. pLineRequestData->wCallReference );
  116. break;
  117. case TSPI_COMPLETE_TRANSFER:
  118. pConsultCall = g_pH323Line -> Find2H323CallsAndLock(
  119. pLineRequestData->hdCall2, pLineRequestData->hdCall1, &pCall );
  120. if( pConsultCall != NULL )
  121. {
  122. pConsultCall -> CompleteTransfer( pCall );
  123. pCall -> Unlock();
  124. pConsultCall -> Unlock();
  125. }
  126. break;
  127. }
  128. delete pLineRequestData;
  129. return EXIT_SUCCESS;
  130. }
  131. //
  132. // Private procedures
  133. //
  134. CH323Line::CH323Line()
  135. {
  136. m_nState = H323_LINESTATE_NONE;
  137. m_hdLine = NULL;
  138. m_htLine = NULL;
  139. m_dwDeviceID = -1;
  140. m_dwTSPIVersion = NULL;
  141. m_dwMediaModes = NULL;
  142. m_hdNextMSPHandle = NULL;
  143. m_wszAddr[0] = UNICODE_NULL;
  144. m_dwInitState = NULL;
  145. m_VendorInfo.bCountryCode = H221_COUNTRY_CODE_USA;
  146. m_VendorInfo.bExtension = H221_COUNTRY_EXT_USA;
  147. m_VendorInfo.wManufacturerCode = H221_MFG_CODE_MICROSOFT;
  148. m_VendorInfo.pProductNumber = &(g_ProductID);
  149. m_VendorInfo.pVersionNumber = &(g_ProductVersion);
  150. m_pCallForwardParams = NULL;
  151. m_dwInvokeID = 256;
  152. m_fForwardConsultInProgress = FALSE;
  153. }
  154. PH323_CALL
  155. CH323Line::Find2H323CallsAndLock (
  156. IN HDRVCALL hdCall1,
  157. IN HDRVCALL hdCall2,
  158. OUT PH323_CALL * ppCall2
  159. )
  160. {
  161. int iIndex1 = MakeCallIndex (hdCall1);
  162. int iIndex2 = MakeCallIndex (hdCall2);
  163. PH323_CALL pCall1 = NULL, pCall2 = NULL;
  164. H323DBG(( DEBUG_LEVEL_TRACE, "Find2H323CallsAndLock entered:%lx:%lx.",
  165. hdCall1, hdCall2 ));
  166. LockCallTable();
  167. //lock the call so that nobody else would be able to delete the call
  168. pCall1 = m_H323CallTable[iIndex1];
  169. if( pCall1 != NULL )
  170. {
  171. pCall1 -> Lock();
  172. if( pCall1->GetCallHandle() != hdCall1 )
  173. {
  174. pCall1 -> Unlock();
  175. pCall1 = NULL;
  176. }
  177. else
  178. {
  179. if( pCall2=m_H323CallTable[iIndex2] )
  180. {
  181. pCall2 -> Lock();
  182. if( pCall2->GetCallHandle() != hdCall2 )
  183. {
  184. pCall2 -> Unlock();
  185. pCall2 = NULL;
  186. pCall1 -> Unlock();
  187. pCall1 = NULL;
  188. }
  189. }
  190. else
  191. {
  192. pCall1 -> Unlock();
  193. pCall1 = NULL;
  194. }
  195. }
  196. }
  197. UnlockCallTable();
  198. *ppCall2 = pCall2;
  199. H323DBG(( DEBUG_LEVEL_TRACE, "Find2H323CallsAndLock exited:%lx:%lx.",
  200. hdCall1, hdCall2 ));
  201. return pCall1;
  202. }
  203. PH323_CALL
  204. CH323Line::FindH323CallAndLock (
  205. IN HDRVCALL hdCall)
  206. {
  207. H323DBG(( DEBUG_LEVEL_TRACE, "FindH323CallAndLock entered:%lx.", hdCall ));
  208. int iIndex = MakeCallIndex (hdCall);
  209. PH323_CALL pCall = NULL;
  210. LockCallTable();
  211. //lock the call so that nobody else would be able to delete the call
  212. if( pCall=m_H323CallTable[iIndex] )
  213. {
  214. pCall -> Lock();
  215. if( pCall->GetCallHandle() != hdCall )
  216. {
  217. pCall -> Unlock();
  218. pCall = NULL;
  219. }
  220. }
  221. UnlockCallTable();
  222. H323DBG(( DEBUG_LEVEL_TRACE, "FindH323CallAndLock exited:%p.", pCall ));
  223. return pCall;
  224. }
  225. PH323_CALL
  226. CH323Line::FindCallByARQSeqNumAndLock(
  227. WORD seqNumber
  228. )
  229. {
  230. PH323_CALL pCall = NULL;
  231. int iIndex;
  232. H323DBG(( DEBUG_LEVEL_TRACE, "FindCallByARQSeqNumAndLock entered:%d.",
  233. seqNumber ));
  234. LockCallTable();
  235. //lock the call so that nobody else would be able to delete the call
  236. for( iIndex=0; iIndex < m_H323CallTable.GetAllocSize(); iIndex++ )
  237. {
  238. if( pCall=m_H323CallTable[iIndex] )
  239. {
  240. if( pCall->GetARQSeqNumber() == seqNumber )
  241. {
  242. pCall -> Lock();
  243. break;
  244. }
  245. pCall = NULL;
  246. }
  247. }
  248. UnlockCallTable();
  249. H323DBG(( DEBUG_LEVEL_TRACE, "FindCallByARQSeqNumAndLock exited." ));
  250. return pCall;
  251. }
  252. //the code is replicated for the purpose of effeciency
  253. PH323_CALL
  254. CH323Line::FindCallByDRQSeqNumAndLock(
  255. WORD seqNumber
  256. )
  257. {
  258. PH323_CALL pCall = NULL;
  259. int iIndex;
  260. H323DBG(( DEBUG_LEVEL_TRACE, "FindCallByDRQSeqNumAndLock entered:%d.",
  261. seqNumber ));
  262. LockCallTable();
  263. //lock the call so that nobody else would be able to delete the call
  264. for( iIndex=0; iIndex < m_H323CallTable.GetAllocSize(); iIndex++ )
  265. {
  266. if( pCall=m_H323CallTable[iIndex] )
  267. {
  268. if( pCall->GetDRQSeqNumber() == seqNumber )
  269. {
  270. pCall -> Lock();
  271. break;
  272. }
  273. pCall = NULL;
  274. }
  275. }
  276. UnlockCallTable();
  277. H323DBG(( DEBUG_LEVEL_TRACE, "FindCallByDRQSeqNumAndLock exited:%d.",
  278. seqNumber ));
  279. return pCall;
  280. }
  281. //the code is replicated for the purpose of effeciency
  282. PH323_CALL
  283. CH323Line::FindCallByCallRefAndLock(
  284. WORD wCallRef
  285. )
  286. {
  287. PH323_CALL pCall = NULL;
  288. int iIndex;
  289. H323DBG(( DEBUG_LEVEL_TRACE, "FindCallByCallRefAndLock entered:%d.",
  290. wCallRef ));
  291. wCallRef &= 0x7fff;
  292. LockCallTable();
  293. //lock the call so that nobody else would be able to delete the call
  294. for( iIndex=0; iIndex < m_H323CallTable.GetAllocSize(); iIndex++ )
  295. {
  296. if( pCall=m_H323CallTable[iIndex] )
  297. {
  298. if( pCall->GetCallRef() == wCallRef )
  299. {
  300. pCall -> Lock();
  301. break;
  302. }
  303. pCall = NULL;
  304. }
  305. }
  306. UnlockCallTable();
  307. H323DBG(( DEBUG_LEVEL_TRACE, "FindCallByCallRefAndLock exited:%d.",
  308. wCallRef ));
  309. return pCall;
  310. }
  311. void
  312. CH323Line::RemoveFromCTCallIdentityTable(
  313. HDRVCALL hdCall )
  314. {
  315. int iIndex;
  316. PCTCALLID_CONTEXT pCTCallIDContext = NULL;
  317. H323DBG(( DEBUG_LEVEL_TRACE, "RemoveFromCTCallIdentityTable entered:%lx.",
  318. hdCall ));
  319. m_CTCallIDTable.Lock();
  320. for( iIndex=0; iIndex < m_CTCallIDTable.GetAllocSize(); iIndex++ )
  321. {
  322. pCTCallIDContext = m_CTCallIDTable[iIndex];
  323. if( pCTCallIDContext != NULL )
  324. {
  325. if( pCTCallIDContext -> hdCall == hdCall)
  326. {
  327. m_CTCallIDTable.RemoveAt(iIndex);
  328. }
  329. }
  330. }
  331. m_CTCallIDTable.Unlock();
  332. H323DBG(( DEBUG_LEVEL_TRACE, "RemoveFromCTCallIdentityTable exited:%lx.",
  333. hdCall ));
  334. }
  335. void
  336. CH323Line::ShutdownCTCallIDTable()
  337. {
  338. int iIndex;
  339. PCTCALLID_CONTEXT pCTCallIDContext = NULL;
  340. H323DBG(( DEBUG_LEVEL_TRACE, "ShutdownCTCallIDTable entered." ));
  341. m_CTCallIDTable.Lock();
  342. for( iIndex=0; iIndex < m_CTCallIDTable.GetAllocSize(); iIndex++ )
  343. {
  344. pCTCallIDContext = m_CTCallIDTable[iIndex];
  345. if( pCTCallIDContext != NULL )
  346. {
  347. delete pCTCallIDContext;
  348. m_CTCallIDTable[iIndex] = NULL;
  349. }
  350. }
  351. m_CTCallIDTable.Unlock();
  352. H323DBG(( DEBUG_LEVEL_TRACE, "ShutdownCTCallIDTable exited." ));
  353. }
  354. BOOL
  355. CH323Line::CallReferenceDuped(
  356. WORD wCallRef
  357. )
  358. {
  359. PH323_CALL pCall = NULL;
  360. int iIndex;
  361. H323DBG(( DEBUG_LEVEL_TRACE, "CallReferenceDuped entered:%d.", wCallRef ));
  362. wCallRef &= 0x7FFF;
  363. LockCallTable();
  364. for( iIndex=0; iIndex < m_H323CallTable.GetAllocSize(); iIndex++ )
  365. {
  366. if( pCall=m_H323CallTable[iIndex] )
  367. {
  368. if( pCall->GetCallRef() == wCallRef )
  369. {
  370. UnlockCallTable();
  371. return TRUE;
  372. }
  373. }
  374. }
  375. UnlockCallTable();
  376. H323DBG(( DEBUG_LEVEL_TRACE, "CallReferenceDuped exited:%d.", wCallRef ));
  377. return FALSE;
  378. }
  379. HDRVCALL
  380. CH323Line::GetCallFromCTCallIdentity(
  381. int iCTCallID
  382. )
  383. {
  384. int iIndex;
  385. PCTCALLID_CONTEXT pCTCallIDContext = NULL;
  386. H323DBG(( DEBUG_LEVEL_TRACE, "GetCallFromCTCallIdentity entered:%d.",
  387. iCTCallID ));
  388. m_CTCallIDTable.Lock();
  389. for( iIndex=0; iIndex < m_CTCallIDTable.GetAllocSize(); iIndex++ )
  390. {
  391. pCTCallIDContext = m_CTCallIDTable[iIndex];
  392. if( pCTCallIDContext != NULL )
  393. {
  394. if( pCTCallIDContext -> iCTCallIdentity == iCTCallID )
  395. {
  396. m_CTCallIDTable.Unlock();
  397. return (HDRVCALL)(pCTCallIDContext -> hdCall);
  398. }
  399. }
  400. }
  401. m_CTCallIDTable.Unlock();
  402. H323DBG(( DEBUG_LEVEL_TRACE, "GetCallFromCTCallIdentity exited:%d.",
  403. iCTCallID ));
  404. return NULL;
  405. }
  406. int
  407. CH323Line::GetCTCallIdentity(
  408. IN HDRVCALL hdCall)
  409. {
  410. int CTCallID = 0;
  411. int iIndex;
  412. PCTCALLID_CONTEXT pCTCallIDContext = NULL;
  413. H323DBG(( DEBUG_LEVEL_TRACE, "GetCTCallIdentity entered:%lx.", hdCall ));
  414. m_CTCallIDTable.Lock();
  415. do
  416. {
  417. g_CTCallIdentity++;
  418. if( g_CTCallIdentity == 10000 )
  419. {
  420. g_CTCallIdentity = 1;
  421. }
  422. //lock the call so that nobody else would be able to delete the call
  423. for( iIndex=0; iIndex < m_CTCallIDTable.GetAllocSize(); iIndex++ )
  424. {
  425. pCTCallIDContext = m_CTCallIDTable[iIndex] ;
  426. if( pCTCallIDContext != NULL )
  427. {
  428. if( pCTCallIDContext -> iCTCallIdentity == g_CTCallIdentity )
  429. {
  430. break;
  431. }
  432. }
  433. }
  434. if( iIndex == m_CTCallIDTable.GetAllocSize() )
  435. {
  436. CTCallID = g_CTCallIdentity;
  437. }
  438. }while( CTCallID == 0 );
  439. pCTCallIDContext = new CTCALLID_CONTEXT;
  440. if( pCTCallIDContext == NULL )
  441. {
  442. m_CTCallIDTable.Unlock();
  443. return 0;
  444. }
  445. pCTCallIDContext->iCTCallIdentity = CTCallID;
  446. pCTCallIDContext->hdCall = hdCall;
  447. if( m_CTCallIDTable.Add(pCTCallIDContext) == -1 )
  448. {
  449. m_CTCallIDTable.Unlock();
  450. delete pCTCallIDContext;
  451. return 0;
  452. }
  453. m_CTCallIDTable.Unlock();
  454. H323DBG(( DEBUG_LEVEL_TRACE, "GetCTCallIdentity exited:%lx.", hdCall ));
  455. return CTCallID;
  456. }
  457. void
  458. CH323Line::SetCallForwardParams(
  459. IN CALLFORWARDPARAMS* pCallForwardParams )
  460. {
  461. H323DBG(( DEBUG_LEVEL_TRACE, "SetCallForwardParams entered." ));
  462. if( m_pCallForwardParams != NULL )
  463. {
  464. FreeCallForwardParams( m_pCallForwardParams );
  465. m_pCallForwardParams = NULL;
  466. }
  467. m_pCallForwardParams = pCallForwardParams;
  468. H323DBG(( DEBUG_LEVEL_TRACE, "SetCallForwardParams exited." ));
  469. }
  470. BOOL
  471. CH323Line::SetCallForwardParams(
  472. IN LPFORWARDADDRESS pForwardAddress
  473. )
  474. {
  475. H323DBG(( DEBUG_LEVEL_TRACE, "SetCallForwardParams entered." ));
  476. if( m_pCallForwardParams != NULL )
  477. {
  478. pForwardAddress->next = m_pCallForwardParams->pForwardedAddresses;
  479. m_pCallForwardParams->pForwardedAddresses = pForwardAddress;
  480. }
  481. else
  482. {
  483. m_pCallForwardParams = new CALLFORWARDPARAMS;
  484. if( m_pCallForwardParams == NULL )
  485. {
  486. return FALSE;
  487. }
  488. ZeroMemory( m_pCallForwardParams, sizeof(CALLFORWARDPARAMS) );
  489. m_pCallForwardParams->fForwardingEnabled = TRUE;
  490. m_pCallForwardParams->pForwardedAddresses = pForwardAddress;
  491. pForwardAddress -> next = NULL;
  492. }
  493. //set unconditional forwarding
  494. m_pCallForwardParams->fForwardForAllOrigins = FALSE;
  495. H323DBG(( DEBUG_LEVEL_TRACE, "SetCallForwardParams exited." ));
  496. return TRUE;
  497. }
  498. CH323Line::~CH323Line()
  499. {
  500. if( m_dwInitState & LINEOBJECT_INITIALIZED )
  501. {
  502. DeleteCriticalSection (&m_CriticalSection);
  503. }
  504. }
  505. /*++
  506. Routine Description:
  507. Hangs up call (if necessary) and closes call object.
  508. Arguments:
  509. Handle of the call.
  510. Return Values:
  511. none.
  512. --*/
  513. void
  514. CH323Line::H323ReleaseCall(
  515. IN HDRVCALL hdCall,
  516. IN DWORD dwDisconnectMode,
  517. IN WORD wCallReference
  518. )
  519. {
  520. H323DBG(( DEBUG_LEVEL_TRACE, "H323ReleaseCall entered:%lx.", hdCall ));
  521. int iIndex = MakeCallIndex (hdCall);
  522. PH323_CALL pCall;
  523. BOOL fDelete = FALSE;
  524. LockCallTable();
  525. //lock the call so that nobody else would be able to delete the call
  526. if( (pCall=m_H323CallTable[iIndex]) && (hdCall==pCall->GetCallHandle()) )
  527. {
  528. pCall -> Lock();
  529. if( (wCallReference != 0) &&
  530. (wCallReference != pCall->GetCallRef()) )
  531. {
  532. //This message is for some other call. Ignore the message.
  533. H323DBG(( DEBUG_LEVEL_VERBOSE, "TSPI_CLOSE_CALL message ignored."));
  534. }
  535. else
  536. {
  537. // drop call using normal disconnect code
  538. pCall -> DropCall( dwDisconnectMode );
  539. pCall -> Shutdown( &fDelete );
  540. H323DBG(( DEBUG_LEVEL_VERBOSE, "call 0x%08lx closed.", pCall ));
  541. }
  542. pCall -> Unlock();
  543. //release the H323 call object
  544. if( fDelete == TRUE )
  545. {
  546. H323DBG(( DEBUG_LEVEL_VERBOSE, "call delete:0x%08lx.", pCall ));
  547. delete pCall;
  548. }
  549. }
  550. UnlockCallTable();
  551. H323DBG(( DEBUG_LEVEL_TRACE, "H323ReleaseCall exited: %p.", pCall ));
  552. }
  553. BOOL
  554. CH323Line::Initialize (
  555. IN DWORD dwLineDeviceIDBase)
  556. {
  557. DWORD dwSize;
  558. H323DBG((DEBUG_LEVEL_TRACE, "line Initialize entered."));
  559. if( m_dwInitState & LINEOBJECT_INITIALIZED )
  560. {
  561. return TRUE;
  562. }
  563. __try
  564. {
  565. if( !InitializeCriticalSectionAndSpinCount( &m_CriticalSection,
  566. 0x80000000 ) )
  567. {
  568. return FALSE;
  569. }
  570. }
  571. __except( 1 )
  572. {
  573. return FALSE;
  574. }
  575. m_dwDeviceID = dwLineDeviceIDBase;
  576. m_dwInitState = LINEOBJECT_INITIALIZED;
  577. //m_dwMediaModes = H323_LINE_MEDIAMODES;
  578. m_hdLine = (HDRVLINE__ *)this;
  579. m_dwNumRingsNoAnswer = H323_NUMRINGS_NOANSWER;
  580. dwSize = sizeof( m_wszAddr );
  581. //create displayable address
  582. GetComputerNameW( m_wszAddr, &dwSize );
  583. H323DBG(( DEBUG_LEVEL_TRACE, "line %d initialized (addr=%S)(hdLine=%d).",
  584. m_dwDeviceID, m_wszAddr, m_hdLine));
  585. // change line device state to closed
  586. m_nState = H323_LINESTATE_NONE;
  587. //init the mSP handles list
  588. m_MSPHandleList = NULL;
  589. H323DBG(( DEBUG_LEVEL_TRACE, "line Initialize exited." ));
  590. // success
  591. return TRUE;
  592. }
  593. BOOL
  594. CH323Line::AddMSPInstance(
  595. HTAPIMSPLINE htMSPLine,
  596. HDRVMSPLINE hdMSPLine )
  597. {
  598. MSPHANDLEENTRY* pMSPHandleEntry;
  599. H323DBG(( DEBUG_LEVEL_TRACE, "AddMSPInstance entered." ));
  600. Lock();
  601. pMSPHandleEntry = new MSPHANDLEENTRY;
  602. if( pMSPHandleEntry == NULL )
  603. {
  604. Unlock();
  605. return FALSE;
  606. }
  607. pMSPHandleEntry->htMSPLine = htMSPLine;
  608. pMSPHandleEntry->hdMSPLine = hdMSPLine;
  609. pMSPHandleEntry->next = m_MSPHandleList;
  610. m_MSPHandleList = pMSPHandleEntry;
  611. Unlock();
  612. H323DBG(( DEBUG_LEVEL_TRACE, "AddMSPInstance exited." ));
  613. return TRUE;
  614. }
  615. BOOL
  616. CH323Line::IsValidMSPHandle(
  617. HDRVMSPLINE hdMSPLine,
  618. HTAPIMSPLINE* phtMSPLine )
  619. {
  620. Lock();
  621. MSPHANDLEENTRY* pMSPHandle = m_MSPHandleList;
  622. while( pMSPHandle )
  623. {
  624. if( pMSPHandle->hdMSPLine == hdMSPLine )
  625. {
  626. *phtMSPLine = pMSPHandle->htMSPLine;
  627. Unlock();
  628. return TRUE;
  629. }
  630. pMSPHandle = pMSPHandle->next;
  631. }
  632. Unlock();
  633. return FALSE;
  634. }
  635. BOOL
  636. CH323Line::DeleteMSPInstance(
  637. HTAPIMSPLINE* phtMSPLine,
  638. HDRVMSPLINE hdMSPLine )
  639. {
  640. MSPHANDLEENTRY* pMSPHandle;
  641. MSPHANDLEENTRY* pMSPHandleDel;
  642. BOOL fRetVal = TRUE;
  643. H323DBG(( DEBUG_LEVEL_TRACE, "DeleteMSPInstance entered." ));
  644. Lock();
  645. if( m_MSPHandleList == NULL )
  646. {
  647. fRetVal = FALSE;
  648. goto func_exit;
  649. }
  650. if( m_MSPHandleList->hdMSPLine == hdMSPLine )
  651. {
  652. *phtMSPLine = m_MSPHandleList->htMSPLine;
  653. pMSPHandleDel = m_MSPHandleList;
  654. m_MSPHandleList = m_MSPHandleList->next;
  655. delete pMSPHandleDel;
  656. fRetVal = TRUE;
  657. goto func_exit;
  658. }
  659. for( pMSPHandle=m_MSPHandleList; pMSPHandle->next; pMSPHandle=pMSPHandle->next )
  660. {
  661. if( pMSPHandle->next->hdMSPLine == hdMSPLine )
  662. {
  663. *phtMSPLine = pMSPHandle->next->htMSPLine;
  664. pMSPHandleDel = pMSPHandle->next;
  665. pMSPHandle->next = pMSPHandle->next->next;
  666. delete pMSPHandleDel;
  667. fRetVal = TRUE;
  668. goto func_exit;
  669. }
  670. }
  671. func_exit:
  672. Unlock();
  673. H323DBG(( DEBUG_LEVEL_TRACE, "DeleteMSPInstance exited." ));
  674. return fRetVal;
  675. }
  676. //!!always called in a lock
  677. void
  678. CH323Line::ShutdownAllCalls(void)
  679. {
  680. PH323_CALL pCall;
  681. H323_CONFERENCE* pConf;
  682. DWORD indexI;
  683. DWORD dwSize;
  684. BOOL fDelete = FALSE;
  685. if( !(m_dwInitState & LINEOBJECT_INITIALIZED) )
  686. return;
  687. H323DBG((DEBUG_LEVEL_TRACE, "ShutdownAllCalls entered."));
  688. if( m_dwInitState & LINEOBJECT_SHUTDOWN )
  689. {
  690. return;
  691. }
  692. //shutdown all calls, delete all calls
  693. LockCallTable();
  694. dwSize = m_H323CallTable.GetAllocSize();
  695. for( indexI=0; indexI < dwSize; indexI++ )
  696. {
  697. pCall = m_H323CallTable[indexI];
  698. if( pCall != NULL )
  699. {
  700. pCall -> DropCall( 0 );
  701. pCall -> Shutdown(&fDelete);
  702. if(fDelete)
  703. {
  704. H323DBG((DEBUG_LEVEL_TRACE, "call delete:%p.", pCall ));
  705. delete pCall;
  706. }
  707. }
  708. }
  709. UnlockCallTable();
  710. dwSize = m_H323ConfTable.GetSize();
  711. for( indexI=0; indexI < dwSize; indexI++ )
  712. {
  713. pConf = m_H323ConfTable[indexI];
  714. //m_H323ConfTable.RemoveAt( indexI );
  715. if( pConf != NULL )
  716. {
  717. delete pConf;
  718. m_H323ConfTable[indexI] = NULL;
  719. }
  720. }
  721. H323DBG((DEBUG_LEVEL_TRACE, "ShutdownAllCalls exited."));
  722. }
  723. void
  724. CH323Line::Shutdown(void)
  725. {
  726. BOOL fDelete = FALSE;
  727. MSPHANDLEENTRY* pMSPHandle;
  728. if( !(m_dwInitState & LINEOBJECT_INITIALIZED) )
  729. {
  730. return;
  731. }
  732. H323DBG((DEBUG_LEVEL_TRACE, "line Shutdown entered."));
  733. Lock();
  734. if( m_dwInitState & LINEOBJECT_SHUTDOWN )
  735. {
  736. Unlock();
  737. return;
  738. }
  739. FreeCallForwardParams( m_pCallForwardParams );
  740. m_pCallForwardParams = NULL;
  741. Close();
  742. m_dwMediaModes = NULL;
  743. //m_hdLine = NULL;
  744. m_hdNextMSPHandle = NULL;
  745. m_htLine = NULL;
  746. //Free the MSP handles list
  747. while( m_MSPHandleList )
  748. {
  749. pMSPHandle = m_MSPHandleList;
  750. m_MSPHandleList = m_MSPHandleList->next;
  751. delete pMSPHandle;
  752. }
  753. m_dwInitState |= LINEOBJECT_SHUTDOWN;
  754. Unlock();
  755. H323DBG(( DEBUG_LEVEL_TRACE, "line Shutdown exited." ));
  756. }
  757. LONG
  758. CH323Line::CopyLineInfo(
  759. IN DWORD dwDeviceID,
  760. OUT LPLINEADDRESSCAPS pAddressCaps
  761. )
  762. {
  763. DWORD dwAddressSize;
  764. H323DBG((DEBUG_LEVEL_TRACE, "line CopyLineInfo entered."));
  765. // determine size of address name
  766. dwAddressSize = H323SizeOfWSZ( m_wszAddr );
  767. // calculate number of bytes needed
  768. pAddressCaps->dwNeededSize = sizeof(LINEADDRESSCAPS) +
  769. dwAddressSize
  770. ;
  771. // validate buffer allocated is large enough
  772. if (pAddressCaps->dwTotalSize >= pAddressCaps->dwNeededSize)
  773. {
  774. // record amount of memory used
  775. pAddressCaps->dwUsedSize = pAddressCaps->dwNeededSize;
  776. // position address name after fixed portion
  777. pAddressCaps->dwAddressSize = dwAddressSize;
  778. pAddressCaps->dwAddressOffset = sizeof(LINEADDRESSCAPS);
  779. // copy address name after fixed portion
  780. CopyMemory((LPBYTE)pAddressCaps + pAddressCaps->dwAddressOffset,
  781. (LPBYTE)m_wszAddr,
  782. pAddressCaps->dwAddressSize );
  783. }
  784. else if (pAddressCaps->dwTotalSize >= sizeof(LINEADDRESSCAPS))
  785. {
  786. H323DBG(( DEBUG_LEVEL_WARNING,
  787. "lineaddresscaps structure too small for strings." ));
  788. // record amount of memory used
  789. pAddressCaps->dwUsedSize = sizeof(LINEADDRESSCAPS);
  790. }
  791. else
  792. {
  793. H323DBG((DEBUG_LEVEL_ERROR, "lineaddresscaps structure too small."));
  794. // allocated structure too small
  795. return LINEERR_STRUCTURETOOSMALL;
  796. }
  797. H323DBG(( DEBUG_LEVEL_VERBOSE, "addr 0 capabilities requested." ));
  798. // transfer associated device id
  799. pAddressCaps->dwLineDeviceID = dwDeviceID;
  800. // initialize number of calls allowed per address
  801. pAddressCaps->dwMaxNumActiveCalls = H323_MAXCALLSPERADDR;
  802. // initialize supported address capabilities
  803. pAddressCaps->dwAddressSharing = H323_ADDR_ADDRESSSHARING;
  804. pAddressCaps->dwCallInfoStates = H323_ADDR_CALLINFOSTATES;
  805. pAddressCaps->dwCallStates = H323_ADDR_CALLSTATES;
  806. pAddressCaps->dwDisconnectModes = H323_ADDR_DISCONNECTMODES;
  807. pAddressCaps->dwAddrCapFlags = H323_ADDR_CAPFLAGS;
  808. pAddressCaps->dwCallFeatures = H323_ADDR_CALLFEATURES;
  809. pAddressCaps->dwAddressFeatures = H323_ADDR_ADDRFEATURES;
  810. pAddressCaps->dwCallerIDFlags = H323_ADDR_CALLPARTYIDFLAGS;
  811. pAddressCaps->dwCalledIDFlags = H323_ADDR_CALLPARTYIDFLAGS;
  812. // initialize unsupported address capabilities
  813. pAddressCaps->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
  814. pAddressCaps->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
  815. pAddressCaps->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
  816. H323DBG((DEBUG_LEVEL_TRACE, "line CopyLineInfo exited."));
  817. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineGetAddressCaps - Exited." ));
  818. // success
  819. return NOERROR;
  820. }
  821. /*++
  822. Routine Description:
  823. Initiate activities on line device and allocate resources.
  824. Arguments:
  825. htLine - TAPI's handle describing line device to open.
  826. dwTSPIVersion - The TSPI version negotiated through
  827. TSPI_lineNegotiateTSPIVersion under which the Service Provider is
  828. willing to operate.
  829. Return Values:
  830. Returns true if successful.
  831. --*/
  832. LONG CH323Line::Open(
  833. IN DWORD DeviceID,
  834. IN HTAPILINE TapiLine,
  835. IN DWORD TspiVersion,
  836. IN HDRVLINE * ReturnDriverLine)
  837. {
  838. HRESULT hr;
  839. LONG dwStatus = ERROR_SUCCESS;
  840. H323DBG(( DEBUG_LEVEL_TRACE, "H323 line open entered." ));
  841. if (GetDeviceID() != DeviceID)
  842. {
  843. // do not recognize device
  844. return LINEERR_BADDEVICEID;
  845. }
  846. // make sure this is a version we support
  847. if (!H323ValidateTSPIVersion (TspiVersion))
  848. {
  849. return LINEERR_INCOMPATIBLEAPIVERSION;
  850. }
  851. Lock();
  852. switch (m_nState)
  853. {
  854. case H323_LINESTATE_OPENED:
  855. H323DBG ((DEBUG_LEVEL_ERROR,
  856. "H323 line is already open (H323_LINESTATE_OPENED), cannot reopen"));
  857. dwStatus = LINEERR_INUSE;
  858. break;
  859. case H323_LINESTATE_LISTENING:
  860. H323DBG ((DEBUG_LEVEL_ERROR,
  861. "H323 line is already open (H323_LINESTATE_LISTENING), cannot reopen"));
  862. dwStatus = LINEERR_INUSE;
  863. break;
  864. case H323_LINESTATE_CLOSING:
  865. H323DBG ((DEBUG_LEVEL_ERROR,
  866. "H323 line cannot be opened (H323_LINESTATE_CLOSING)"));
  867. dwStatus = LINEERR_INVALLINESTATE;
  868. break;
  869. case H323_LINESTATE_OPENING:
  870. H323DBG ((DEBUG_LEVEL_ERROR,
  871. "H323 line cannot be opened (H323_LINESTATE_OPENING)"));
  872. dwStatus = LINEERR_INVALLINESTATE;
  873. break;
  874. case H323_LINESTATE_NONE:
  875. // attempt to open line device
  876. H323DBG ((DEBUG_LEVEL_TRACE, "H323 line is opening"));
  877. // start listen if necessary
  878. if (IsMediaDetectionEnabled())
  879. {
  880. hr = Q931AcceptStart();
  881. if (hr == S_OK)
  882. {
  883. dwStatus = ERROR_SUCCESS;
  884. RasStart();
  885. }
  886. else
  887. {
  888. H323DBG ((DEBUG_LEVEL_ERROR, "failed to listen on Q.931"));
  889. dwStatus = LINEERR_OPERATIONFAILED;
  890. }
  891. }
  892. if (dwStatus == ERROR_SUCCESS)
  893. {
  894. H323DBG ((DEBUG_LEVEL_TRACE, "H323 line successfully opened"));
  895. // save line variables now
  896. m_nState = IsMediaDetectionEnabled()?
  897. H323_LINESTATE_LISTENING:H323_LINESTATE_OPENED;
  898. m_htLine = TapiLine;
  899. m_dwTSPIVersion = TspiVersion;
  900. *ReturnDriverLine = (HDRVLINE) this;
  901. }
  902. else
  903. {
  904. Q931AcceptStop();
  905. }
  906. break;
  907. default:
  908. _ASSERTE( FALSE );
  909. }
  910. Unlock();
  911. H323DBG(( DEBUG_LEVEL_TRACE, "H323 line open exited." ));
  912. return dwStatus;
  913. }
  914. /*++
  915. Routine Description:
  916. Terminate activities on line device.
  917. Arguments:
  918. Return Values:
  919. Returns true if successful.
  920. --*/
  921. LONG
  922. CH323Line::Close(void)
  923. {
  924. LONG dwStatus;
  925. H323DBG(( DEBUG_LEVEL_TRACE, "H323 line close entered." ));
  926. Lock();
  927. switch (m_nState)
  928. {
  929. case H323_LINESTATE_OPENED:
  930. case H323_LINESTATE_LISTENING:
  931. if( m_fForwardConsultInProgress == TRUE )
  932. {
  933. H323DBG(( DEBUG_LEVEL_TRACE, "H323 line closed while forward is in progress." ));
  934. //Unlock();
  935. //return NOERROR;
  936. }
  937. // change line device state to closing
  938. m_nState = H323_LINESTATE_CLOSING;
  939. //shutdown all the calls
  940. ShutdownAllCalls();
  941. RasStop();
  942. if (IsMediaDetectionEnabled())
  943. {
  944. Q931AcceptStop();
  945. }
  946. ShutdownCTCallIDTable();
  947. // reset variables
  948. m_htLine = (HTAPILINE) NULL;
  949. m_dwTSPIVersion = 0;
  950. // change line device state to closed
  951. m_nState = H323_LINESTATE_NONE;
  952. dwStatus = ERROR_SUCCESS;
  953. break;
  954. default:
  955. H323DBG(( DEBUG_LEVEL_ERROR,
  956. "H323: lineclose called in bogus state:%d", m_nState ));
  957. dwStatus = LINEERR_OPERATIONFAILED;
  958. break;
  959. }
  960. Unlock();
  961. H323DBG(( DEBUG_LEVEL_TRACE, "H323 line close exited." ));
  962. return dwStatus;
  963. }
  964. //
  965. // TSPI procedures
  966. //
  967. /*++
  968. Routine Description:
  969. This function closes the specified open line device after completing or
  970. aborting all outstanding calls and asynchronous operations on the device.
  971. The Service Provider has the responsibility to (eventually) report
  972. completion for every operation it decides to execute asynchronously.
  973. If this procedure is called for a line on which there are outstanding
  974. asynchronous operations, the operations should be reported complete with an
  975. appropriate result or error code before this procedure returns. Generally
  976. the TAPI DLL would wait for these to complete in an orderly fashion.
  977. However, the Service Provider should be prepared to handle an early call to
  978. TSPI_lineClose in "abort" or "emergency shutdown" situtations.
  979. A similar requirement exists for active calls on the line. Such calls must
  980. be dropped, with outstanding operations reported complete with appropriate
  981. result or error codes.
  982. After this procedure returns the Service Provider must report no further
  983. events on the line or calls that were on the line. The Service Provider's
  984. opaque handles for the line and calls on the line become "invalid".
  985. The Service Provider must relinquish non-sharable resources it reserves
  986. while the line is open. For example, closing a line accessed through a
  987. comm port and modem should result in closing the comm port, making it once
  988. available for use by other applications.
  989. This function is presumed to complete successfully and synchronously.
  990. Arguments:
  991. hdLine - Specifies the Service Provider's opaque handle to the line to be
  992. closed. After the line has been successfully closed, this handle is
  993. no longer valid.
  994. Return Values:
  995. Returns zero if the function is successful, or a negative error
  996. number if an error has occurred. Possible error returns are:
  997. LINEERR_INVALLINEHANDLE - The specified device handle is invalid.
  998. LINEERR_OPERATIONFAILED - The specified operation failed for unknown
  999. reasons.
  1000. --*/
  1001. LONG
  1002. TSPIAPI
  1003. TSPI_lineClose (
  1004. IN HDRVLINE DriverLine)
  1005. {
  1006. _ASSERTE(DriverLine);
  1007. _ASSERTE(DriverLine == (HDRVLINE) &g_H323Line);
  1008. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineClose - Entered." ));
  1009. return ((CH323Line *) DriverLine) -> Close();
  1010. }
  1011. /*++
  1012. Routine Description:
  1013. This function queries a specified line device to determine its telephony
  1014. capabilities. The returned information is valid for all addresses on the
  1015. line device.
  1016. Line device ID numbering for a Service Provider is sequential from the
  1017. value set by the function TSPI_lineSetDeviceIDBase.
  1018. The dwExtVersion field of pLineDevCaps has already been filled in to
  1019. indicate the version number of the Extension information requested. If
  1020. it is zero, no Extension information is requested. If it is non-zero it
  1021. holds a value that has already been negotiated for this device with the
  1022. function TSPI_lineNegotiateExtVersion. The Service Provider should fill
  1023. in Extension information according to the Extension version specified.
  1024. One of the fields in the LINEDEVCAPS structure returned by this function
  1025. contains the number of addresses assigned to the specified line device.
  1026. The actual address IDs used to reference individual addresses vary from
  1027. zero to one less than the returned number. The capabilities of each
  1028. address may be different. Use TSPI_lineGetAddressCaps for each available
  1029. <dwDeviceID, dwAddressID> combination to determine the exact capabilities
  1030. of each address.
  1031. Arguments:
  1032. dwDeviceID - Specifies the line device to be queried.
  1033. dwTSPIVersion - Specifies the negotiated TSPI version number. This value
  1034. has already been negotiated for this device through the
  1035. TSPI_lineNegotiateTSPIVersion function.
  1036. pLineDevCaps - Specifies a far pointer to a variable sized structure of
  1037. type LINEDEVCAPS. Upon successful completion of the request, this
  1038. structure is filled with line device capabilities information.
  1039. Return Values:
  1040. Returns zero if the function is successful or a negative error
  1041. number if an error has occurred. Possible error returns are:
  1042. LINEERR_BADDEVICEID - The specified line device ID is out of range.
  1043. LINEERR_INCOMPATIBLEAPIVERSION - The application requested an API
  1044. version or version range that is either incompatible or cannot
  1045. be supported by the Telephony API implementation and/or
  1046. corresponding service provider.
  1047. LINEERR_STRUCTURETOOSMALL - The dwTotalSize member of a structure
  1048. does not specify enough memory to contain the fixed portion of
  1049. the structure. The dwNeededSize field has been set to the amount
  1050. required.
  1051. --*/
  1052. LONG
  1053. TSPIAPI
  1054. TSPI_lineGetDevCaps(
  1055. DWORD dwDeviceID,
  1056. DWORD dwTSPIVersion,
  1057. DWORD dwExtVersion,
  1058. LPLINEDEVCAPS pLineDevCaps
  1059. )
  1060. {
  1061. DWORD dwLineNameSize;
  1062. DWORD dwProviderInfoSize;
  1063. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineGetDevCaps - Entered." ));
  1064. if( g_pH323Line -> GetDeviceID() != dwDeviceID )
  1065. {
  1066. // do not recognize device
  1067. return LINEERR_BADDEVICEID;
  1068. }
  1069. // make sure this is a version we support
  1070. if (!H323ValidateTSPIVersion(dwTSPIVersion))
  1071. {
  1072. // do not support tspi version
  1073. return LINEERR_INCOMPATIBLEAPIVERSION;
  1074. }
  1075. // determine string lengths
  1076. dwProviderInfoSize = H323SizeOfWSZ(g_pwszProviderInfo);
  1077. dwLineNameSize = H323SizeOfWSZ(g_pwszLineName);
  1078. // calculate number of bytes required
  1079. pLineDevCaps->dwNeededSize = sizeof(LINEDEVCAPS) +
  1080. dwProviderInfoSize +
  1081. dwLineNameSize
  1082. ;
  1083. // make sure buffer is large enough for variable length data
  1084. if (pLineDevCaps->dwTotalSize >= pLineDevCaps->dwNeededSize)
  1085. {
  1086. // record amount of memory used
  1087. pLineDevCaps->dwUsedSize = pLineDevCaps->dwNeededSize;
  1088. // position provider info after fixed portion
  1089. pLineDevCaps->dwProviderInfoSize = dwProviderInfoSize;
  1090. pLineDevCaps->dwProviderInfoOffset = sizeof(LINEDEVCAPS);
  1091. // position line name after device class
  1092. pLineDevCaps->dwLineNameSize = dwLineNameSize;
  1093. pLineDevCaps->dwLineNameOffset =
  1094. pLineDevCaps->dwProviderInfoOffset +
  1095. pLineDevCaps->dwProviderInfoSize
  1096. ;
  1097. // copy provider info after fixed portion
  1098. CopyMemory((LPBYTE)pLineDevCaps + pLineDevCaps->dwProviderInfoOffset,
  1099. (LPBYTE)g_pwszProviderInfo,
  1100. pLineDevCaps->dwProviderInfoSize
  1101. );
  1102. // copy line name after device class
  1103. CopyMemory((LPBYTE)pLineDevCaps + pLineDevCaps->dwLineNameOffset,
  1104. (LPBYTE)g_pwszLineName,
  1105. pLineDevCaps->dwLineNameSize
  1106. );
  1107. }
  1108. else if (pLineDevCaps->dwTotalSize >= sizeof(LINEDEVCAPS))
  1109. {
  1110. H323DBG(( DEBUG_LEVEL_WARNING,
  1111. "linedevcaps structure too small for strings." ));
  1112. // structure only contains fixed portion
  1113. pLineDevCaps->dwUsedSize = sizeof(LINEDEVCAPS);
  1114. }
  1115. else
  1116. {
  1117. H323DBG(( DEBUG_LEVEL_WARNING, "linedevcaps structure too small." ));
  1118. // structure is too small
  1119. return LINEERR_STRUCTURETOOSMALL;
  1120. }
  1121. H323DBG(( DEBUG_LEVEL_VERBOSE, "line capabilities requested."));
  1122. // construct permanent line identifier
  1123. pLineDevCaps->dwPermanentLineID = (DWORD)MAKELONG(
  1124. dwDeviceID - g_dwLineDeviceIDBase,
  1125. g_dwPermanentProviderID
  1126. );
  1127. // notify tapi that strings returned are in unicode
  1128. pLineDevCaps->dwStringFormat = STRINGFORMAT_UNICODE;
  1129. // initialize line device capabilities
  1130. pLineDevCaps->dwNumAddresses = H323_MAXADDRSPERLINE;
  1131. pLineDevCaps->dwMaxNumActiveCalls = H323_MAXCALLSPERLINE;
  1132. pLineDevCaps->dwAddressModes = H323_LINE_ADDRESSMODES;
  1133. pLineDevCaps->dwBearerModes = H323_LINE_BEARERMODES;
  1134. pLineDevCaps->dwDevCapFlags = H323_LINE_DEVCAPFLAGS;
  1135. pLineDevCaps->dwLineFeatures = H323_LINE_LINEFEATURES;
  1136. pLineDevCaps->dwMaxRate = H323_LINE_MAXRATE;
  1137. pLineDevCaps->dwMediaModes = H323_LINE_MEDIAMODES;
  1138. pLineDevCaps->dwRingModes = 0;
  1139. // initialize address types to include phone numbers
  1140. pLineDevCaps->dwAddressTypes = H323_LINE_ADDRESSTYPES;
  1141. // line guid
  1142. pLineDevCaps->PermanentLineGuid = LINE_H323;
  1143. // modify GUID to be unique for each line
  1144. pLineDevCaps->PermanentLineGuid.Data1 +=
  1145. dwDeviceID - g_dwLineDeviceIDBase;
  1146. // protocol guid
  1147. pLineDevCaps->ProtocolGuid = TAPIPROTOCOL_H323;
  1148. // add dtmf support via H.245 user input messages
  1149. pLineDevCaps->dwGenerateDigitModes = LINEDIGITMODE_DTMF;
  1150. pLineDevCaps->dwMonitorDigitModes = LINEDIGITMODE_DTMF;
  1151. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineGetDevCaps - Exited." ));
  1152. // success
  1153. return NOERROR;
  1154. }
  1155. /*++
  1156. Routine Description:
  1157. This operation enables the TAPI DLL to query the specified open line
  1158. device for its current status.
  1159. The TAPI DLL uses TSPI_lineGetLineDevStatus to query the line device
  1160. for its current line status. This status information applies globally
  1161. to all addresses on the line device. Use TSPI_lineGetAddressStatus to
  1162. determine status information about a specific address on a line.
  1163. Arguments:
  1164. hdLine - Specifies the Service Provider's opaque handle to the line
  1165. to be queried.
  1166. pLineDevStatus - Specifies a far pointer to a variable sized data
  1167. structure of type LINEDEVSTATUS. Upon successful completion of
  1168. the request, this structure is filled with the line's device status.
  1169. Return Values:
  1170. Returns zero if the function is successful or a negative error
  1171. number if an error has occurred. Possible error returns are:
  1172. LINEERR_INVALLINEHANDLE - The specified line device handle is invalid.
  1173. LINEERR_STRUCTURETOOSMALL - The dwTotalSize member of a structure does
  1174. not specify enough memory to contain the fixed portion of the
  1175. structure. The dwNeededSize field has been set to the amount
  1176. required.
  1177. --*/
  1178. LONG
  1179. TSPIAPI
  1180. TSPI_lineGetLineDevStatus(
  1181. HDRVLINE hdLine,
  1182. LPLINEDEVSTATUS pLineDevStatus
  1183. )
  1184. {
  1185. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineGetDevStatus - Entered." ));
  1186. if( hdLine != g_pH323Line -> GetHDLine() )
  1187. {
  1188. return LINEERR_INVALLINEHANDLE;
  1189. }
  1190. // determine number of bytes needed
  1191. pLineDevStatus->dwNeededSize = sizeof(LINEDEVSTATUS);
  1192. // see if allocated structure is large enough
  1193. if (pLineDevStatus->dwTotalSize < pLineDevStatus->dwNeededSize)
  1194. {
  1195. H323DBG(( DEBUG_LEVEL_ERROR, "linedevstatus structure too small." ));
  1196. // structure too small
  1197. return LINEERR_STRUCTURETOOSMALL;
  1198. }
  1199. // record number of bytes used
  1200. pLineDevStatus->dwUsedSize = pLineDevStatus->dwNeededSize;
  1201. // initialize supported line device status fields
  1202. pLineDevStatus->dwLineFeatures = H323_LINE_LINEFEATURES;
  1203. pLineDevStatus->dwDevStatusFlags = H323_LINE_DEVSTATUSFLAGS;
  1204. // determine number of active calls on the line device
  1205. pLineDevStatus -> dwNumActiveCalls = g_pH323Line -> GetNoOfCalls();
  1206. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineGetDevStatus - Exited." ));
  1207. // success
  1208. return NOERROR;
  1209. }
  1210. /*++
  1211. Routine Description:
  1212. Retrieves the number of address IDs supported on the indicated line.
  1213. This function is called by TAPI.DLL in response to an application calling
  1214. lineSetNumRings, lineGetNumRings, or lineGetNewCalls. TAPI.DLL uses the
  1215. retrieved value to determine if the specified address ID is within the
  1216. range supported by the service provider.
  1217. Arguments:
  1218. hdLine - Specifies the handle to the line for which the number of address
  1219. IDs is to be retrieved.
  1220. pdwNumAddressIDs - Specifies a far pointer to a DWORD. The location is
  1221. filled with the number of address IDs supported on the indicated line.
  1222. The value should be one or larger.
  1223. Return Values:
  1224. Returns zero if the function is successful, or a negative error number
  1225. if an error has occurred. Possible return values are as follows:
  1226. LINEERR_INVALLINEHANDLE - The specified line device handle is invalid.
  1227. --*/
  1228. LONG
  1229. TSPIAPI
  1230. TSPI_lineGetNumAddressIDs(
  1231. HDRVLINE hdLine,
  1232. LPDWORD pdwNumAddressIDs
  1233. )
  1234. {
  1235. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineGetNumAddressIDs - Entered." ));
  1236. if( hdLine != g_pH323Line -> GetHDLine() )
  1237. {
  1238. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineGetNumAddressIDs - bad linehandle:%lx, %lx.",
  1239. hdLine, g_pH323Line -> GetHDLine() ));
  1240. return LINEERR_INVALLINEHANDLE ;
  1241. }
  1242. // transfer number of addresses
  1243. *pdwNumAddressIDs = H323_MAXADDRSPERLINE;
  1244. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineGetNumAddressIDs - Exited." ));
  1245. // success
  1246. return NOERROR;
  1247. }
  1248. /*++
  1249. Routine Description:
  1250. This function opens the line device whose device ID is given, returning
  1251. the Service Provider's opaque handle for the device and retaining the TAPI
  1252. DLL's opaque handle for the device for use in subsequent calls to the
  1253. LINEEVENT procedure.
  1254. Opening a line entitles the TAPI DLL to make further requests on the line.
  1255. The line becomes "active" in the sense that the TAPI DLL can initiate
  1256. outbound calls and the Service Provider can report inbound calls. The
  1257. Service Provider reserves whatever non-sharable resources are required to
  1258. manage the line. For example, opening a line accessed through a comm port
  1259. and modem should result in opening the comm port, making it no longer
  1260. available for use by other applications.
  1261. If the function is successful, both the TAPI DLL and the Service Provider
  1262. become committed to operating under the specified interface version number
  1263. for this open device. Subsquent operations and events identified using
  1264. the exchanged opaque line handles conform to that interface version. This
  1265. commitment and the validity of the handles remain in effect until the TAPI
  1266. DLL closes the line using the TSPI_lineClose operation or the Service
  1267. Provider reports the LINE_CLOSE event. If the function is not successful,
  1268. no such commitment is made and the handles are not valid.
  1269. Arguments:
  1270. dwDeviceID - Identifies the line device to be opened. The value
  1271. LINE_MAPPER for a device ID is not permitted.
  1272. htLine - Specifies the TAPI DLL's opaque handle for the line device to be
  1273. used in subsequent calls to the LINEEVENT callback procedure to
  1274. identify the device.
  1275. phdLine - A far pointer to a HDRVLINE where the Service Provider fills in
  1276. its opaque handle for the line device to be used by the TAPI DLL in
  1277. subsequent calls to identify the device.
  1278. dwTSPIVersion - The TSPI version negotiated through
  1279. TSPI_lineNegotiateTSPIVersion under which the Service Provider is
  1280. willing to operate.
  1281. pfnEventProc - A far pointer to the LINEEVENT callback procedure supplied
  1282. by the TAPI DLL that the Service Provider will call to report
  1283. subsequent events on the line.
  1284. Return Values:
  1285. Returns zero if the function is successful, or a negative error number
  1286. if an error has occurred. Possible return values are as follows:
  1287. LINEERR_BADDEVICEID - The specified line device ID is out of range.
  1288. LINEERR_INCOMPATIBLEAPIVERSION - The passed TSPI version or version
  1289. range did not match an interface version definition supported by
  1290. the service provider.
  1291. LINEERR_INUSE - The line device is in use and cannot currently be
  1292. configured, allow a party to be added, allow a call to be
  1293. answered, or allow a call to be placed.
  1294. LINEERR_OPERATIONFAILED - The operation failed for an unspecified or
  1295. unknown reason.
  1296. --*/
  1297. LONG
  1298. TSPIAPI
  1299. TSPI_lineOpen (
  1300. IN DWORD DeviceID,
  1301. IN HTAPILINE TapiLine,
  1302. IN LPHDRVLINE ReturnDriverLine,
  1303. IN DWORD TspiVersion,
  1304. IN LINEEVENT pfnEventProc)
  1305. {
  1306. return g_H323Line.Open (DeviceID, TapiLine, TspiVersion, ReturnDriverLine);
  1307. }
  1308. LONG
  1309. TSPIAPI
  1310. TSPI_lineCreateMSPInstance(
  1311. HDRVLINE hdLine,
  1312. DWORD dwAddressID,
  1313. HTAPIMSPLINE htMSPLine,
  1314. LPHDRVMSPLINE phdMSPLine
  1315. )
  1316. {
  1317. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineCreateMSPInstance - Entered." ));
  1318. if( hdLine != g_pH323Line -> GetHDLine() )
  1319. {
  1320. return LINEERR_RESOURCEUNAVAIL;
  1321. }
  1322. // We are not keeping the msp handles. Just fake a handle here.
  1323. *phdMSPLine = g_pH323Line->GetNextMSPHandle();
  1324. if( !g_pH323Line->AddMSPInstance( htMSPLine , *phdMSPLine ) )
  1325. {
  1326. return LINEERR_NOMEM;
  1327. }
  1328. H323DBG(( DEBUG_LEVEL_TRACE, "MSP instance created. hdMSP:%lx, htMSP:%lx.",
  1329. *phdMSPLine, htMSPLine ));
  1330. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineCreateMSPInstance - Exited." ));
  1331. // success
  1332. return NOERROR;
  1333. }
  1334. LONG
  1335. TSPIAPI
  1336. TSPI_lineCloseMSPInstance(
  1337. HDRVMSPLINE hdMSPLine
  1338. )
  1339. {
  1340. HTAPIMSPLINE htMSPLine;
  1341. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineCloseMSPInstance - Entered." ));
  1342. if( !g_pH323Line->DeleteMSPInstance( &htMSPLine , hdMSPLine ) )
  1343. {
  1344. return LINEERR_INVALPOINTER;
  1345. }
  1346. H323DBG(( DEBUG_LEVEL_TRACE, "MSP instance deleted. hdMSP:%lx, htMSP:%lx.",
  1347. hdMSPLine, htMSPLine ));
  1348. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineCloseMSPInstance - Exited." ));
  1349. // success
  1350. return NOERROR;
  1351. }