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.

3725 lines
112 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. confcall.cpp
  5. Abstract:
  6. TAPI Service Provider functions related to conference calls.
  7. TSPI_lineAddToConference
  8. TSPI_lineCompleteTransfer
  9. TSPI_linePrepareAddToConference
  10. TSPI_lineRemoveFromConference
  11. TSPI_lineSetupConference
  12. TSPI_lineSetupTransfer
  13. TSPI_lineDial
  14. TSPI_lineCompleteTransfer
  15. TSPI_lineForward
  16. TSPI_lineSetStatusMessage
  17. TSPI_lineRedirect
  18. TSPI_lineHold
  19. TSPI_lineUnhold
  20. Author:
  21. Nikhil Bobde (NikhilB)
  22. Revision History:
  23. --*/
  24. //
  25. // Include files
  26. //
  27. #include "globals.h"
  28. #include "line.h"
  29. #include "q931obj.h"
  30. #include "ras.h"
  31. #include "call.h"
  32. #define CALL_DIVERTNA_NUM_RINGS 8000
  33. extern DWORD g_dwTSPIVersion;
  34. //Queues a supplementary service work item to the thread pool
  35. BOOL
  36. QueueSuppServiceWorkItem(
  37. IN DWORD EventID,
  38. IN HDRVCALL hdCall,
  39. IN ULONG_PTR dwParam1
  40. )
  41. {
  42. SUPP_REQUEST_DATA * pCallRequestData = new SUPP_REQUEST_DATA;
  43. BOOL fResult = TRUE;
  44. if( pCallRequestData != NULL )
  45. {
  46. pCallRequestData -> EventID = EventID;
  47. pCallRequestData -> hdCall = hdCall;
  48. pCallRequestData -> dwParam1 = dwParam1;
  49. if( !QueueUserWorkItem( ProcessSuppServiceWorkItem,
  50. pCallRequestData, WT_EXECUTEDEFAULT) )
  51. {
  52. delete pCallRequestData;
  53. fResult = FALSE;
  54. }
  55. }
  56. else
  57. {
  58. fResult = FALSE;
  59. }
  60. return fResult;
  61. }
  62. #if DBG
  63. DWORD
  64. ProcessSuppServiceWorkItem(
  65. IN PVOID ContextParameter
  66. )
  67. {
  68. __try
  69. {
  70. return ProcessSuppServiceWorkItemFre( ContextParameter );
  71. }
  72. __except( 1 )
  73. {
  74. SUPP_REQUEST_DATA* pRequestData = (SUPP_REQUEST_DATA*)ContextParameter;
  75. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI %s event threw exception: %p, %p.",
  76. EventIDToString(pRequestData -> EventID),
  77. pRequestData -> hdCall,
  78. pRequestData -> dwParam1 ));
  79. _ASSERTE( FALSE );
  80. return 0;
  81. }
  82. }
  83. #endif
  84. DWORD
  85. ProcessSuppServiceWorkItemFre(
  86. IN PVOID ContextParameter
  87. )
  88. {
  89. _ASSERTE( ContextParameter );
  90. PH323_CALL pCall = NULL;
  91. SUPP_REQUEST_DATA* pRequestData = (SUPP_REQUEST_DATA*)ContextParameter;
  92. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI %s event recvd.",
  93. EventIDToString(pRequestData -> EventID) ));
  94. switch( pRequestData -> EventID )
  95. {
  96. case H450_PLACE_DIVERTEDCALL:
  97. g_pH323Line -> PlaceDivertedCall( pRequestData->hdCall,
  98. pRequestData->pAliasNames );
  99. break;
  100. case TSPI_DIAL_TRNASFEREDCALL:
  101. g_pH323Line -> PlaceTransferedCall( pRequestData->hdCall,
  102. pRequestData->pAliasNames );
  103. break;
  104. case SWAP_REPLACEMENT_CALL:
  105. g_pH323Line -> SwapReplacementCall( pRequestData->hdCall,
  106. pRequestData->hdReplacementCall, TRUE );
  107. break;
  108. case DROP_PRIMARY_CALL:
  109. g_pH323Line -> SwapReplacementCall( pRequestData->hdCall,
  110. pRequestData->hdReplacementCall, FALSE );
  111. break;
  112. case STOP_CTIDENTIFYRR_TIMER:
  113. pCall=g_pH323Line -> FindH323CallAndLock( pRequestData->hdCall );
  114. if( pCall != NULL )
  115. {
  116. pCall -> StopCTIdentifyRRTimer( pRequestData->hdReplacementCall );
  117. pCall -> Unlock();
  118. }
  119. else
  120. {
  121. //set the m_hdRelatedCall of dwParam1 to NULL
  122. }
  123. break;
  124. case SEND_CTINITIATE_MESSAGE:
  125. pCall=g_pH323Line -> FindH323CallAndLock(pRequestData->hdCall);
  126. if( pCall != NULL )
  127. {
  128. pCall -> SendCTInitiateMessagee( pRequestData->pCTIdentifyRes );
  129. pCall -> Unlock();
  130. }
  131. break;
  132. }
  133. delete ContextParameter;
  134. return EXIT_SUCCESS;
  135. }
  136. //!!must be always called in a lock
  137. void
  138. CH323Call::TransferInfoToDivertedCall(
  139. IN PH323_CALL pDivertedCall
  140. )
  141. {
  142. H323DBG(( DEBUG_LEVEL_TRACE, "TransferInfoToDivertedCall entered." ));
  143. pDivertedCall -> SetDivertedCallInfo(
  144. m_hdCall,
  145. m_pCallReroutingInfo,
  146. m_dwCallDiversionState,
  147. m_hdMSPLine,
  148. m_pCallerAliasNames,
  149. m_htMSPLine,
  150. m_pFastStart,
  151. m_hdRelatedCall,
  152. m_dwCallType,
  153. m_dwAppSpecific,
  154. &m_CallData );
  155. //reset the reference to this struct
  156. m_pCallReroutingInfo = NULL;
  157. m_pCallerAliasNames = NULL;
  158. m_dwCallDiversionState = H4503_CALLSTATE_IDLE;
  159. m_dwCallType = CALLTYPE_NORMAL;
  160. m_dwCallState = LINECALLSTATE_IDLE;
  161. m_pFastStart = NULL;
  162. ZeroMemory( (PVOID)&m_CallData, sizeof(H323_OCTETSTRING) );
  163. H323DBG(( DEBUG_LEVEL_TRACE, "TransferInfoToDivertedCall exited." ));
  164. }
  165. //!!always called in a lock
  166. BOOL
  167. CH323Call::TransferInfoToTransferedCall(
  168. IN PH323_CALL pTransferedCall
  169. )
  170. {
  171. H323DBG(( DEBUG_LEVEL_TRACE, "TransferInfoToTransferedCall entered." ));
  172. if( !pTransferedCall -> SetTransferedCallInfo(
  173. m_hdCall, m_pCallerAliasNames, m_pCTCallIdentity ) )
  174. {
  175. pTransferedCall -> Unlock();
  176. return FALSE;
  177. }
  178. m_hdRelatedCall = pTransferedCall -> GetCallHandle();
  179. H323DBG(( DEBUG_LEVEL_TRACE, "TransferInfoToTransferedCall exited." ));
  180. return TRUE;
  181. }
  182. void
  183. CH323Call::SetDivertedCallInfo(
  184. HDRVCALL hdCall,
  185. CALLREROUTINGINFO* pCallReroutingInfo,
  186. SUPP_CALLSTATE dwCallDiversionState,
  187. HDRVMSPLINE hdMSPLine,
  188. PH323_ALIASNAMES pCallerAliasNames,
  189. HTAPIMSPLINE htMSPLine,
  190. PH323_FASTSTART pFastStart,
  191. HDRVCALL hdRelatedCall,
  192. DWORD dwCallType,
  193. DWORD dwAppSpecific,
  194. PH323_OCTETSTRING pCallData
  195. )
  196. {
  197. H323DBG(( DEBUG_LEVEL_TRACE, "SetDivertedCallInfo entered:%p.", this ));
  198. Lock();
  199. m_hdCall = hdCall;
  200. m_pCallReroutingInfo = pCallReroutingInfo;
  201. m_dwCallDiversionState = dwCallDiversionState;
  202. m_hdMSPLine = hdMSPLine;
  203. m_htMSPLine = htMSPLine;
  204. FreeAliasNames( m_pCallerAliasNames );
  205. m_pCallerAliasNames = pCallerAliasNames;
  206. H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
  207. m_dwCallState = LINECALLSTATE_DIALING;
  208. m_pFastStart = pFastStart;
  209. m_CallData = *pCallData;
  210. m_dwAppSpecific = dwAppSpecific;
  211. //If the original call had any call type apart from being a diverted call
  212. //copy it.
  213. if( (dwCallType & CALLTYPE_TRANSFEREDSRC) ||
  214. (dwCallType & CALLTYPE_DIVERTEDTRANSFERED) )
  215. {
  216. m_dwCallType |= CALLTYPE_DIVERTEDTRANSFERED;
  217. m_hdRelatedCall = hdRelatedCall;
  218. }
  219. Unlock();
  220. H323DBG(( DEBUG_LEVEL_TRACE, "SetDivertedCallInfo exited:%p.", this ));
  221. }
  222. //!!must be always called in a lock
  223. BOOL
  224. CH323Call::SetTransferedCallInfo(
  225. HDRVCALL hdCall,
  226. PH323_ALIASNAMES pCallerAliasNames,
  227. BYTE * pCTCallIdentity
  228. )
  229. {
  230. H323DBG(( DEBUG_LEVEL_TRACE, "SetTransferedCallInfo entered:%p.", this ));
  231. m_hdRelatedCall = hdCall;
  232. m_pCallerAliasNames = NULL;
  233. if( (pCallerAliasNames != NULL) && (pCallerAliasNames->wCount != 0) )
  234. {
  235. m_pCallerAliasNames = new H323_ALIASNAMES;
  236. if( m_pCallerAliasNames == NULL )
  237. {
  238. return FALSE;
  239. }
  240. ZeroMemory( (PVOID)m_pCallerAliasNames, sizeof(H323_ALIASNAMES) );
  241. H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
  242. if( !AddAliasItem( m_pCallerAliasNames,
  243. pCallerAliasNames->pItems[0].pData,
  244. pCallerAliasNames->pItems[0].wType ) )
  245. {
  246. return FALSE;
  247. }
  248. H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
  249. }
  250. CopyMemory( (PVOID)m_pCTCallIdentity, pCTCallIdentity,
  251. sizeof(m_pCTCallIdentity) );
  252. m_dwCallState = LINECALLSTATE_DIALING;
  253. H323DBG(( DEBUG_LEVEL_TRACE, "SetTransferedCallInfo exited:%p.", this ));
  254. return TRUE;
  255. }
  256. void
  257. CH323Line::PlaceDivertedCall(
  258. IN HDRVCALL hdCall,
  259. IN PH323_ALIASNAMES divertedToAlias
  260. )
  261. {
  262. H323DBG(( DEBUG_LEVEL_TRACE, "PlaceDivertedCall entered:%p.", this ));
  263. int iIndex = MakeCallIndex( hdCall );
  264. int iDivertedCallIndex;
  265. PH323_CALL pCall;
  266. BOOL fDelete = FALSE;
  267. PH323_CALL pDivertedCall = NULL;
  268. Lock();
  269. LockCallTable();
  270. //lock the call so that nobody else would be able to delete the call
  271. if( (pCall=m_H323CallTable[iIndex]) != NULL )
  272. {
  273. pCall -> Lock();
  274. if( pCall->GetCallHandle() == hdCall )
  275. {
  276. pDivertedCall = pCall-> CreateNewDivertedCall( divertedToAlias );
  277. if( pDivertedCall == NULL )
  278. {
  279. pCall -> Unlock();
  280. UnlockCallTable();
  281. pCall->CloseCall( 0 );
  282. Unlock();
  283. return;
  284. }
  285. //remove the diverted call from the table
  286. iDivertedCallIndex = pDivertedCall -> GetCallIndex();
  287. m_H323CallTable[iDivertedCallIndex] = NULL;
  288. //transfer the required information to the diverted call.
  289. //put the original call in IDLE mode
  290. pCall -> TransferInfoToDivertedCall( pDivertedCall );
  291. //This DropCall is supposed to send only the DRQ if required
  292. pCall->DropCall( 0 );
  293. //close the original call
  294. pCall -> Shutdown( &fDelete );
  295. H323DBG(( DEBUG_LEVEL_VERBOSE, "call 0x%08lx closed.", pCall ));
  296. pCall -> Unlock();
  297. //release the original call object
  298. if( fDelete == TRUE )
  299. {
  300. H323DBG(( DEBUG_LEVEL_VERBOSE, "call delete:0x%08lx.", pCall ));
  301. delete pCall;
  302. }
  303. //place the diverted call in the place of the original call
  304. m_H323CallTable[iIndex] = pDivertedCall;
  305. }
  306. else
  307. {
  308. pCall -> Unlock();
  309. }
  310. }
  311. UnlockCallTable();
  312. //dial the diverted call
  313. if( pDivertedCall )
  314. {
  315. pDivertedCall -> DialCall();
  316. }
  317. Unlock();
  318. H323DBG(( DEBUG_LEVEL_TRACE, "PlaceDivertedCall exited:%p.", this ));
  319. }
  320. //!!always called in a lock
  321. PH323_CALL
  322. CH323Call::CreateNewDivertedCall(
  323. IN PH323_ALIASNAMES pwszCalleeAlias
  324. )
  325. {
  326. PH323_CONFERENCE pConf = NULL;
  327. BOOL fDelete = FALSE;
  328. PH323_CALL pCall = new CH323Call();
  329. H323DBG(( DEBUG_LEVEL_TRACE, "CreateNewDivertedCall entered:%p.", this ));
  330. if( pCall == NULL )
  331. {
  332. H323DBG(( DEBUG_LEVEL_ERROR,
  333. "could not allocate diverted call." ));
  334. return NULL;
  335. }
  336. // save tapi handle and specify outgoing call direction
  337. if( !pCall -> Initialize( m_htCall, LINECALLORIGIN_OUTBOUND,
  338. CALLTYPE_DIVERTEDSRC ) )
  339. {
  340. H323DBG(( DEBUG_LEVEL_ERROR,
  341. "could not allocate outgoing call." ));
  342. goto cleanup;
  343. }
  344. // bind outgoing call
  345. pConf = pCall -> CreateConference(NULL);
  346. if( pConf == NULL )
  347. {
  348. H323DBG(( DEBUG_LEVEL_ERROR,
  349. "could not create conference." ));
  350. goto cleanup;
  351. }
  352. if( !g_pH323Line -> GetH323ConfTable() -> Add(pConf) )
  353. {
  354. H323DBG(( DEBUG_LEVEL_ERROR, "could not add conf to conf table." ));
  355. goto cleanup;
  356. }
  357. if( pwszCalleeAlias->pItems[0].wType == e164_chosen )
  358. {
  359. pCall->SetAddressType( e164_chosen );
  360. }
  361. if (!RasIsRegistered())
  362. {
  363. if( !pCall->ResolveAddress( pwszCalleeAlias->pItems[0].pData ) )
  364. {
  365. goto cleanup;
  366. }
  367. }
  368. if( !pCall->SetCalleeAlias( pwszCalleeAlias->pItems[0].pData,
  369. pwszCalleeAlias->pItems[0].wType ) )
  370. {
  371. goto cleanup;
  372. }
  373. //send the informarion to the user that call has been diverted
  374. PostLineEvent(
  375. LINE_CALLINFO,
  376. LINECALLINFOSTATE_REDIRECTIONID,
  377. 0, 0 );
  378. H323DBG(( DEBUG_LEVEL_TRACE, "diverted call created:%p.", pCall ));
  379. H323DBG(( DEBUG_LEVEL_TRACE, "CreateNewDivertedCall exited.\n:%p", this ));
  380. return pCall;
  381. cleanup:
  382. if( pCall != NULL )
  383. {
  384. pCall -> Shutdown( &fDelete );
  385. delete pCall;
  386. H323DBG((DEBUG_LEVEL_TRACE, "call delete:%p.", pCall ));
  387. }
  388. return NULL;
  389. }
  390. //!!always called in a lock
  391. void
  392. CH323Call::Hold()
  393. {
  394. //1.Send MSP call hold message
  395. //2.Send hold H450 APDU
  396. if( m_dwCallState == LINECALLSTATE_ONHOLD )
  397. {
  398. return;
  399. }
  400. if( !SendQ931Message( NO_INVOKEID, 0, 0, FACILITYMESSAGETYPE,
  401. HOLDNOTIFIC_OPCODE | H450_INVOKE ) )
  402. {
  403. CloseCall( 0 );
  404. return;
  405. }
  406. SendMSPMessage( SP_MSG_Hold, 0, 1, NULL );
  407. //Call put on hold by local endpoint
  408. m_dwFlags |= TSPI_CALL_LOCAL_HOLD;
  409. ChangeCallState( LINECALLSTATE_ONHOLD, 0 );
  410. return;
  411. }
  412. //!!always called in a lock
  413. void
  414. CH323Call::UnHold()
  415. {
  416. //1.Send MSP call unhold message
  417. //2.Send unhold H450 APDU
  418. if( (m_dwCallState == LINECALLSTATE_ONHOLD) &&
  419. (m_dwFlags & TSPI_CALL_LOCAL_HOLD) )
  420. {
  421. if( !SendQ931Message( NO_INVOKEID, 0, 0, FACILITYMESSAGETYPE,
  422. RETRIEVENOTIFIC_OPCODE | H450_INVOKE ) )
  423. {
  424. CloseCall( 0 );
  425. return;
  426. }
  427. SendMSPMessage( SP_MSG_Hold, 0, 0, NULL );
  428. m_dwFlags &= (~TSPI_CALL_LOCAL_HOLD);
  429. ChangeCallState( LINECALLSTATE_CONNECTED, 0 );
  430. }
  431. return;
  432. }
  433. //!!always called in a lock
  434. void
  435. CH323Call::OnCallReroutingReceive(
  436. IN DWORD dwInvokeID
  437. )
  438. {
  439. H323DBG(( DEBUG_LEVEL_TRACE, "OnCallReroutingReceive entered:%p.", this ));
  440. if( (m_dwOrigin != LINECALLORIGIN_OUTBOUND) ||
  441. ( (m_dwStateMachine != Q931_SETUP_SENT) &&
  442. (m_dwStateMachine != Q931_PROCEED_RECVD) &&
  443. (m_dwStateMachine != Q931_ALERT_RECVD)
  444. )
  445. )
  446. {
  447. goto error;
  448. }
  449. //If setupsent timer is still alive stop it.
  450. if( m_hSetupSentTimer != NULL )
  451. {
  452. DeleteTimerQueueTimer( H323TimerQueue, m_hSetupSentTimer, NULL );
  453. m_hSetupSentTimer = NULL;
  454. }
  455. if( dwInvokeID != NO_INVOKEID )
  456. {
  457. if(!SendQ931Message( dwInvokeID,
  458. 0,
  459. 0,
  460. FACILITYMESSAGETYPE,
  461. CALLREROUTING_OPCODE | H450_RETURNRESULT ))
  462. {
  463. //goto error;
  464. }
  465. }
  466. m_fCallInTrnasition = TRUE;
  467. if( !SendQ931Message( NO_INVOKEID,
  468. 0,
  469. 0,
  470. RELEASECOMPLMESSAGETYPE,
  471. NO_H450_APDU) )
  472. {
  473. //goto error;
  474. }
  475. if( !QueueSuppServiceWorkItem( H450_PLACE_DIVERTEDCALL, m_hdCall,
  476. (ULONG_PTR)m_pCallReroutingInfo->divertedToNrAlias ) )
  477. {
  478. H323DBG(( DEBUG_LEVEL_ERROR, "could not post place diverted event." ));
  479. }
  480. H323DBG(( DEBUG_LEVEL_TRACE, "OnCallReroutingReceive exited:%p.", this ));
  481. return;
  482. error:
  483. CloseCall( 0 );
  484. }
  485. //!!always called in a lock
  486. BOOL
  487. CH323Call::IsValidInvokeID(
  488. IN DWORD dwInvokeId
  489. )
  490. {
  491. if( m_dwCallType != CALLTYPE_NORMAL )
  492. {
  493. if( m_dwInvokeID == dwInvokeId )
  494. {
  495. return TRUE;
  496. }
  497. H323DBG(( DEBUG_LEVEL_ERROR, "invoke id not matched:%d:%d.",
  498. m_dwInvokeID, dwInvokeId ));
  499. return FALSE;
  500. }
  501. H323DBG(( DEBUG_LEVEL_ERROR, "IsValidinvokeID called on wrong call." ));
  502. return FALSE;
  503. }
  504. BOOL
  505. CH323Call::StartTimerForCallDiversionOnNA(
  506. IN PH323_ALIASITEM pwszDivertedToAlias
  507. )
  508. {
  509. if( m_pCallReroutingInfo == NULL )
  510. {
  511. m_pCallReroutingInfo = new CALLREROUTINGINFO;
  512. if( m_pCallReroutingInfo == NULL )
  513. {
  514. goto cleanup;
  515. }
  516. ZeroMemory( m_pCallReroutingInfo, sizeof(CALLREROUTINGINFO) );
  517. }
  518. m_pCallReroutingInfo->divertedToNrAlias = new H323_ALIASNAMES;
  519. if( m_pCallReroutingInfo->divertedToNrAlias == NULL )
  520. {
  521. goto cleanup;
  522. }
  523. ZeroMemory( m_pCallReroutingInfo->divertedToNrAlias,
  524. sizeof(H323_ALIASNAMES) );
  525. if( !AddAliasItem( m_pCallReroutingInfo->divertedToNrAlias,
  526. (BYTE*)pwszDivertedToAlias->pData,
  527. sizeof(WCHAR) * (wcslen(pwszDivertedToAlias->pData) +1),
  528. pwszDivertedToAlias->wType ) )
  529. {
  530. goto cleanup;
  531. }
  532. if( !CreateTimerQueueTimer(
  533. &m_hCallDivertOnNATimer,
  534. H323TimerQueue,
  535. CH323Call::CallDivertOnNACallback,
  536. (PVOID)m_hdCall,
  537. (g_pH323Line->m_dwNumRingsNoAnswer * 1000), 0,
  538. WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE) )
  539. {
  540. goto cleanup;
  541. }
  542. return TRUE;
  543. cleanup:
  544. FreeCallReroutingInfo();
  545. return FALSE;
  546. }
  547. LONG
  548. CH323Call::SetDivertedToAlias(
  549. WCHAR* pwszDivertedToAddr,
  550. WORD wAliasType
  551. )
  552. {
  553. if( m_pCallReroutingInfo == NULL )
  554. {
  555. m_pCallReroutingInfo = new CALLREROUTINGINFO;
  556. if( m_pCallReroutingInfo == NULL )
  557. {
  558. return LINEERR_NOMEM;
  559. }
  560. ZeroMemory( m_pCallReroutingInfo, sizeof(CALLREROUTINGINFO) );
  561. }
  562. m_pCallReroutingInfo->divertedToNrAlias = new H323_ALIASNAMES;
  563. if( m_pCallReroutingInfo->divertedToNrAlias == NULL )
  564. {
  565. delete m_pCallReroutingInfo;
  566. m_pCallReroutingInfo = NULL;
  567. return LINEERR_NOMEM;
  568. }
  569. ZeroMemory( m_pCallReroutingInfo->divertedToNrAlias, sizeof(H323_ALIASNAMES) );
  570. if( !AddAliasItem( m_pCallReroutingInfo->divertedToNrAlias,
  571. (BYTE*)pwszDivertedToAddr,
  572. sizeof(WCHAR) * (wcslen(pwszDivertedToAddr) +1),
  573. wAliasType ) )
  574. {
  575. delete m_pCallReroutingInfo->divertedToNrAlias;
  576. delete m_pCallReroutingInfo;
  577. m_pCallReroutingInfo = NULL;
  578. return LINEERR_NOMEM;
  579. }
  580. return NOERROR;
  581. }
  582. //!!always called in a lock
  583. //this function is called to replace a TRANSFERD_PRIMARY call with a connected
  584. //TRANSFEREDSRC call or to preplace a TRANSFERED2_PRIMARY call with a connected
  585. //TRANSFEREDDEST call
  586. BOOL
  587. CH323Call::InitiateCallReplacement(
  588. PH323_FASTSTART pFastStart,
  589. PH323_ADDR pH245Addr
  590. )
  591. {
  592. H323DBG(( DEBUG_LEVEL_ERROR, "InitiateCallReplacement entered:%p.",this ));
  593. SendMSPStartH245( pH245Addr, pFastStart );
  594. SendMSPMessage( SP_MSG_ConnectComplete, 0, 0, m_hdRelatedCall );
  595. m_fCallInTrnasition = TRUE;
  596. if( (m_dwRASCallState == RASCALL_STATE_REGISTERED ) ||
  597. (m_dwRASCallState == RASCALL_STATE_ARQSENT ) )
  598. {
  599. //disengage from the GK
  600. SendDRQ( forcedDrop_chosen, NOT_RESEND_SEQ_NUM, FALSE );
  601. }
  602. if( !SendQ931Message( m_dwInvokeID,
  603. 0,
  604. 0,
  605. RELEASECOMPLMESSAGETYPE,
  606. CTINITIATE_OPCODE | H450_RETURNRESULT) )
  607. {
  608. goto cleanup;
  609. }
  610. H323DBG(( DEBUG_LEVEL_ERROR, "InitiateCallReplacement exited:%p.",this ));
  611. return TRUE;
  612. cleanup:
  613. CloseCall( 0 );
  614. return FALSE;
  615. }
  616. //this function is called to replace a TRANSFERD_PRIMARY call with TRANSFEREDSRC
  617. //call or to replace a TRANSFERD2_CONSULT call with a TRANSFEREDDEST call
  618. void
  619. CH323Line::SwapReplacementCall(
  620. HDRVCALL hdReplacementCall,
  621. HDRVCALL hdPrimaryCall,
  622. BOOL fChangeCallSate
  623. )
  624. {
  625. H323DBG(( DEBUG_LEVEL_TRACE, "SwapReplacementCall entered:%p.", this ));
  626. int iReplacementCallIndex = (int)LOWORD(hdReplacementCall);
  627. int iPrimaryCallIndex = (int)LOWORD(hdPrimaryCall);
  628. PH323_CALL pReplacementCall;
  629. BOOL fDelete = FALSE;
  630. PH323_CALL pPrimaryCall;
  631. Lock();
  632. LockCallTable();
  633. //lock the replacement call before primary call to avoid deadlock
  634. if( (pReplacementCall=m_H323CallTable[iReplacementCallIndex]) != NULL )
  635. {
  636. pReplacementCall -> Lock();
  637. if( pReplacementCall -> GetCallHandle() == hdReplacementCall )
  638. {
  639. if( (pPrimaryCall=m_H323CallTable[iPrimaryCallIndex]) != NULL )
  640. {
  641. pPrimaryCall -> Lock();
  642. if( pPrimaryCall -> GetCallHandle() == hdPrimaryCall )
  643. {
  644. pPrimaryCall -> InitiateCallReplacement(
  645. pReplacementCall->GetPeerFastStart(),
  646. pReplacementCall->GetPeerH245Addr() );
  647. //remove the replacement call from the table
  648. m_H323CallTable[iReplacementCallIndex] = NULL;
  649. //Transfer the required information to the replacement call.
  650. //put the primary call in IDLE mode
  651. pPrimaryCall -> TransferInfoToReplacementCall( pReplacementCall );
  652. //close the original call
  653. pPrimaryCall -> Shutdown( &fDelete );
  654. H323DBG(( DEBUG_LEVEL_VERBOSE, "call 0x%08lx closed.",
  655. pPrimaryCall ));
  656. pPrimaryCall -> Unlock();
  657. //release the primary call object
  658. if( fDelete == TRUE )
  659. {
  660. H323DBG(( DEBUG_LEVEL_VERBOSE, "call delete:0x%08lx.",
  661. pPrimaryCall ));
  662. delete pPrimaryCall;
  663. }
  664. //Place the replacement call in the place of primary call.
  665. m_H323CallTable[iPrimaryCallIndex] = pReplacementCall;
  666. }
  667. else
  668. {
  669. pPrimaryCall -> Unlock();
  670. }
  671. }
  672. else
  673. {
  674. pReplacementCall-> CloseCall( 0 );
  675. }
  676. //inform TAPI that the transfered call is in connected state
  677. if( fChangeCallSate == TRUE )
  678. {
  679. pReplacementCall->ChangeCallState( LINECALLSTATE_CONNECTED, 0 );
  680. }
  681. }
  682. pReplacementCall -> Unlock();
  683. }
  684. UnlockCallTable();
  685. Unlock();
  686. H323DBG(( DEBUG_LEVEL_TRACE, "SwapReplacementCall exited:%p.", this ));
  687. }
  688. //!!both the calls are locked when this function is called
  689. void
  690. CH323Call::TransferInfoToReplacementCall(
  691. PH323_CALL pReplacementCall
  692. )
  693. {
  694. H323DBG(( DEBUG_LEVEL_TRACE,
  695. "TransferInfoToReplacementCall entered:%p.", this ));
  696. m_dwCallDiversionState = H4503_CALLSTATE_IDLE;
  697. m_dwCallType = CALLTYPE_NORMAL;
  698. m_dwCallState = LINECALLSTATE_IDLE;
  699. pReplacementCall->SetReplacementCallInfo(
  700. m_hdCall,
  701. m_hdMSPLine,
  702. m_htCall,
  703. m_htMSPLine,
  704. m_dwAppSpecific,
  705. &m_CallData );
  706. //don't release this octet string while releasing tis call.
  707. ZeroMemory( (PVOID)&m_CallData, sizeof(H323_OCTETSTRING) );
  708. H323DBG(( DEBUG_LEVEL_TRACE,
  709. "TransferInfoToReplacementCall exited:%p.", this ));
  710. }
  711. //!!always called in a lock
  712. void
  713. CH323Call::SetReplacementCallInfo(
  714. HDRVCALL hdCall,
  715. HDRVMSPLINE hdMSPLine,
  716. HTAPICALL htCall,
  717. HTAPIMSPLINE htMSPLine,
  718. DWORD dwAppSpecific,
  719. PH323_OCTETSTRING pCallData
  720. )
  721. {
  722. H323DBG(( DEBUG_LEVEL_TRACE,
  723. "SetReplacementCallInfo entered:%p.", this ));
  724. m_hdCall = hdCall;
  725. m_hdMSPLine = hdMSPLine;
  726. m_htMSPLine = htMSPLine;
  727. m_htCall = htCall;
  728. m_hdRelatedCall = NULL;
  729. m_dwCallType = CALLTYPE_NORMAL;
  730. m_dwAppSpecific = dwAppSpecific;
  731. m_CallData = *pCallData;
  732. H323DBG(( DEBUG_LEVEL_TRACE,
  733. "SetReplacementCallInfo exited:%p.", this ));
  734. }
  735. //!!always called in a lock
  736. void
  737. CH323Call::CompleteTransfer(
  738. PH323_CALL pCall
  739. )
  740. {
  741. BOOL retVal;
  742. //set the call type of both the calls
  743. pCall -> SetCallType( CALLTYPE_TRANSFERING_PRIMARY );
  744. m_dwCallType |= CALLTYPE_TRANSFERING_CONSULT;
  745. m_hdRelatedCall = pCall -> GetCallHandle();
  746. //send CallTransferIdentify message to the transferredTo endpoint over the
  747. //consultation call
  748. retVal = SendQ931Message( NO_INVOKEID, 0, 0/*undefinedReason*/,
  749. FACILITYMESSAGETYPE, CTIDENTIFY_OPCODE | H450_INVOKE );
  750. m_dwCallDiversionState = H4502_CTIDENTIFY_SENT;
  751. //start the timer for CTIdenity message
  752. if( retVal )
  753. {
  754. retVal = CreateTimerQueueTimer(
  755. &m_hCTIdentifyTimer,
  756. H323TimerQueue,
  757. CH323Call::CTIdentifyExpiredCallback,
  758. (PVOID)m_hdCall,
  759. CTIDENTIFY_SENT_TIMEOUT, 0,
  760. WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE );
  761. }
  762. if( retVal == FALSE )
  763. {
  764. CloseCall( 0 );
  765. }
  766. }
  767. void
  768. CH323Line::PlaceTransferedCall(
  769. IN HDRVCALL hdCall,
  770. IN PH323_ALIASNAMES pTransferedToAlias
  771. )
  772. {
  773. H323DBG(( DEBUG_LEVEL_TRACE, "PlaceTransferedCall entered:%p.", this ));
  774. PH323_CALL pCall = NULL;
  775. PH323_CALL pTransferedCall = NULL;
  776. BOOL fDelete = FALSE;
  777. Lock();
  778. LockCallTable();
  779. pCall=g_pH323Line -> FindH323CallAndLock(hdCall);
  780. if( pCall == NULL )
  781. {
  782. goto cleanup;
  783. }
  784. pTransferedCall = CreateNewTransferedCall( pTransferedToAlias );
  785. if( pTransferedCall == NULL )
  786. {
  787. goto cleanup;
  788. }
  789. //transfer the required information to the transfered call
  790. if( !pCall -> TransferInfoToTransferedCall( pTransferedCall ) )
  791. {
  792. goto cleanup;
  793. }
  794. pCall -> SetCallState( LINECALLSTATE_ONHOLD );
  795. pCall -> SendMSPMessage( SP_MSG_Hold, 0, 1, NULL );
  796. pCall -> Unlock();
  797. //dial the transfered call
  798. pTransferedCall -> DialCall();
  799. UnlockCallTable();
  800. Unlock();
  801. H323DBG(( DEBUG_LEVEL_TRACE, "PlaceTransferedCall exited:%p.", this ));
  802. return;
  803. cleanup:
  804. if( pCall != NULL )
  805. {
  806. //close the primary call
  807. QueueTAPILineRequest(
  808. TSPI_CLOSE_CALL,
  809. hdCall,
  810. NULL,
  811. LINEDISCONNECTMODE_NORMAL,
  812. NULL);
  813. pCall -> Unlock();
  814. }
  815. if( pTransferedCall )
  816. {
  817. pTransferedCall -> Shutdown( &fDelete );
  818. delete pTransferedCall;
  819. }
  820. UnlockCallTable();
  821. Unlock();
  822. }
  823. //!!always called in a lock
  824. PH323_CALL
  825. CH323Line::CreateNewTransferedCall(
  826. IN PH323_ALIASNAMES pwszCalleeAlias
  827. )
  828. {
  829. PH323_CONFERENCE pConf = NULL;
  830. BOOL fDelete = FALSE;
  831. PH323_CALL pCall = new CH323Call();
  832. H323DBG(( DEBUG_LEVEL_TRACE, "CreateNewTransferedCall entered:%p.", this ));
  833. if( pCall == NULL )
  834. {
  835. H323DBG(( DEBUG_LEVEL_ERROR,
  836. "could not allocate Transfered call." ));
  837. return NULL;
  838. }
  839. // no tapi handle for this call
  840. if( !pCall -> Initialize( NULL, LINECALLORIGIN_OUTBOUND,
  841. CALLTYPE_TRANSFEREDSRC ) )
  842. {
  843. H323DBG(( DEBUG_LEVEL_ERROR,
  844. "could not allocate outgoing call." ));
  845. goto cleanup;
  846. }
  847. // bind outgoing call
  848. pConf = pCall -> CreateConference(NULL);
  849. if( pConf == NULL )
  850. {
  851. H323DBG(( DEBUG_LEVEL_ERROR,
  852. "could not create conference." ));
  853. goto cleanup;
  854. }
  855. if( !g_pH323Line -> GetH323ConfTable() -> Add(pConf) )
  856. {
  857. H323DBG(( DEBUG_LEVEL_ERROR, "could not add conf to conf table." ));
  858. goto cleanup;
  859. }
  860. if( pwszCalleeAlias->pItems[0].wType == e164_chosen )
  861. {
  862. pCall->SetAddressType( e164_chosen );
  863. }
  864. if (!RasIsRegistered())
  865. {
  866. if( !pCall->ResolveAddress( pwszCalleeAlias->pItems[0].pData ) )
  867. {
  868. goto cleanup;
  869. }
  870. }
  871. if( !pCall->SetCalleeAlias( pwszCalleeAlias->pItems[0].pData,
  872. pwszCalleeAlias->pItems[0].wType ) )
  873. {
  874. goto cleanup;
  875. }
  876. H323DBG(( DEBUG_LEVEL_TRACE, "Transfered call created:%p.", pCall ));
  877. H323DBG(( DEBUG_LEVEL_TRACE, "CreateNewTransferedCall exited:%p.", this ));
  878. return pCall;
  879. cleanup:
  880. if( pCall != NULL )
  881. {
  882. pCall -> Shutdown( &fDelete );
  883. delete pCall;
  884. H323DBG((DEBUG_LEVEL_TRACE, "call delete:%p.", pCall ));
  885. }
  886. return NULL;
  887. }
  888. //
  889. // TSPI procedures
  890. //
  891. LONG
  892. TSPIAPI
  893. TSPI_lineAddToConference(
  894. DRV_REQUESTID dwRequestID,
  895. HDRVCALL hdConfCall,
  896. HDRVCALL hdConsultCall
  897. )
  898. /*++
  899. Routine Description:
  900. This function adds the call specified by hdConsultCall to the conference
  901. call specified by hdConfCall.
  902. Note that the call handle of the added party remains valid after adding
  903. the call to a conference; its state will typically change to conferenced
  904. while the state of the conference call will typically become connected.
  905. The handle to an individual participating call can be used later to remove
  906. that party from the conference call using TSPI_lineRemoveFromConference.
  907. The call states of the calls participating in a conference are not
  908. independent. For example, when dropping a conference call, all
  909. participating calls may automatically become idle. The TAPI DLL may consult
  910. the line's device capabilities to determine what form of conference removal
  911. is available. The TAPI DLL or its client applications should track the
  912. LINE_CALLSTATE messages to determine what really happened to the calls
  913. involved.
  914. The conference call is established either via TSPI_lineSetupConference or
  915. TSPI_lineCompleteTransfer. The call added to a conference will typically be
  916. established using TSPI_lineSetupConference or
  917. TSPI_linePrepareAddToConference. Some switches may allow adding of an
  918. arbitrary calls to conference, and such a call may have been set up using
  919. TSPI_lineMakeCall and be on (hard) hold.
  920. Arguments:
  921. dwRequestID - Specifies the identifier of the asynchronous request.
  922. The Service Provider returns this value if the function completes
  923. asynchronously.
  924. hdConfCall - Specifies the Service Provider's opaque handle to the
  925. conference call. Valid call states: onHoldPendingConference, onHold.
  926. hdAddCall - Specifies the Service Provider's opaque handle to the call to
  927. be added to the conference call. Valid call states: connected, onHold.
  928. Return Values:
  929. Returns zero if the function is successful, the (positive) dwRequestID
  930. value if the function will be completed asynchronously, or a negative error
  931. number if an error has occurred. Possible error returns are:
  932. LINEERR_INVALCONFCALLHANDLE - The specified call handle for the
  933. conference call is invalid or is not a handle for a conference
  934. call.
  935. LINEERR_INVALCALLHANDLE - The specified call handle for the added
  936. call is invalid.
  937. LINEERR_INVALCALLSTATE - One or both of the specified calls are not
  938. in a valid state for the requested operation.
  939. LINEERR_CONFERENCEFULL - The maximum number of parties for a
  940. conference has been reached.
  941. LINEERR_OPERATIONUNAVAIL - The specified operation is not available.
  942. LINEERR_OPERATIONFAILED - The specified operation failed for
  943. unspecified reason.
  944. --*/
  945. {
  946. return LINEERR_OPERATIONUNAVAIL; // CODEWORK...
  947. }
  948. LONG
  949. TSPIAPI
  950. TSPI_lineBlindTransfer(
  951. DRV_REQUESTID dwRequestID,
  952. HDRVCALL hdCall,
  953. LPCWSTR lpszDestAddress,
  954. DWORD dwCountryCode
  955. )
  956. {
  957. PH323_CALL pCall = NULL;
  958. LONG retVal = ERROR_SUCCESS;
  959. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineBlindTransfer - Entered." ));
  960. if( lpszDestAddress == NULL )
  961. {
  962. return LINEERR_INVALPARAM;
  963. }
  964. // retrieve call pointer from handle
  965. pCall=g_pH323Line -> FindH323CallAndLock(hdCall);
  966. if( pCall == NULL )
  967. {
  968. return LINEERR_INVALCALLHANDLE;
  969. }
  970. retVal = pCall -> InitiateBlindTransfer( lpszDestAddress );
  971. pCall -> Unlock();
  972. if( retVal == ERROR_SUCCESS )
  973. {
  974. // complete the async accept operation now
  975. H323CompleteRequest (dwRequestID, ERROR_SUCCESS);
  976. retVal = dwRequestID;
  977. }
  978. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineBlindTransfer - Exited." ));
  979. return retVal;
  980. }
  981. //!!always called in a lock
  982. LONG
  983. CH323Call::InitiateBlindTransfer(
  984. IN LPCWSTR lpszDestAddress
  985. )
  986. {
  987. WORD wAliasType = h323_ID_chosen;
  988. DWORD dwMaxAddrSize = MAX_H323_ADDR_LEN;
  989. DWORD dwAddrLen;
  990. H323DBG(( DEBUG_LEVEL_TRACE, "InitiateBlindTransfer - Entered." ));
  991. if( m_dwCallState != LINECALLSTATE_CONNECTED )
  992. {
  993. return LINEERR_INVALCALLSTATE;
  994. }
  995. if( (*lpszDestAddress==L'T') &&
  996. IsValidE164String((WCHAR*)lpszDestAddress+1) )
  997. {
  998. wAliasType = e164_chosen;
  999. //strip off the leading 'T'
  1000. lpszDestAddress++;
  1001. dwMaxAddrSize = MAX_E164_ADDR_LEN;
  1002. }
  1003. else if( IsValidE164String( (WCHAR*)lpszDestAddress) )
  1004. {
  1005. wAliasType = e164_chosen;
  1006. dwMaxAddrSize = MAX_E164_ADDR_LEN;
  1007. }
  1008. dwAddrLen = wcslen( lpszDestAddress );
  1009. if( (dwAddrLen > dwMaxAddrSize) || (dwAddrLen == 0) )
  1010. {
  1011. return LINEERR_INVALPARAM;
  1012. }
  1013. if( m_pTransferedToAlias )
  1014. {
  1015. FreeAliasNames( m_pTransferedToAlias );
  1016. m_pTransferedToAlias = NULL;
  1017. }
  1018. m_pTransferedToAlias = new H323_ALIASNAMES;
  1019. if( m_pTransferedToAlias == NULL )
  1020. {
  1021. return LINEERR_OPERATIONFAILED;
  1022. }
  1023. ZeroMemory( (PVOID)m_pTransferedToAlias, sizeof(H323_ALIASNAMES) );
  1024. if( !AddAliasItem( m_pTransferedToAlias,
  1025. (BYTE*)lpszDestAddress,
  1026. sizeof(WCHAR) * (wcslen(lpszDestAddress) +1),
  1027. wAliasType ) )
  1028. {
  1029. return LINEERR_OPERATIONFAILED;
  1030. }
  1031. if( !SendQ931Message( NO_INVOKEID, 0, 0, FACILITYMESSAGETYPE,
  1032. CTINITIATE_OPCODE | H450_INVOKE ) )
  1033. {
  1034. return LINEERR_OPERATIONFAILED;
  1035. }
  1036. m_dwCallDiversionState = H4502_CTINITIATE_SENT;
  1037. m_dwCallType |= CALLTYPE_TRANSFERING_PRIMARY;
  1038. H323DBG(( DEBUG_LEVEL_TRACE, "InitiateBlindTransfer - Exited." ));
  1039. return ERROR_SUCCESS;
  1040. }
  1041. /*++
  1042. Routine Description:
  1043. This function completes the transfer of the specified call to the party
  1044. connected in the consultation call.
  1045. This operation completes the transfer of the original call, hdCall, to
  1046. the party currently connected via hdConsultCall. The consultation call
  1047. will typically have been dialed on the consultation call allocated as
  1048. part of TSPI_lineSetupTransfer, but it may be any call to which the
  1049. switch is capable of transferring hdCall.
  1050. The transfer request can be resolved either as a transfer or as a
  1051. three-way conference call. When resolved as a transfer, the parties
  1052. connected via hdCall and hdConsultCall will be connected to each other,
  1053. and both hdCall and hdConsultCall will typically be removed from the line
  1054. they were on and both will transition to the idle state. Note that the
  1055. Service Provider's opaque handles for these calls must remain valid after
  1056. the transfer has completed. The TAPI DLL causes these handles to be
  1057. invalidated when it is no longer interested in them using
  1058. TSPI_lineCloseCall.
  1059. When resolved as a conference, all three parties will enter in a
  1060. conference call. Both existing call handles remain valid, but will
  1061. transition to the conferenced state. A conference call handle will created
  1062. and returned, and it will transition to the connected state.
  1063. It may also be possible to perform a blind transfer of a call using
  1064. TSPI_lineBlindTransfer.
  1065. Arguments:
  1066. dwRequestID - Specifies the identifier of the asynchronous request.
  1067. The Service Provider returns this value if the function completes
  1068. asynchronously.
  1069. hdCall - Specifies the Service Provider's opaque handle to the call to be
  1070. transferred. Valid call states: onHoldPendingTransfer.
  1071. hdConsultCall - Specifies a handle to the call that represents a connection
  1072. with the destination of the transfer. Valid call states: connected,
  1073. ringback, busy.
  1074. htConfCall - Specifies the TAPI DLL's opaque handle to the new call. If
  1075. dwTransferMode is specified as LINETRANSFERMODE_CONFERENCE then the
  1076. Service Provider must save this and use it in all subsequent calls to
  1077. the LINEEVENT procedure reporting events on the call. Otherwise this
  1078. parameter is ignored.
  1079. lphdConfCall - Specifies a far pointer to an opaque HDRVCALL representing
  1080. the Service Provider's identifier for the call. If dwTransferMode is
  1081. specified as LINETRANSFERMODE_CONFERENCE then the Service Provider must
  1082. fill this location with its opaque handle for the new conference call
  1083. before this procedure returns, whether it decides to execute the
  1084. request sychronously or asynchronously. This handle is invalid if the
  1085. function results in an error (either synchronously or asynchronously).
  1086. If dwTransferMode is some other value this parameter is ignored.
  1087. dwTransferMode - Specifies how the initiated transfer request is to be
  1088. resolved, of type LINETRANSFERMODE. Values are:
  1089. LINETRANSFERMODE_TRANSFER - Resolve the initiated transfer by
  1090. transferring the initial call to the consultation call.
  1091. LINETRANSFERMODE_CONFERENCE - Resolve the initiated transfer by
  1092. conferencing all three parties into a three-way conference call.
  1093. A conference call is created and returned to the TAPI DLL.
  1094. Return Values:
  1095. Returns zero if the function is successful, the (positive) dwRequestID
  1096. value if the function will be completed asynchronously, or a negative error
  1097. number if an error has occurred. Possible error returns are:
  1098. LINEERR_INVALCALLHANDLE - The specified call handle is invalid.
  1099. LINEERR_INVALCONSULTCALLHANDLE - The specified consultation call
  1100. handle is invalid.
  1101. LINEERR_INVALCALLSTATE - One or both calls are not in a valid state
  1102. for the requested operation.
  1103. LINEERR_INVALTRANSFERMODE - The specified transfer mode parameter is
  1104. invalid.
  1105. LINEERR_INVALPOINTER - The specified pointer parameter is invalid.
  1106. LINEERR_OPERATIONUNAVAIL - The specified operation is not available.
  1107. LINEERR_OPERATIONFAILED - The specified operation failed for
  1108. unspecified reason.
  1109. --*/
  1110. LONG
  1111. TSPIAPI
  1112. TSPI_lineCompleteTransfer(
  1113. DRV_REQUESTID dwRequestID,
  1114. HDRVCALL hdCall,
  1115. HDRVCALL hdConsultCall,
  1116. HTAPICALL htConfCall,
  1117. LPHDRVCALL lphdConfCall,
  1118. DWORD dwTransferMode
  1119. )
  1120. {
  1121. LONG retVal = (DWORD)dwRequestID;
  1122. PH323_CALL pCall = NULL;
  1123. PH323_CALL pConsultCall = NULL;
  1124. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineCompleteTransfer - Entered." ));
  1125. if( dwTransferMode != LINETRANSFERMODE_TRANSFER )
  1126. {
  1127. return LINEERR_INVALTRANSFERMODE; // CODEWORK...
  1128. }
  1129. // retrieve call pointer from handle
  1130. pCall=g_pH323Line -> Find2H323CallsAndLock(
  1131. hdCall, hdConsultCall, &pConsultCall);
  1132. if( pCall == NULL )
  1133. {
  1134. return LINEERR_INVALCALLHANDLE;
  1135. }
  1136. if( (pCall -> GetCallState() != LINECALLSTATE_CONNECTED) &&
  1137. !pCall -> IsCallOnHold() )
  1138. {
  1139. H323DBG(( DEBUG_LEVEL_ERROR, "call 0x%08lx not connected.", pCall ));
  1140. retVal = LINEERR_INVALCALLSTATE;
  1141. goto cleanup;
  1142. }
  1143. if( (pConsultCall -> GetCallState() != LINECALLSTATE_CONNECTED) &&
  1144. !pConsultCall -> IsCallOnHold() )
  1145. {
  1146. H323DBG(( DEBUG_LEVEL_ERROR, "call 0x%08lx not connected.", pCall ));
  1147. retVal = LINEERR_INVALCALLSTATE;
  1148. goto cleanup;
  1149. }
  1150. if( !QueueTAPILineRequest(
  1151. TSPI_COMPLETE_TRANSFER,
  1152. hdCall,
  1153. hdConsultCall,
  1154. 0,
  1155. NULL ))
  1156. {
  1157. H323DBG(( DEBUG_LEVEL_ERROR, "could not post transfer complete event." ));
  1158. retVal = LINEERR_OPERATIONFAILED;
  1159. goto cleanup;
  1160. }
  1161. // complete the async accept operation now
  1162. H323CompleteRequest (dwRequestID, ERROR_SUCCESS);
  1163. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineCompleteTransfer - Exited." ));
  1164. cleanup:
  1165. if( pCall != NULL )
  1166. {
  1167. pCall -> Unlock();
  1168. }
  1169. if( pConsultCall )
  1170. {
  1171. pConsultCall -> Unlock();
  1172. }
  1173. return retVal;
  1174. }
  1175. /*++
  1176. Parameters:
  1177. dwRequestID - The identifier of the asynchronous request.
  1178. hdCall - The handle to the call to be transferred. The call state of hdCall
  1179. can be connected.
  1180. htConsultCall - The TAPI handle to the new, temporary consultation call.
  1181. The service provider must save this and use it in all subsequent calls
  1182. to the LINEEVENT procedure reporting events on the new consultation call.
  1183. lphdConsultCall - A pointer to an HDRVCALL representing the service
  1184. provider's identifier for the new consultation call. The service
  1185. provider must fill this location with its handle for the new
  1186. consultation call before this procedure returns. This handle is ignored
  1187. by TAPI if the function results in an error. The call state of
  1188. hdConsultCall is not applicable.
  1189. When setting a call up for transfer, another call (a consultation call)
  1190. is automatically allocated to enable the application (through TAPI) to
  1191. dial the address (using TSPI_lineDial) of the party to where the call
  1192. is to be transferred. The originating party can carry on a conversation
  1193. over this consultation call prior to completing the transfer.
  1194. This transfer procedure may not be valid for some line devices. Instead
  1195. of calling this procedure, TAPI may need to unhold an existing held
  1196. call (using TSPI_lineUnhold) to identify the destination of the transfer.
  1197. On switches that support cross-address call transfer, the consultation
  1198. call can exist on a different address than the call to be transferred.
  1199. It may also be necessary to set up the consultation call as an entirely
  1200. new call using TSPI_lineMakeCall, to the destination of the transfer.
  1201. The transferHeld and transferMake flags in the LINEADDRESSCAPS data
  1202. structure report what model the service provider uses.
  1203. lpCallParams - A pointer to call parameters to be used when establishing
  1204. the consultation call. This parameter can be set to NULL if no special
  1205. call setup parameters are desired (the service provider uses defaults).
  1206. Return Values:
  1207. Returns dwRequestID, or an error number if an error occurs. The lResult
  1208. actual parameter of the corresponding ASYNC_COMPLETION is zero if the
  1209. function succeeds, or an error number if an error occurs. Possible return
  1210. values are as follows:
  1211. LINEERR_INVALCALLHANDLE,
  1212. LINEERR_INVALBEARERMODE,
  1213. LINEERR_INVALCALLSTATE,
  1214. LINEERR_INVALRATE,
  1215. LINEERR_CALLUNAVAIL,
  1216. LINEERR_INVALCALLPARAMS,
  1217. LINEERR_NOMEM,
  1218. LINEERR_INVALLINESTATE,
  1219. LINEERR_OPERATIONUNAVAIL,
  1220. LINEERR_INVALMEDIAMODE,
  1221. LINEERR_OPERATIONFAILED,
  1222. LINEERR_INUSE,
  1223. LINEERR_RESOURCEUNAVAIL,
  1224. LINEERR_NOMEM,
  1225. LINEERR_BEARERMODEUNAVAIL,
  1226. LINEERR_RATEUNAVAIL,
  1227. LINEERR_INVALADDRESSMODE,
  1228. LINEERR_USERUSERINFOTOOBIG.
  1229. --*/
  1230. LONG
  1231. TSPIAPI
  1232. TSPI_lineSetupTransfer(
  1233. DRV_REQUESTID dwRequestID,
  1234. HDRVCALL hdCall,
  1235. HTAPICALL htConsultCall,
  1236. LPHDRVCALL phdConsultCall,
  1237. LPLINECALLPARAMS const lpCallParams
  1238. )
  1239. {
  1240. LONG retVal = (DWORD)dwRequestID;
  1241. PH323_CALL pCall = NULL;
  1242. PH323_CALL pConsultCall = NULL;
  1243. H323_CONFERENCE * pConf = NULL;
  1244. BOOL fDelete = FALSE;
  1245. DWORD dwCallState;
  1246. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineSetupTransfer - Entered." ));
  1247. // Acquire the call table lock.
  1248. g_pH323Line -> LockCallTable();
  1249. pCall = g_pH323Line -> FindH323CallAndLock( hdCall );
  1250. if( pCall == NULL )
  1251. {
  1252. retVal = LINEERR_INVALCALLHANDLE;
  1253. goto cleanup;
  1254. }
  1255. dwCallState = pCall -> GetCallState();
  1256. if( (dwCallState != LINECALLSTATE_CONNECTED) &&
  1257. !pCall -> IsCallOnLocalHold() )
  1258. {
  1259. H323DBG(( DEBUG_LEVEL_ERROR, "call 0x%08lx not connected.", pCall ));
  1260. retVal = LINEERR_INVALCALLSTATE;
  1261. goto cleanup;
  1262. }
  1263. dwCallState = pCall -> GetCallDiversionState();
  1264. if( dwCallState == H4502_CONSULTCALL_INITIATED )
  1265. {
  1266. H323DBG(( DEBUG_LEVEL_ERROR, "call 0x%08lx already is consulting.",
  1267. pCall ));
  1268. retVal = LINEERR_INVALCALLSTATE;
  1269. goto cleanup;
  1270. }
  1271. // allocate outgoing call
  1272. pConsultCall = new CH323Call();
  1273. if( pConsultCall == NULL )
  1274. {
  1275. H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate outgoing call." ));
  1276. // no memory available
  1277. retVal = LINEERR_NOMEM;
  1278. goto cleanup;
  1279. }
  1280. // save tapi handle and specify outgoing call direction
  1281. if( !pConsultCall -> Initialize( htConsultCall, LINECALLORIGIN_OUTBOUND,
  1282. CALLTYPE_TRANSFERING_CONSULT ) )
  1283. {
  1284. H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate outgoing call." ));
  1285. // no memory available
  1286. retVal = LINEERR_NOMEM;
  1287. goto cleanup;
  1288. }
  1289. // transfer handle
  1290. *phdConsultCall = pConsultCall -> GetCallHandle();
  1291. // bind outgoing call
  1292. pConf = pConsultCall -> CreateConference(NULL);
  1293. if( pConf == NULL )
  1294. {
  1295. H323DBG(( DEBUG_LEVEL_ERROR,
  1296. "could not create conference." ));
  1297. // no memory available
  1298. retVal = LINEERR_NOMEM;
  1299. // failure
  1300. goto cleanup;
  1301. }
  1302. if( !g_pH323Line -> GetH323ConfTable() -> Add(pConf) )
  1303. {
  1304. H323DBG(( DEBUG_LEVEL_ERROR, "could not add conf to conf table." ));
  1305. // no memory available
  1306. retVal = LINEERR_NOMEM;
  1307. // failure
  1308. goto cleanup;
  1309. }
  1310. // complete the async accept operation now
  1311. H323CompleteRequest (dwRequestID, ERROR_SUCCESS);
  1312. pConsultCall -> ChangeCallState( LINECALLSTATE_DIALTONE, 0 );
  1313. // Put the primary call on hold
  1314. pCall-> Hold();
  1315. pCall -> SetCallDiversionState( H4502_CONSULTCALL_INITIATED );
  1316. pCall -> Unlock();
  1317. // Release the call table lock
  1318. g_pH323Line -> UnlockCallTable();
  1319. // Create a new call. put it in DIALTONE mode and return its handle
  1320. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineSetupTransfer - Exited." ));
  1321. return retVal;
  1322. cleanup:
  1323. if( pCall != NULL )
  1324. {
  1325. pCall -> Unlock();
  1326. }
  1327. if( pConf != NULL )
  1328. {
  1329. g_pH323Line -> GetH323ConfTable() -> Remove( pConf );
  1330. delete pConf;
  1331. pConf = NULL;
  1332. }
  1333. if( pConsultCall != NULL )
  1334. {
  1335. pConsultCall -> Shutdown( &fDelete );
  1336. H323DBG((DEBUG_LEVEL_TRACE, "call delete:%p.", pCall ));
  1337. delete pConsultCall;
  1338. pCall = NULL;
  1339. }
  1340. // Release the call table lock
  1341. g_pH323Line -> UnlockCallTable();
  1342. return retVal;
  1343. }
  1344. /*
  1345. Parameters:
  1346. dwRequestID - The identifier of the asynchronous request.
  1347. hdCall - The service provider's handle to the call to be dialed. The call
  1348. state of hdCall can be any state except idle and disconnected.
  1349. lpszDestAddress - The destination to be dialed using the standard dialable
  1350. number format.
  1351. dwCountryCode - The country code of the destination. This is used by the
  1352. implementation to select the call progress protocols for the destination
  1353. address. If a value of 0 is specified, a default call-progress protocol
  1354. defined by the service provider is used. This parameter is not validated
  1355. by TAPI when this function is called.
  1356. Return Values -
  1357. Returns dwRequestID or an error number if an error occurs. The lResult
  1358. actual parameter of the corresponding ASYNC_COMPLETION is zero if the
  1359. function succeeds or an error number if an error occurs. Possible return
  1360. values are as follows:
  1361. LINEERR_INVALCALLHANDLE,
  1362. LINEERR_OPERATIONFAILED,
  1363. LINEERR_INVALADDRESS,
  1364. LINEERR_RESOURCEUNAVAIL,
  1365. LINEERR_INVALCOUNTRYCODE,
  1366. LINEERR_DIALBILLING,
  1367. LINEERR_INVALCALLSTATE,
  1368. LINEERR_DIALQUIET,
  1369. LINEERR_ADDRESSBLOCKED,
  1370. LINEERR_DIALDIALTONE,
  1371. LINEERR_NOMEM,
  1372. LINEERR_DIALPROMPT,
  1373. LINEERR_OPERATIONUNAVAIL.
  1374. Remarks -
  1375. The service provider returns LINEERR_INVALCALLSTATE if the current state
  1376. of the call does not allow dialing.
  1377. The service provider carries out no dialing if it returns
  1378. LINEERR_INVALADDRESS.
  1379. If the service provider returns LINEERR_DIALBILLING, LINEERR_DIALQUIET,
  1380. LINEERR_DIALDIALTONE, or LINEERR_DIALPROMPT, it should perform none of
  1381. the actions otherwise performed by TSPI_lineDial (for example, no
  1382. partial dialing, and no going offhook). This is because the service
  1383. provider should pre-scan the number for unsupported characters first.
  1384. TSPI_lineDial is used for dialing on an existing call appearance; for
  1385. example, call handles returned from TSPI_lineMakeCall with NULL as the
  1386. lpszDestAddress or ending in ';', call handles returned from
  1387. TSPI_lineSetupTransfer or TSPI_lineSetupConference. TSPI_lineDial can
  1388. be invoked multiple times in the course of dialing in the case of
  1389. multistage dialing, if the line's device capabilities permit it.
  1390. If the string pointed to by the lpszDestAddress parameter in the
  1391. previous call to the TSPI_lineMakeCall or TSPI_lineDial function is
  1392. terminated with a semicolon, an empty string in the current call to
  1393. TSPI_lineDial indicates that dialing is complete.
  1394. Multiple addresses can be provided in a single dial string separated by
  1395. CRLF. Service providers that provide inverse multiplexing can establish
  1396. individual physical calls with each of the addresses, and return a
  1397. single call handle to the aggregate of all calls to the application.
  1398. All addresses would use the same country code.
  1399. Dialing is considered complete after the address has been accepted by
  1400. the service provider, not after the call is finally connected. Service
  1401. providers that provide inverse multiplexing may allow multiple addresses
  1402. to be provided at once. The service provider must send LINE_CALLSTATE
  1403. messages to TAPI to inform it about the progress of the call.
  1404. */
  1405. LONG
  1406. TSPIAPI
  1407. TSPI_lineDial(
  1408. DRV_REQUESTID dwRequestID,
  1409. HDRVCALL hdCall,
  1410. LPCWSTR lpszDestAddress,
  1411. DWORD dwCountryCode
  1412. )
  1413. {
  1414. LONG retVal = (DWORD)dwRequestID;
  1415. PH323_CALL pCall = NULL;
  1416. WORD wAliasType = h323_ID_chosen;
  1417. DWORD dwCallState;
  1418. WCHAR* wszMachineName;
  1419. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineDial - Entered." ));
  1420. if( lpszDestAddress == NULL )
  1421. {
  1422. return LINEERR_INVALPARAM;
  1423. }
  1424. pCall=g_pH323Line -> FindH323CallAndLock(hdCall);
  1425. if( pCall == NULL )
  1426. {
  1427. return LINEERR_INVALCALLHANDLE;
  1428. }
  1429. dwCallState = pCall -> GetCallState();
  1430. if( dwCallState == LINECALLSTATE_CONNECTED )
  1431. {
  1432. //no need to dial the call. Inform TAPI3 about it once again.
  1433. pCall -> ChangeCallState( LINECALLSTATE_CONNECTED, 0 );
  1434. goto func_exit;
  1435. }
  1436. if( dwCallState != LINECALLSTATE_DIALTONE )
  1437. {
  1438. H323DBG(( DEBUG_LEVEL_ERROR, "call 0x%08lx no dialtone.", pCall ));
  1439. pCall -> Unlock();
  1440. return LINEERR_INVALCALLSTATE;
  1441. }
  1442. if( (*lpszDestAddress==L'T') &&
  1443. IsValidE164String((WCHAR*)lpszDestAddress+1) )
  1444. {
  1445. wAliasType = e164_chosen;
  1446. //strip off the leading 'T'
  1447. lpszDestAddress++;
  1448. }
  1449. else if( IsValidE164String( (WCHAR*)lpszDestAddress) )
  1450. {
  1451. wAliasType = e164_chosen;
  1452. }
  1453. pCall->SetAddressType( wAliasType );
  1454. if( !pCall->SetCalleeAlias( (WCHAR*)lpszDestAddress, wAliasType ) )
  1455. {
  1456. H323DBG(( DEBUG_LEVEL_ERROR, "could not set callee alias." ));
  1457. pCall -> Unlock();
  1458. // invalid destination addr
  1459. return LINEERR_NOMEM;
  1460. }
  1461. //set the caller alias name
  1462. if( RasIsRegistered() )
  1463. {
  1464. //ARQ message must have a caller alias
  1465. PH323_ALIASNAMES pAliasList = RASGetRegisteredAliasList();
  1466. wszMachineName = pAliasList -> pItems[0].pData;
  1467. wAliasType = pAliasList -> pItems[0].wType;
  1468. }
  1469. else
  1470. {
  1471. wszMachineName = g_pH323Line->GetMachineName();
  1472. wAliasType = h323_ID_chosen;
  1473. }
  1474. //set the value for m_pCallerAliasNames
  1475. if( !pCall->SetCallerAlias( wszMachineName, wAliasType ) )
  1476. {
  1477. H323DBG(( DEBUG_LEVEL_ERROR, "could not set caller alias." ));
  1478. pCall -> Unlock();
  1479. // invalid destination addr
  1480. return LINEERR_NOMEM;
  1481. }
  1482. if( !pCall -> QueueTAPICallRequest( TSPI_MAKE_CALL, NULL ))
  1483. {
  1484. H323DBG(( DEBUG_LEVEL_ERROR, "could not post transfer complete event." ));
  1485. pCall -> Unlock();
  1486. return LINEERR_OPERATIONFAILED;
  1487. }
  1488. func_exit:
  1489. // complete the async accept operation now
  1490. H323CompleteRequest (dwRequestID, ERROR_SUCCESS);
  1491. //create a new call. put it in DIALTONE mode and return its handle
  1492. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineDial - Exited." ));
  1493. pCall -> Unlock();
  1494. return retVal;
  1495. }
  1496. LONG
  1497. TSPIAPI
  1498. TSPI_linePrepareAddToConference(
  1499. DRV_REQUESTID dwRequestID,
  1500. HDRVCALL hdConfCall,
  1501. HTAPICALL htConsultCall,
  1502. LPHDRVCALL lphdConsultCall,
  1503. LPLINECALLPARAMS const lpCallParams
  1504. )
  1505. /*++
  1506. Routine Description:
  1507. This function prepares an existing conference call for the addition of
  1508. another party. It creates a new, temporary consultation call. The new
  1509. consulatation call can be subsequently added to the conference call.
  1510. A conference call handle can be obtained via TSPI_lineSetupConference or
  1511. via TSPI_lineCompleteTransfer that is resolved as a three-way conference
  1512. call. The function TSPI_linePrepareAddToConference typically places the
  1513. existing conference call in the onHoldPendingConference state and creates
  1514. a consultation call that can be added later to the existing conference
  1515. call via TSPI_lineAddToConference.
  1516. The consultation call can be canceled using TSPI_lineDrop. It may also
  1517. be possible for the TAPI DLL to swap between the consultation call and
  1518. the held conference call via TSPI_lineSwapHold.
  1519. The Service Provider initially does media monitoring on the new call for
  1520. at least the set of media modes that were monitored for on the line.
  1521. Arguments:
  1522. dwRequestID - Specifies the identifier of the asynchronous request.
  1523. The Service Provider returns this value if the function completes
  1524. asynchronously.
  1525. hdConfCall - Specifies the Service Provider's opaque handle to a
  1526. conference call. Valid call states: connected.
  1527. htAddCall - Specifies the TAPI DLL's opaque handle to the new, temporary
  1528. consultation call. The Service Provider must save this and use it in
  1529. all subsequent calls to the LINEEVENT procedure reporting events on
  1530. the new call.
  1531. lphdAddCall - Specifies a far pointer to an opaque HDRVCALL representing
  1532. the Service Provider's identifier for the new, temporary consultation
  1533. call. The Service Provider must fill this location with its opaque
  1534. handle for the new call before this procedure returns, whether it
  1535. decides to execute the request sychronously or asynchronously. This
  1536. handle is invalid if the function results in an error (either
  1537. synchronously or asynchronously).
  1538. lpCallParams - Specifies a far pointer to call parameters to be used when
  1539. establishing the consultation call. This parameter may be set to NULL
  1540. if no special call setup parameters are desired.
  1541. Return Values:
  1542. Returns zero if the function is successful, the (positive) dwRequestID
  1543. value if the function will be completed asynchronously, or a negative error
  1544. number if an error has occurred. Possible error returns are:
  1545. LINEERR_INVALCONFCALLHANDLE - The specified call handle for the
  1546. conference call is invalid.
  1547. LINEERR_INVALPOINTER - One or more of the specified pointer
  1548. parameters are invalid.
  1549. LINEERR_INVALCALLSTATE - The conference call is not in a valid state
  1550. for the requested operation.
  1551. LINEERR_CALLUNAVAIL - All call appearances on the specified address
  1552. are currently allocated.
  1553. LINEERR_CONFERENCEFULL - The maximum number of parties for a
  1554. conference has been reached.
  1555. LINEERR_INVALCALLPARAMS - The specified call parameters are invalid.
  1556. LINEERR_OPERATIONUNAVAIL - The specified operation is not available.
  1557. LINEERR_OPERATIONFAILED - The specified operation failed for
  1558. unspecified reason.
  1559. --*/
  1560. {
  1561. return LINEERR_OPERATIONUNAVAIL; // CODEWORK...
  1562. }
  1563. LONG
  1564. TSPIAPI
  1565. TSPI_lineSetupConference(
  1566. DRV_REQUESTID dwRequestID,
  1567. HDRVCALL hdCall,
  1568. HDRVLINE hdLine,
  1569. HTAPICALL htConfCall,
  1570. LPHDRVCALL lphdConfCall,
  1571. HTAPICALL htConsultCall,
  1572. LPHDRVCALL lphdConsultCall,
  1573. DWORD dwNumParties,
  1574. LPLINECALLPARAMS const lpCallParams
  1575. )
  1576. /*++
  1577. Routine Description:
  1578. This function sets up a conference call for the addition of the third
  1579. party.
  1580. TSPI_lineSetupConference provides two ways for establishing a new
  1581. conference call, depending on whether a normal two-party call is required
  1582. to pre-exist or not. When setting up a conference call from an existing
  1583. two-party call, the hdCall parameter is a valid call handle that is
  1584. initially added to the conference call by the TSPI_lineSetupConference
  1585. request and hdLine is ignored. On switches where conference call setup
  1586. does not start with an existing call, hdCall must be NULL and hdLine
  1587. must be specified to identify the line device on which to initiate the
  1588. conference call. In either case, a consultation call is allocated for
  1589. connecting to the party that is to be added to the call. The TAPI DLL
  1590. can use TSPI_lineDial to dial the address of the other party.
  1591. The conference call will typically transition into the
  1592. onHoldPendingConference state, the consultation call dialtone state and
  1593. the initial call (if one) into the conferenced state.
  1594. A conference call can also be set up via a TSPI_lineCompleteTransfer that
  1595. is resolved into a three-way conference.
  1596. The TAPI DLL may be able to toggle between the consultation call and the
  1597. conference call by using TSPI_lineSwapHold.
  1598. Arguments:
  1599. dwRequestID - Specifies the identifier of the asynchronous request.
  1600. The Service Provider returns this value if the function completes
  1601. asynchronously.
  1602. hdCall - Specifies the Service Provider's opaque handle to the initial
  1603. call that identifies the first party of a conference call. In some
  1604. environments, a call must exist in order to start a conference call.
  1605. In other telephony environments, no call initially exists and hdCall
  1606. is left NULL. Valid call states: connected.
  1607. hdLine - Specifies the Service Provider's opaque handle to the line device
  1608. on which to originate the conference call if hdCall is NULL. The
  1609. hdLine parameter is ignored if hdCall is non-NULL. The Service
  1610. Provider reports which model it supports through the setupConfNull
  1611. flag of the LINEADDRESSCAPS data structure.
  1612. htConfCall - Specifies the TAPI DLL's opaque handle to the new conference
  1613. call. The Service Provider must save this and use it in all subsequent
  1614. calls to the LINEEVENT procedure reporting events on the new call.
  1615. lphdConfCall - Specifies a far pointer to an opaque HDRVCALL representing
  1616. the Service Provider's identifier for the newly created conference
  1617. call. The Service Provider must fill this location with its opaque
  1618. handle for the new call before this procedure returns, whether it
  1619. decides to execute the request sychronously or asynchronously. This
  1620. handle is invalid if the function results in an error (either
  1621. synchronously or asynchronously).
  1622. htAddCall - Specifies the TAPI DLL's opaque handle to a new call. When
  1623. setting up a call for the addition of a new party, a new temporary call
  1624. (consultation call) is automatically allocated. The Service Provider
  1625. must save the htAddCall and use it in all subsequent calls to the
  1626. LINEEVENT procedure reporting events on the new consultation call.
  1627. lphdAddCall - Specifies a far pointer to an opaque HDRVCALL representing
  1628. the Service Provider's identifier for a call. When setting up a call
  1629. for the addition of a new party, a new temporary call (consultation
  1630. call) is automatically allocated. The Service Provider must fill this
  1631. location with its opaque handle for the new consultation call before
  1632. this procedure returns, whether it decides to execute the request
  1633. sychronously or asynchronously. This handle is invalid if the
  1634. function results in an error (either synchronously or asynchronously).
  1635. dwNumParties - Specifies the expected number of parties in the conference
  1636. call. The service provider is free to do with this number as it
  1637. pleases; ignore it, use it a hint to allocate the right size
  1638. conference bridge inside the switch, etc.
  1639. lpCallParams - Specifies a far pointer to call parameters to be used when
  1640. establishing the consultation call. This parameter may be set to NULL
  1641. if no special call setup parameters are desired.
  1642. Return Values:
  1643. Returns zero if the function is successful, the (positive) dwRequestID
  1644. value if the function will be completed asynchronously, or a negative error
  1645. number if an error has occurred. Possible error returns are:
  1646. LINEERR_INVALCALLHANDLE - The specified call handle for the conference
  1647. call is invalid. This error may also indicate that the telephony
  1648. environment requires an initial call to set up a conference but a
  1649. NULL call handle was supplied.
  1650. LINEERR_INVALLINEHANDLE - The specified line handle for the line
  1651. containing the conference call is invalid. This error may also
  1652. indicate that the telephony environment requires an initial line
  1653. to set up a conference but a non-NULL call handle was supplied
  1654. instead.
  1655. LINEERR_INVALCALLSTATE - The call is not in a valid state for the
  1656. requested operation.
  1657. LINEERR_CALLUNAVAIL - All call appearances on the specified address
  1658. are currently allocated.
  1659. LINEERR_CONFERENCEFULL - The requested number of parties cannot be
  1660. satisfied.
  1661. LINEERR_INVALPOINTER - One or more of the specified pointer
  1662. parameters are invalid.
  1663. LINEERR_INVALCALLPARAMS - The specified call parameters are invalid.
  1664. LINEERR_OPERATIONUNAVAIL - The specified operation is not available.
  1665. LINEERR_OPERATIONFAILED - The specified operation failed for
  1666. unspecified reason.
  1667. --*/
  1668. {
  1669. return LINEERR_OPERATIONUNAVAIL; // CODEWORK...
  1670. }
  1671. LONG
  1672. TSPIAPI
  1673. TSPI_lineRemoveFromConference(
  1674. DRV_REQUESTID dwRequestID,
  1675. HDRVCALL hdCall
  1676. )
  1677. /*++
  1678. Routine Description:
  1679. This function removes the specified call from the conference call to
  1680. which it currently belongs. The remaining calls in the conference
  1681. call are unaffected.
  1682. This operation removes a party that currently belongs to a conference
  1683. call. After the call has been successfully removed, it may be possible
  1684. to further manipulate it using its handle. The availability of this
  1685. operation and its result are likely to be limited in many
  1686. implementations. For example, in many implementations, only the most
  1687. recently added party may be removed from a conference, and the removed
  1688. call may be automatically dropped (becomes idle). Consult the line's
  1689. device capabilities to determine the available effects of removing a
  1690. call from a conference.
  1691. Arguments:
  1692. dwRequestID - Specifies the identifier of the asynchronous request.
  1693. The Service Provider returns this value if the function completes
  1694. asynchronously.
  1695. hdCall - Specifies the Service Provider's opaque handle to the call
  1696. to be removed from the conference. Valid call states: conferenced.
  1697. Return Values:
  1698. Returns zero if the function is successful, the (positive) dwRequestID
  1699. value if the function will be completed asynchronously, or a negative error
  1700. number if an error has occurred. Possible error returns are:
  1701. LINEERR_INVALCALLHANDLE - The specified call handle is invalid.
  1702. LINEERR_INVALCALLSTATE - The call is not in a valid state for the
  1703. requested operation.
  1704. LINEERR_OPERATIONUNAVAIL - The specified operation is not available.
  1705. LINEERR_OPERATIONFAILED - The specified operation failed for
  1706. unspecified reasons.
  1707. --*/
  1708. {
  1709. return LINEERR_OPERATIONUNAVAIL; // CODEWORK...
  1710. }
  1711. /*
  1712. Parameters:
  1713. dwRequestID - The identifier of the asynchronous request.
  1714. hdLine - The service provider's handle to the line to be forwarded.
  1715. bAllAddresses - Specifies whether all originating addresses on the line or
  1716. just the one specified is to be forwarded. If TRUE, all addresses on
  1717. the line are forwarded and dwAddressID is ignored; if FALSE, only the
  1718. address specified as dwAddressID is forwarded. This parameter is not
  1719. validated by TAPI when this function is called.
  1720. dwAddressID - The address on the specified line whose incoming calls are to
  1721. be forwarded. This parameter is ignored if bAllAddresses is TRUE. This
  1722. parameter is not validated by TAPI when this function is called.
  1723. lpForwardList - A pointer to a variably sized data structure of type
  1724. LINEFORWARDLIST that describes the specific forwarding instructions.
  1725. dwNumRingsNoAnswer - Specifies the number of rings before an incoming call
  1726. is considered a "no answer." If dwNumRingsNoAnswer is out of range, the
  1727. actual value is set to the nearest value in the allowable range. This
  1728. parameter is not validated by TAPI when this function is called.
  1729. htConsultCall - The TAPI handle to a new call, if such a call must be created
  1730. by the service provider. In some telephony environments, forwarding a
  1731. call has the side effect of creating a consultation call used to consult
  1732. the party that is being forwarded to. In such an environment, the service
  1733. provider creates the new consutation call and must save this value and
  1734. use it in all subsequent calls to the LINEEVENT procedure reporting
  1735. events on the call. If no consultation call is created, this value can
  1736. be ignored by the service provider.
  1737. lphdConsultCall - A pointer to an HDRVCALL representing the service
  1738. provider's identifier for the call. In telephony environments where
  1739. forwarding a call has the side effect of creating a consultation call
  1740. used to consult the party that is being forwarded to, the service
  1741. provider must fill this location with its handle for the call before
  1742. this procedure returns. The service provider is permitted to do callbacks
  1743. regarding the new call before it returns from this procedure. If no
  1744. consultation call is created, the HDRVCALL must be left NULL.
  1745. lpCallParams - A pointer to a structure of type LINECALLPARAMS. This pointer
  1746. is ignored by the service provider unless lineForward requires the
  1747. establishment of a call to the forwarding destination (and
  1748. lphdConsultCall is returned, in which case lpCallParams is optional).
  1749. If NULL, default call parameters are used. Otherwise, the specified call
  1750. parameters are used for establishing htConsultCall.
  1751. Return Values:
  1752. Returns dwRequestID or an error number if an error occurs. The lResult
  1753. actual parameter of the corresponding ASYNC_COMPLETION is zero if the
  1754. function succeeds or an error number if an error occurs. Possible return
  1755. values are as follows:
  1756. LINEERR_INVALLINEHANDLE,
  1757. LINEERR_NOMEM,
  1758. LINEERR_INVALADDRESS,
  1759. LINEERR_OPERATIONUNAVAIL,
  1760. LINEERR_INVALADDRESSID,
  1761. LINEERR_OPERATIONFAILED,
  1762. LINEERR_INVALCOUNTRYCODE,
  1763. LINEERR_RESOURCEUNAVAIL,
  1764. LINEERR_INVALPARAM,
  1765. LINEERR_STRUCTURETOOSMALL.
  1766. Remarks
  1767. */
  1768. LONG
  1769. TSPIAPI TSPI_lineForward(
  1770. DRV_REQUESTID dwRequestID,
  1771. HDRVLINE hdLine,
  1772. DWORD bAllAddresses,
  1773. DWORD dwAddressID,
  1774. LPLINEFORWARDLIST const lpForwardList,
  1775. DWORD dwNumRingsNoAnswer,
  1776. HTAPICALL htConsultCall,
  1777. LPHDRVCALL lphdConsultCall,
  1778. LPLINECALLPARAMS const lpCallParams
  1779. )
  1780. {
  1781. DWORD dwStatus = dwRequestID;
  1782. PH323_CALL pCall = NULL;
  1783. H323_CONFERENCE * pConf = NULL;
  1784. BOOL fDelete = FALSE;
  1785. DWORD dwState;
  1786. PVOID pForwardParams = NULL;
  1787. DWORD event = NULL;
  1788. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineForward - Entered." ));
  1789. //lock the line device
  1790. g_pH323Line -> Lock();
  1791. if( hdLine != g_pH323Line -> GetHDLine() )
  1792. {
  1793. g_pH323Line ->Unlock();
  1794. return LINEERR_RESOURCEUNAVAIL;
  1795. }
  1796. // validate line state
  1797. dwState = g_pH323Line -> GetState();
  1798. if( ( dwState != H323_LINESTATE_OPENED) &&
  1799. ( dwState != H323_LINESTATE_LISTENING) )
  1800. {
  1801. H323DBG(( DEBUG_LEVEL_ERROR, "H323 line is not currently opened:%d.",
  1802. dwState ));
  1803. // release line device
  1804. g_pH323Line ->Unlock();
  1805. // line needs to be opened
  1806. return LINEERR_INVALLINESTATE;
  1807. }
  1808. if( lpForwardList == NULL )
  1809. {
  1810. //forwarding is disabled
  1811. g_pH323Line -> DisableCallForwarding();
  1812. g_pH323Line ->Unlock();
  1813. *lphdConsultCall = NULL;
  1814. //inform the user about change in line forward state
  1815. (*g_pfnLineEventProc)(
  1816. g_pH323Line->m_htLine,
  1817. (HTAPICALL)NULL,
  1818. (DWORD)LINE_ADDRESSSTATE,
  1819. (DWORD)LINEADDRESSSTATE_FORWARD,
  1820. (DWORD)LINEADDRESSSTATE_FORWARD,
  1821. (DWORD)0
  1822. );
  1823. // complete the async accept operation now
  1824. H323CompleteRequest (dwRequestID, ERROR_SUCCESS);
  1825. return dwRequestID;
  1826. }
  1827. // allocate outgoing call
  1828. pCall = new CH323Call();
  1829. if( pCall == NULL )
  1830. {
  1831. H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate outgoing call." ));
  1832. // no memory available
  1833. dwStatus = LINEERR_NOMEM;
  1834. goto cleanup;
  1835. }
  1836. // save tapi handle and specify outgoing call direction
  1837. if( !pCall -> Initialize( htConsultCall, LINECALLORIGIN_OUTBOUND,
  1838. CALLTYPE_FORWARDCONSULT ) )
  1839. {
  1840. H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate outgoing call." ));
  1841. // no memory available
  1842. dwStatus = LINEERR_NOMEM;
  1843. goto cleanup;
  1844. }
  1845. dwStatus = pCall -> ValidateForwardParams(
  1846. lpForwardList, &pForwardParams, &event );
  1847. if( dwStatus != ERROR_SUCCESS )
  1848. {
  1849. // failure
  1850. goto cleanup;
  1851. }
  1852. _ASSERTE( event );
  1853. // transfer handle
  1854. *lphdConsultCall = (HDRVCALL)NULL /*pCall -> GetCallHandle()*/;
  1855. // bind outgoing call
  1856. pConf = pCall -> CreateConference(NULL);
  1857. if( pConf == NULL )
  1858. {
  1859. H323DBG(( DEBUG_LEVEL_ERROR,
  1860. "could not create conference." ));
  1861. // no memory available
  1862. dwStatus = LINEERR_NOMEM;
  1863. // failure
  1864. goto cleanup;
  1865. }
  1866. if( !g_pH323Line -> GetH323ConfTable() -> Add(pConf) )
  1867. {
  1868. H323DBG(( DEBUG_LEVEL_ERROR, "could not add conf to conf table." ));
  1869. // no memory available
  1870. dwStatus = LINEERR_NOMEM;
  1871. // failure
  1872. goto cleanup;
  1873. }
  1874. pCall -> Lock();
  1875. // post line forward request to callback thread
  1876. if( !pCall->QueueTAPICallRequest( event, (PVOID)pForwardParams ) )
  1877. {
  1878. H323DBG(( DEBUG_LEVEL_ERROR, "could not post forward message." ));
  1879. // could not complete operation
  1880. dwStatus = LINEERR_OPERATIONFAILED;
  1881. pCall-> Unlock();
  1882. // failure
  1883. goto cleanup;
  1884. }
  1885. g_pH323Line -> m_fForwardConsultInProgress = TRUE;
  1886. if( (dwNumRingsNoAnswer >= H323_NUMRINGS_LO) &&
  1887. (dwNumRingsNoAnswer <= H323_NUMRINGS_HI) )
  1888. {
  1889. g_pH323Line -> m_dwNumRingsNoAnswer = dwNumRingsNoAnswer;
  1890. }
  1891. // complete the async accept operation now
  1892. H323CompleteRequest (dwRequestID, ERROR_SUCCESS);
  1893. //unlock the call object.
  1894. pCall-> Unlock();
  1895. // release line device
  1896. g_pH323Line -> Unlock();
  1897. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineForward - Exited." ));
  1898. // success
  1899. return dwRequestID;
  1900. cleanup:
  1901. if( pCall != NULL )
  1902. {
  1903. pCall -> Shutdown( &fDelete );
  1904. H323DBG((DEBUG_LEVEL_TRACE, "call delete:%p.", pCall ));
  1905. delete pCall;
  1906. pCall = NULL;
  1907. }
  1908. *lphdConsultCall = NULL;
  1909. if( pForwardParams != NULL )
  1910. {
  1911. delete pForwardParams;
  1912. pForwardParams = NULL;
  1913. }
  1914. // release line device
  1915. g_pH323Line -> Unlock();
  1916. // failure
  1917. return dwStatus;
  1918. }
  1919. LONG
  1920. TSPIAPI TSPI_lineRedirect(
  1921. DRV_REQUESTID dwRequestID,
  1922. HDRVCALL hdCall,
  1923. LPCWSTR lpszDestAddress,
  1924. DWORD dwCountryCode
  1925. )
  1926. {
  1927. LONG retVal = (DWORD)dwRequestID;
  1928. PH323_CALL pCall = NULL;
  1929. CALLREROUTINGINFO* pCallReroutingInfo = NULL;
  1930. WORD wAliasType = h323_ID_chosen;
  1931. DWORD dwMaxAddrSize = MAX_H323_ADDR_LEN;
  1932. DWORD dwAddrLen;
  1933. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineRedirect - Entered." ));
  1934. if( lpszDestAddress == NULL )
  1935. return LINEERR_INVALPARAM;
  1936. pCall=g_pH323Line -> FindH323CallAndLock(hdCall);
  1937. if( pCall == NULL )
  1938. {
  1939. return LINEERR_INVALCALLHANDLE;
  1940. }
  1941. if( pCall -> GetCallState() != LINECALLSTATE_OFFERING )
  1942. {
  1943. H323DBG(( DEBUG_LEVEL_ERROR, "call 0x%08lx not ringback.", pCall ));
  1944. pCall -> Unlock();
  1945. return LINEERR_INVALCALLSTATE;
  1946. }
  1947. if( (*lpszDestAddress==L'T') &&
  1948. IsValidE164String((WCHAR*)lpszDestAddress+1) )
  1949. {
  1950. wAliasType = e164_chosen;
  1951. //strip off the leading 'T'
  1952. lpszDestAddress++;
  1953. dwMaxAddrSize = MAX_E164_ADDR_LEN;
  1954. }
  1955. else if( IsValidE164String( (WCHAR*)lpszDestAddress) )
  1956. {
  1957. wAliasType = e164_chosen;
  1958. dwMaxAddrSize = MAX_E164_ADDR_LEN;
  1959. }
  1960. dwAddrLen = wcslen(lpszDestAddress);
  1961. if( (dwAddrLen > dwMaxAddrSize) || (dwAddrLen == 0) )
  1962. {
  1963. return LINEERR_INVALPARAM;
  1964. }
  1965. retVal = pCall -> SetDivertedToAlias( (WCHAR*)lpszDestAddress, wAliasType );
  1966. if( retVal != NOERROR )
  1967. {
  1968. pCall->Unlock();
  1969. return retVal;
  1970. }
  1971. if( !pCall -> QueueTAPICallRequest( TSPI_CALL_DIVERT, NULL ))
  1972. {
  1973. H323DBG(( DEBUG_LEVEL_ERROR, "could not post call divert event." ));
  1974. pCall -> Unlock();
  1975. return LINEERR_OPERATIONFAILED;
  1976. }
  1977. // complete the async accept operation now
  1978. H323CompleteRequest (dwRequestID, ERROR_SUCCESS);
  1979. pCall -> Unlock();
  1980. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineRedirect - Exited." ));
  1981. return dwRequestID;
  1982. }
  1983. LONG TSPIAPI TSPI_lineUnhold (
  1984. DRV_REQUESTID dwRequestID,
  1985. HDRVCALL hdCall
  1986. )
  1987. {
  1988. LONG retVal = (DWORD)dwRequestID;
  1989. PH323_CALL pCall = NULL;
  1990. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineUnHold - Entered." ));
  1991. pCall=g_pH323Line -> FindH323CallAndLock(hdCall);
  1992. if( pCall == NULL )
  1993. {
  1994. return LINEERR_INVALCALLHANDLE;
  1995. }
  1996. if( pCall -> IsCallOnHold() == FALSE )
  1997. {
  1998. H323DBG(( DEBUG_LEVEL_ERROR, "call 0x%08lx not ringback.", pCall ));
  1999. pCall -> Unlock();
  2000. return LINEERR_INVALCALLSTATE;
  2001. }
  2002. if( !pCall -> QueueTAPICallRequest( TSPI_CALL_UNHOLD, NULL ))
  2003. {
  2004. H323DBG(( DEBUG_LEVEL_ERROR, "could not post transfer complete event." ));
  2005. pCall -> Unlock();
  2006. return LINEERR_OPERATIONFAILED;
  2007. }
  2008. // complete the async accept operation now
  2009. H323CompleteRequest (dwRequestID, ERROR_SUCCESS);
  2010. pCall -> Unlock();
  2011. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineUnHold - Exited." ));
  2012. return dwRequestID;
  2013. }
  2014. LONG TSPIAPI TSPI_lineHold(
  2015. DRV_REQUESTID dwRequestID,
  2016. HDRVCALL hdCall
  2017. )
  2018. {
  2019. LONG retVal = (DWORD)dwRequestID;
  2020. PH323_CALL pCall = NULL;
  2021. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineHold - Entered." ));
  2022. pCall=g_pH323Line -> FindH323CallAndLock(hdCall);
  2023. if( pCall == NULL )
  2024. {
  2025. return LINEERR_INVALCALLHANDLE;
  2026. }
  2027. if( (pCall -> GetCallState() != LINECALLSTATE_CONNECTED) ||
  2028. (pCall -> IsCallOnHold()) )
  2029. {
  2030. H323DBG(( DEBUG_LEVEL_ERROR, "call 0x%08lx not ringback.", pCall ));
  2031. pCall -> Unlock();
  2032. return LINEERR_INVALCALLSTATE;
  2033. }
  2034. if( !pCall -> QueueTAPICallRequest( TSPI_CALL_HOLD, NULL ))
  2035. {
  2036. H323DBG(( DEBUG_LEVEL_ERROR, "could not post transfer complete event." ));
  2037. pCall -> Unlock();
  2038. return LINEERR_OPERATIONFAILED;
  2039. }
  2040. // complete the async accept operation now
  2041. H323CompleteRequest (dwRequestID, ERROR_SUCCESS);
  2042. pCall -> Unlock();
  2043. H323DBG(( DEBUG_LEVEL_TRACE, "TSPI_lineHold - Exited." ));
  2044. return retVal;
  2045. }
  2046. BOOL
  2047. CH323Call::ResolveToIPAddress(
  2048. IN WCHAR* pwszAddr,
  2049. IN SOCKADDR_IN* psaAddr
  2050. )
  2051. {
  2052. CHAR szDelimiters[] = "@ \t\n";
  2053. CHAR szAddr[H323_MAXDESTNAMELEN+1];
  2054. LPSTR pszUser = NULL;
  2055. LPSTR pszDomain = NULL;
  2056. DWORD dwIPAddr;
  2057. struct hostent* pHost;
  2058. H323DBG(( DEBUG_LEVEL_ERROR, "ResolveToIPAddress entered:%p.",this ));
  2059. ZeroMemory( psaAddr, sizeof(SOCKADDR) );
  2060. // validate pointerr
  2061. if (pwszAddr == NULL)
  2062. {
  2063. H323DBG(( DEBUG_LEVEL_ERROR, "null destination address." ));
  2064. // failure
  2065. return FALSE;
  2066. }
  2067. // convert address from unicode
  2068. if (WideCharToMultiByte(
  2069. CP_ACP,
  2070. 0,
  2071. pwszAddr,
  2072. -1,
  2073. szAddr,
  2074. sizeof(szAddr),
  2075. NULL,
  2076. NULL
  2077. ) == 0)
  2078. {
  2079. H323DBG(( DEBUG_LEVEL_ERROR,
  2080. "could not convert address from unicode." ));
  2081. // failure
  2082. return FALSE;
  2083. }
  2084. // check whether phone number has been specified
  2085. if( IsPhoneNumber( szAddr ) )
  2086. {
  2087. // need to direct call to pstn gateway
  2088. if ((g_RegistrySettings.fIsGatewayEnabled == FALSE) ||
  2089. (g_RegistrySettings.gatewayAddr.nAddrType == 0))
  2090. {
  2091. H323DBG(( DEBUG_LEVEL_ERROR, "pstn gateway not specified." ));
  2092. // failure
  2093. return FALSE;
  2094. }
  2095. psaAddr->sin_family = AF_INET;
  2096. psaAddr->sin_addr.S_un.S_addr =
  2097. htonl( g_RegistrySettings.gatewayAddr.Addr.IP_Binary.dwAddr );
  2098. psaAddr->sin_port = g_RegistrySettings.gatewayAddr.Addr.IP_Binary.wPort;
  2099. return TRUE;
  2100. }
  2101. // parse user name
  2102. pszUser = strtok(szAddr, szDelimiters);
  2103. // parse domain name
  2104. pszDomain = strtok(NULL, szDelimiters);
  2105. // validate pointer
  2106. if (pszUser == NULL)
  2107. {
  2108. H323DBG(( DEBUG_LEVEL_ERROR,
  2109. "could not parse destination address." ));
  2110. // failure
  2111. return FALSE;
  2112. }
  2113. // validate pointer
  2114. if (pszDomain == NULL)
  2115. {
  2116. // switch pointers
  2117. pszDomain = pszUser;
  2118. // re-initialize
  2119. pszUser = NULL;
  2120. }
  2121. H323DBG(( DEBUG_LEVEL_VERBOSE,
  2122. "resolving user %s domain %s.",
  2123. pszUser, pszDomain ));
  2124. // attempt to convert ip address
  2125. dwIPAddr = inet_addr(szAddr);
  2126. // see if address converted
  2127. if( dwIPAddr == INADDR_NONE )
  2128. {
  2129. // attempt to lookup hostname
  2130. pHost = gethostbyname(szAddr);
  2131. // validate pointer
  2132. if( pHost != NULL )
  2133. {
  2134. // retrieve host address from structure
  2135. dwIPAddr = *(unsigned long *)pHost->h_addr;
  2136. }
  2137. }
  2138. // see if address converted
  2139. if( dwIPAddr == INADDR_NONE )
  2140. {
  2141. H323DBG(( DEBUG_LEVEL_ERROR,
  2142. "error 0x%08lx resolving IP address.",
  2143. WSAGetLastError() ));
  2144. // make sure proxy has been specified
  2145. if ((g_RegistrySettings.fIsProxyEnabled == FALSE) ||
  2146. (g_RegistrySettings.proxyAddr.nAddrType == 0))
  2147. {
  2148. H323DBG(( DEBUG_LEVEL_ERROR, "proxy not specified." ));
  2149. // failure
  2150. return FALSE;
  2151. }
  2152. psaAddr->sin_family = AF_INET;
  2153. psaAddr->sin_addr.S_un.S_addr =
  2154. htonl( g_RegistrySettings.proxyAddr.Addr.IP_Binary.dwAddr );
  2155. psaAddr->sin_port = g_RegistrySettings.proxyAddr.Addr.IP_Binary.wPort;
  2156. return TRUE;
  2157. }
  2158. // save converted address
  2159. psaAddr->sin_family = AF_INET;
  2160. psaAddr->sin_addr.S_un.S_addr = dwIPAddr;
  2161. H323DBG(( DEBUG_LEVEL_TRACE,
  2162. "callee address resolved to %s:%d.",
  2163. H323AddrToString(dwIPAddr),
  2164. m_CalleeAddr.Addr.IP_Binary.wPort ));
  2165. return TRUE;
  2166. }
  2167. //!!always called in a lock
  2168. LONG
  2169. CH323Line::CopyAddressForwardInfo(
  2170. IN LPLINEADDRESSSTATUS lpAddressStatus
  2171. )
  2172. {
  2173. LINEFORWARD * lineForwardStructArray;
  2174. LPFORWARDADDRESS pForwardedAddress;
  2175. if( m_pCallForwardParams-> fForwardForAllOrigins == TRUE )
  2176. {
  2177. lpAddressStatus->dwForwardNumEntries = 1;
  2178. lpAddressStatus->dwForwardSize = sizeof(LINEFORWARD) +
  2179. sizeof(WCHAR) * (m_pCallForwardParams->divertedToAlias.wDataLength+1);
  2180. }
  2181. else
  2182. {
  2183. lpAddressStatus->dwForwardNumEntries = 0;
  2184. pForwardedAddress = m_pCallForwardParams->pForwardedAddresses;
  2185. while( pForwardedAddress )
  2186. {
  2187. lpAddressStatus->dwForwardNumEntries++;
  2188. lpAddressStatus->dwForwardSize += sizeof(LINEFORWARD) +
  2189. sizeof(WCHAR) * (pForwardedAddress->callerAlias.wDataLength+1) +
  2190. sizeof(WCHAR) * (pForwardedAddress->divertedToAlias.wDataLength+1);
  2191. pForwardedAddress = pForwardedAddress->next;
  2192. }
  2193. }
  2194. lpAddressStatus->dwNeededSize += lpAddressStatus->dwForwardSize;
  2195. if( lpAddressStatus->dwTotalSize < lpAddressStatus->dwNeededSize )
  2196. {
  2197. return LINEERR_STRUCTURETOOSMALL;
  2198. }
  2199. lineForwardStructArray = (LINEFORWARD*)
  2200. ((BYTE*)lpAddressStatus + lpAddressStatus->dwUsedSize);
  2201. lpAddressStatus->dwUsedSize += lpAddressStatus->dwForwardNumEntries *
  2202. sizeof(LINEFORWARD);
  2203. if( m_pCallForwardParams-> fForwardForAllOrigins == TRUE )
  2204. {
  2205. //copy the first structure
  2206. lineForwardStructArray[0].dwForwardMode =
  2207. m_pCallForwardParams->dwForwardTypeForAllOrigins;
  2208. //copy dest address alias
  2209. lineForwardStructArray[0].dwDestAddressOffset =
  2210. lpAddressStatus->dwUsedSize;
  2211. lineForwardStructArray[0].dwDestAddressSize =
  2212. sizeof(WCHAR)* (m_pCallForwardParams->divertedToAlias.wDataLength + 1);
  2213. CopyMemory(
  2214. (PVOID)((BYTE*)lpAddressStatus+lpAddressStatus->dwUsedSize),
  2215. m_pCallForwardParams->divertedToAlias.pData,
  2216. lineForwardStructArray[0].dwDestAddressSize );
  2217. lpAddressStatus->dwUsedSize +=
  2218. lineForwardStructArray[0].dwDestAddressSize;
  2219. lineForwardStructArray[0].dwDestCountryCode = 0;
  2220. }
  2221. else
  2222. {
  2223. pForwardedAddress = m_pCallForwardParams->pForwardedAddresses;
  2224. for( DWORD indexI = 0; indexI < lpAddressStatus->dwForwardNumEntries; indexI++ )
  2225. {
  2226. _ASSERTE( pForwardedAddress );
  2227. lineForwardStructArray[indexI].dwForwardMode =
  2228. pForwardedAddress->dwForwardType;
  2229. //copy caller address alias
  2230. lineForwardStructArray[indexI].dwCallerAddressOffset =
  2231. lpAddressStatus->dwUsedSize;
  2232. lineForwardStructArray[indexI].dwCallerAddressSize =
  2233. sizeof(WCHAR)* (pForwardedAddress->callerAlias.wDataLength + 1);
  2234. CopyMemory(
  2235. (PVOID)((BYTE*)lpAddressStatus+lpAddressStatus->dwUsedSize),
  2236. (PVOID)pForwardedAddress->callerAlias.pData,
  2237. lineForwardStructArray[indexI].dwCallerAddressSize );
  2238. lpAddressStatus->dwUsedSize +=
  2239. lineForwardStructArray[indexI].dwCallerAddressSize;
  2240. //copy dest address alias
  2241. lineForwardStructArray[indexI].dwDestAddressOffset =
  2242. lpAddressStatus->dwUsedSize;
  2243. lineForwardStructArray[indexI].dwDestAddressSize =
  2244. sizeof(WCHAR)* (pForwardedAddress->divertedToAlias.wDataLength + 1);
  2245. CopyMemory(
  2246. (PVOID)((BYTE*)lpAddressStatus+lpAddressStatus->dwUsedSize),
  2247. pForwardedAddress->divertedToAlias.pData,
  2248. lineForwardStructArray[indexI].dwDestAddressSize);
  2249. lpAddressStatus->dwUsedSize +=
  2250. lineForwardStructArray[indexI].dwDestAddressSize;
  2251. lineForwardStructArray[indexI].dwDestCountryCode = 0;
  2252. pForwardedAddress = pForwardedAddress->next;
  2253. }
  2254. }
  2255. _ASSERTE( lpAddressStatus->dwUsedSize == lpAddressStatus->dwNeededSize);
  2256. return NOERROR;
  2257. }
  2258. //!!always called in a lock
  2259. LONG
  2260. CH323Call::ValidateForwardParams(
  2261. IN LPLINEFORWARDLIST lpLineForwardList,
  2262. OUT PVOID* ppForwardParams,
  2263. OUT DWORD* pEvent
  2264. )
  2265. {
  2266. LPLINEFORWARD pLineForwardStruct;
  2267. LPWSTR pwszDestAddr = NULL;
  2268. LPWSTR pAllocAddrBuffer = NULL;
  2269. DWORD dwStatus = ERROR_SUCCESS;
  2270. CALLFORWARDPARAMS * pCallForwardParams = NULL;
  2271. FORWARDADDRESS * pForwardAddress = NULL;
  2272. WORD wAliasType = h323_ID_chosen;
  2273. DWORD dwMaxAddrSize = MAX_H323_ADDR_LEN;
  2274. DWORD dwAddrLen;
  2275. *pEvent = 0;
  2276. if( (lpLineForwardList->dwNumEntries == 0) ||
  2277. (lpLineForwardList->dwTotalSize == 0) )
  2278. {
  2279. return LINEERR_INVALPARAM;
  2280. }
  2281. pLineForwardStruct = &(lpLineForwardList->ForwardList[0]);
  2282. if( pLineForwardStruct->dwDestAddressSize == 0 )
  2283. {
  2284. return LINEERR_INVALPARAM;
  2285. }
  2286. //resolve the diverted-to address
  2287. pAllocAddrBuffer = pwszDestAddr =
  2288. (WCHAR*)new BYTE[pLineForwardStruct->dwDestAddressSize];
  2289. if( pwszDestAddr == NULL )
  2290. {
  2291. return LINEERR_NOMEM;
  2292. }
  2293. CopyMemory( pwszDestAddr,
  2294. (BYTE*)lpLineForwardList + pLineForwardStruct->dwDestAddressOffset,
  2295. pLineForwardStruct->dwDestAddressSize );
  2296. //If negotiated version is 3.1 get the alias type
  2297. if( g_dwTSPIVersion >= 0x00030001 )
  2298. {
  2299. switch( pLineForwardStruct->dwDestAddressType )
  2300. {
  2301. case LINEADDRESSTYPE_PHONENUMBER:
  2302. wAliasType = e164_chosen;
  2303. if( *pwszDestAddr == L'T' )
  2304. {
  2305. //strip off the leading 'T'
  2306. pwszDestAddr++;
  2307. }
  2308. if( IsValidE164String( (WCHAR*)pwszDestAddr) == FALSE )
  2309. {
  2310. delete pAllocAddrBuffer;
  2311. return LINEERR_INVALPARAM;
  2312. }
  2313. dwMaxAddrSize = MAX_E164_ADDR_LEN;
  2314. break;
  2315. case LINEADDRESSTYPE_DOMAINNAME:
  2316. case LINEADDRESSTYPE_IPADDRESS:
  2317. wAliasType = h323_ID_chosen;
  2318. break;
  2319. default:
  2320. H323DBG(( DEBUG_LEVEL_VERBOSE, "Wrong address type:.",
  2321. pLineForwardStruct->dwDestAddressType ));
  2322. delete pAllocAddrBuffer;
  2323. return LINEERR_INVALPARAM;
  2324. }
  2325. }
  2326. else
  2327. {
  2328. if( (*pwszDestAddr==L'T') &&
  2329. IsValidE164String((WCHAR*)pwszDestAddr+1) )
  2330. {
  2331. wAliasType = e164_chosen;
  2332. //strip off the leading 'T'
  2333. pwszDestAddr++;
  2334. dwMaxAddrSize = MAX_E164_ADDR_LEN;
  2335. }
  2336. else if( IsValidE164String( (WCHAR*)pwszDestAddr) )
  2337. {
  2338. wAliasType = e164_chosen;
  2339. dwMaxAddrSize = MAX_E164_ADDR_LEN;
  2340. }
  2341. }
  2342. dwAddrLen = wcslen( pwszDestAddr );
  2343. if( (dwAddrLen > dwMaxAddrSize) || (dwAddrLen == 0) )
  2344. {
  2345. delete pAllocAddrBuffer;
  2346. return LINEERR_INVALPARAM;
  2347. }
  2348. m_dwAddressType = wAliasType;
  2349. //don't resolve the address if GK enabled
  2350. if( !ResolveAddress( pwszDestAddr ) )
  2351. {
  2352. if( !RasIsRegistered())
  2353. {
  2354. delete pAllocAddrBuffer;
  2355. return LINEERR_INVALPARAM;
  2356. }
  2357. }
  2358. else if(m_CallerAddr.Addr.IP_Binary.dwAddr == HOST_LOCAL_IP_ADDR_INTERFACE )
  2359. {
  2360. delete pAllocAddrBuffer;
  2361. return LINEERR_INVALPARAM;
  2362. }
  2363. if( !SetCalleeAlias( (WCHAR*)pwszDestAddr, wAliasType ) )
  2364. {
  2365. H323DBG(( DEBUG_LEVEL_ERROR, "could not set callee alias." ));
  2366. delete pAllocAddrBuffer;
  2367. return LINEERR_NOMEM;
  2368. }
  2369. switch( pLineForwardStruct->dwForwardMode )
  2370. {
  2371. case LINEFORWARDMODE_UNCOND:
  2372. case LINEFORWARDMODE_BUSY:
  2373. case LINEFORWARDMODE_NOANSW:
  2374. case LINEFORWARDMODE_BUSYNA:
  2375. pCallForwardParams = new CALLFORWARDPARAMS;
  2376. if( pCallForwardParams == NULL )
  2377. {
  2378. delete pAllocAddrBuffer;
  2379. return LINEERR_NOMEM;
  2380. }
  2381. ZeroMemory( pCallForwardParams, sizeof(CALLFORWARDPARAMS) );
  2382. //Forward all calls unconditionally, irrespective of their origin.
  2383. pCallForwardParams->fForwardForAllOrigins = TRUE;
  2384. pCallForwardParams->dwForwardTypeForAllOrigins =
  2385. pLineForwardStruct->dwForwardMode;
  2386. //set the diverted-to alias
  2387. pCallForwardParams->divertedToAlias.wType = wAliasType;
  2388. pCallForwardParams->divertedToAlias.wPrefixLength = 0;
  2389. pCallForwardParams->divertedToAlias.pPrefix = NULL;
  2390. pCallForwardParams->divertedToAlias.wDataLength =
  2391. (WORD)wcslen(pwszDestAddr);// UNICODE character count
  2392. pCallForwardParams->divertedToAlias.pData = pwszDestAddr;
  2393. //enable forwarding
  2394. pCallForwardParams->fForwardingEnabled = TRUE;
  2395. *ppForwardParams = (PVOID)pCallForwardParams;
  2396. *pEvent = TSPI_LINEFORWARD_NOSPECIFIC;
  2397. break;
  2398. case LINEFORWARDMODE_BUSYNASPECIFIC:
  2399. case LINEFORWARDMODE_UNCONDSPECIFIC:
  2400. case LINEFORWARDMODE_BUSYSPECIFIC:
  2401. case LINEFORWARDMODE_NOANSWSPECIFIC:
  2402. if( pLineForwardStruct-> dwCallerAddressSize == 0 )
  2403. {
  2404. delete pAllocAddrBuffer;
  2405. return LINEERR_INVALPARAM;
  2406. }
  2407. /*if( g_pH323Line->ForwardEnabledForAllOrigins() )
  2408. {
  2409. //specific forward can't be enabled when non-specific forward for
  2410. //all caller addresses is enabled
  2411. delete pAllocAddrBuffer;
  2412. return LINEERR_INVALPARAM;
  2413. }*/
  2414. pForwardAddress = new FORWARDADDRESS;
  2415. if( pForwardAddress == NULL )
  2416. {
  2417. delete pAllocAddrBuffer;
  2418. return LINEERR_NOMEM;
  2419. }
  2420. ZeroMemory( pForwardAddress, sizeof(FORWARDADDRESS) );
  2421. pForwardAddress->dwForwardType = pLineForwardStruct->dwForwardMode;
  2422. //set the caller alias(alias to be forward).
  2423. pForwardAddress->callerAlias.wType = h323_ID_chosen;
  2424. pForwardAddress->callerAlias.pData =
  2425. (WCHAR*)new BYTE[pLineForwardStruct-> dwCallerAddressSize];
  2426. if( pForwardAddress->callerAlias.pData == NULL )
  2427. {
  2428. delete pForwardAddress;
  2429. delete pAllocAddrBuffer;
  2430. return LINEERR_NOMEM;
  2431. }
  2432. CopyMemory( pForwardAddress->callerAlias.pData,
  2433. (BYTE*)lpLineForwardList + pLineForwardStruct->dwCallerAddressOffset,
  2434. pLineForwardStruct-> dwCallerAddressSize );
  2435. pForwardAddress->callerAlias.wDataLength =
  2436. (WORD)wcslen( pForwardAddress->callerAlias.pData );
  2437. //set the diverted-to alias.
  2438. pForwardAddress->divertedToAlias.wType = wAliasType;
  2439. pForwardAddress->divertedToAlias.wDataLength =
  2440. (WORD)wcslen( pwszDestAddr );
  2441. pForwardAddress->divertedToAlias.pData = pwszDestAddr;
  2442. //set the diverted-to address
  2443. /*pForwardAddress->saDivertedToAddr.sin_family = AF_INET;
  2444. pForwardAddress->saDivertedToAddr.sin_addr.S_un.S_addr
  2445. = htonl( m_CalleeAddr.Addr.IP_Binary.dwAddr );
  2446. pForwardAddress->saDivertedToAddr.sin_port =
  2447. htons( m_CalleeAddr.Addr.IP_Binary.wPort );*/
  2448. //here we could have a for loop and process multiple pLineForwardStructs
  2449. //post the event for line forward
  2450. *ppForwardParams = (PVOID)pForwardAddress;
  2451. *pEvent = TSPI_LINEFORWARD_SPECIFIC;
  2452. break;
  2453. case LINEFORWARDMODE_UNCONDINTERNAL:
  2454. case LINEFORWARDMODE_UNCONDEXTERNAL:
  2455. case LINEFORWARDMODE_BUSYINTERNAL:
  2456. case LINEFORWARDMODE_BUSYEXTERNAL:
  2457. case LINEFORWARDMODE_NOANSWINTERNAL:
  2458. case LINEFORWARDMODE_NOANSWEXTERNAL:
  2459. case LINEFORWARDMODE_BUSYNAINTERNAL:
  2460. case LINEFORWARDMODE_BUSYNAEXTERNAL:
  2461. delete pAllocAddrBuffer;
  2462. return LINEERR_INVALPARAM;
  2463. default:
  2464. delete pAllocAddrBuffer;
  2465. return LINEERR_INVALPARAM;
  2466. }
  2467. return ERROR_SUCCESS;
  2468. }
  2469. void
  2470. CH323Call::Forward(
  2471. DWORD event,
  2472. PVOID pForwardInfo
  2473. )
  2474. {
  2475. WCHAR * pwszDialableAddr;
  2476. WCHAR * wszMachineName;
  2477. WORD wAliasType = h323_ID_chosen;
  2478. if( event == TSPI_LINEFORWARD_SPECIFIC )
  2479. {
  2480. m_pForwardAddress = (LPFORWARDADDRESS)pForwardInfo;
  2481. pwszDialableAddr = m_pForwardAddress->divertedToAlias.pData;
  2482. wAliasType = m_pForwardAddress->divertedToAlias.wType;
  2483. }
  2484. else if( event == TSPI_LINEFORWARD_NOSPECIFIC )
  2485. {
  2486. m_pCallForwardParams = (CALLFORWARDPARAMS*)pForwardInfo;
  2487. pwszDialableAddr = m_pCallForwardParams->divertedToAlias.pData;
  2488. wAliasType = m_pCallForwardParams->divertedToAlias.wType;
  2489. }
  2490. else
  2491. {
  2492. // Wrong event, shouldn't get
  2493. // here at all...
  2494. return;
  2495. }
  2496. _ASSERTE( pwszDialableAddr );
  2497. //set the values for m_pCalleeAliasNames
  2498. if( !AddAliasItem( m_pCalleeAliasNames,
  2499. (BYTE*)(pwszDialableAddr),
  2500. sizeof(WCHAR) * (wcslen(pwszDialableAddr) + 1 ),
  2501. wAliasType ) )
  2502. {
  2503. H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate callee name." ));
  2504. DropCall( 0 );
  2505. }
  2506. if( RasIsRegistered() )
  2507. {
  2508. PH323_ALIASNAMES pAliasList = RASGetRegisteredAliasList();
  2509. H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
  2510. if( !AddAliasItem( m_pCallerAliasNames,
  2511. pAliasList->pItems[0].pData,
  2512. pAliasList->pItems[0].wType ) )
  2513. {
  2514. H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate caller name." ));
  2515. DropCall( 0 );
  2516. }
  2517. //set the value of m_pCalleeAddr
  2518. else if( !SendARQ( NOT_RESEND_SEQ_NUM ) )
  2519. {
  2520. // drop call using disconnect mode
  2521. DropCall( 0 );
  2522. }
  2523. H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
  2524. }
  2525. else
  2526. {
  2527. wszMachineName = g_pH323Line->GetMachineName();
  2528. H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
  2529. //set the value for m_pCallerAliasNames
  2530. if( !AddAliasItem( m_pCallerAliasNames,
  2531. (BYTE*)(wszMachineName),
  2532. sizeof(WCHAR) * (wcslen(wszMachineName) + 1 ),
  2533. h323_ID_chosen ) )
  2534. {
  2535. H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate caller name." ));
  2536. DropCall( 0 );
  2537. }
  2538. else if( !PlaceCall() )
  2539. {
  2540. // drop call using disconnect mode
  2541. DropCall( LINEDISCONNECTMODE_UNREACHABLE );
  2542. }
  2543. H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
  2544. }
  2545. }
  2546. //returns the alias of the divertedTo endpoint
  2547. PH323_ALIASITEM
  2548. CH323Line::CallToBeDiverted(
  2549. IN WCHAR* pwszCallerName,
  2550. IN DWORD dwCallerNameSize,
  2551. IN DWORD dwForwardMode
  2552. )
  2553. {
  2554. LPFORWARDADDRESS pForwardAddress;
  2555. DWORD dwForwardCallerLength;
  2556. H323DBG(( DEBUG_LEVEL_TRACE, "CallToBeDiverted entered:%p.", this ));
  2557. if( (m_pCallForwardParams == NULL) ||
  2558. (!m_pCallForwardParams->fForwardingEnabled) )
  2559. {
  2560. return NULL;
  2561. }
  2562. if( m_pCallForwardParams->fForwardForAllOrigins == TRUE )
  2563. {
  2564. if( m_pCallForwardParams->dwForwardTypeForAllOrigins & dwForwardMode )
  2565. {
  2566. return &(m_pCallForwardParams->divertedToAlias);
  2567. }
  2568. if( m_pCallForwardParams->dwForwardTypeForAllOrigins ==
  2569. LINEFORWARDMODE_BUSYNA )
  2570. {
  2571. if( (dwForwardMode == LINEFORWARDMODE_BUSY) ||
  2572. (dwForwardMode == LINEFORWARDMODE_NOANSW) )
  2573. {
  2574. return &(m_pCallForwardParams->divertedToAlias);
  2575. }
  2576. }
  2577. }
  2578. if( pwszCallerName == NULL )
  2579. {
  2580. return NULL;
  2581. }
  2582. pForwardAddress = m_pCallForwardParams->pForwardedAddresses;
  2583. while( pForwardAddress )
  2584. {
  2585. dwForwardCallerLength = (pForwardAddress->callerAlias.wDataLength +1)*sizeof(WCHAR);
  2586. if( (dwForwardCallerLength == dwCallerNameSize) &&
  2587. (memcmp( pwszCallerName, (PVOID)(pForwardAddress->callerAlias.pData),
  2588. dwCallerNameSize) == 0 ) )
  2589. {
  2590. if( pForwardAddress->dwForwardType & dwForwardMode )
  2591. return &(pForwardAddress->divertedToAlias);
  2592. if( pForwardAddress->dwForwardType == LINEFORWARDMODE_BUSYNA )
  2593. {
  2594. if( (dwForwardMode == LINEFORWARDMODE_BUSY) ||
  2595. (dwForwardMode == LINEFORWARDMODE_NOANSW) )
  2596. {
  2597. return &(pForwardAddress->divertedToAlias);
  2598. }
  2599. }
  2600. return NULL;
  2601. }
  2602. pForwardAddress = pForwardAddress->next;
  2603. }
  2604. H323DBG(( DEBUG_LEVEL_TRACE, "CallToBeDiverted exited:%p.", this ));
  2605. return NULL;
  2606. }
  2607. LONG
  2608. TSPIAPI
  2609. TSPI_lineSetStatusMessages(
  2610. HDRVLINE hdLine,
  2611. DWORD dwLineStates,
  2612. DWORD dwAddressStates
  2613. )
  2614. {
  2615. return NOERROR;
  2616. }
  2617. #if DBG
  2618. DWORD
  2619. SendMSPMessageOnRelatedCall(
  2620. IN PVOID ContextParameter
  2621. )
  2622. {
  2623. __try
  2624. {
  2625. return SendMSPMessageOnRelatedCallFre( ContextParameter );
  2626. }
  2627. __except( 1 )
  2628. {
  2629. MSPMessageData* pMSPMessageData = (MSPMessageData*)ContextParameter;
  2630. H323DBG(( DEBUG_LEVEL_TRACE,
  2631. "TSPI event threw exception: %p, %d, %p, %d, %p.",
  2632. pMSPMessageData -> hdCall,
  2633. pMSPMessageData -> messageType,
  2634. pMSPMessageData -> pbEncodedBuf,
  2635. pMSPMessageData -> wLength,
  2636. pMSPMessageData -> hReplacementCall ));
  2637. _ASSERTE( FALSE );
  2638. return 0;
  2639. }
  2640. }
  2641. #endif
  2642. DWORD
  2643. SendMSPMessageOnRelatedCallFre(
  2644. IN PVOID ContextParameter
  2645. )
  2646. {
  2647. H323DBG(( DEBUG_LEVEL_TRACE, "SendMSPMessageOnRelatedCall entered." ));
  2648. _ASSERTE( ContextParameter );
  2649. MSPMessageData* pMSPMessageData = (MSPMessageData*)ContextParameter;
  2650. PH323_CALL pCall = NULL;
  2651. pCall = g_pH323Line->FindH323CallAndLock(pMSPMessageData -> hdCall);
  2652. if( pCall != NULL )
  2653. {
  2654. pCall -> SendMSPMessage( pMSPMessageData->messageType,
  2655. pMSPMessageData->pbEncodedBuf, pMSPMessageData->wLength,
  2656. pMSPMessageData->hReplacementCall );
  2657. pCall -> Unlock();
  2658. }
  2659. if( pMSPMessageData->pbEncodedBuf != NULL )
  2660. {
  2661. delete pMSPMessageData->pbEncodedBuf;
  2662. }
  2663. delete pMSPMessageData;
  2664. H323DBG(( DEBUG_LEVEL_TRACE, "SendMSPMessageOnRelatedCall exited." ));
  2665. return EXIT_SUCCESS;
  2666. }
  2667. // static
  2668. void
  2669. NTAPI CH323Call::CTIdentifyExpiredCallback(
  2670. IN PVOID DriverCallHandle, // HDRVCALL
  2671. IN BOOLEAN bTimer
  2672. )
  2673. {
  2674. PH323_CALL pCall = NULL;
  2675. H323DBG(( DEBUG_LEVEL_TRACE, "CTIdentifyExpiredCallback entered." ));
  2676. //if the timer expired
  2677. _ASSERTE( bTimer );
  2678. H323DBG(( DEBUG_LEVEL_TRACE, "CTIdentity expired event recvd." ));
  2679. pCall=g_pH323Line -> FindH323CallAndLock((HDRVCALL) DriverCallHandle);
  2680. if( pCall != NULL )
  2681. {
  2682. pCall -> CTIdentifyExpired();
  2683. pCall -> Unlock();
  2684. }
  2685. H323DBG(( DEBUG_LEVEL_TRACE, "CTIdentifyExpiredCallback exited." ));
  2686. }
  2687. // static
  2688. void
  2689. NTAPI CH323Call::CTIdentifyRRExpiredCallback(
  2690. IN PVOID DriverCallHandle, // HDRVCALL
  2691. IN BOOLEAN bTimer
  2692. )
  2693. {
  2694. PH323_CALL pCall = NULL;
  2695. H323DBG(( DEBUG_LEVEL_TRACE, "CTIdentifyRRExpiredCallback entered." ));
  2696. //if the timer expired
  2697. _ASSERTE( bTimer );
  2698. H323DBG(( DEBUG_LEVEL_TRACE, "CTIdentity expired event recvd." ));
  2699. pCall=g_pH323Line -> FindH323CallAndLock((HDRVCALL) DriverCallHandle);
  2700. if( pCall != NULL )
  2701. {
  2702. pCall -> CTIdentifyRRExpired();
  2703. pCall -> Unlock();
  2704. }
  2705. H323DBG(( DEBUG_LEVEL_TRACE, "CTIdentifyRRExpiredCallback exited." ));
  2706. }
  2707. // static
  2708. void
  2709. NTAPI CH323Call::CTInitiateExpiredCallback(
  2710. IN PVOID DriverCallHandle, // HDRVCALL
  2711. IN BOOLEAN bTimer
  2712. )
  2713. {
  2714. PH323_CALL pCall = NULL;
  2715. H323DBG(( DEBUG_LEVEL_TRACE, "CTInitiateExpiredCallback entered." ));
  2716. //if the timer expired
  2717. _ASSERTE( bTimer );
  2718. H323DBG(( DEBUG_LEVEL_TRACE, "CTInitiate expired event recvd." ));
  2719. if( !QueueTAPILineRequest(
  2720. TSPI_CLOSE_CALL,
  2721. (HDRVCALL)DriverCallHandle,
  2722. NULL,
  2723. LINEDISCONNECTMODE_NOANSWER,
  2724. NULL) )
  2725. {
  2726. H323DBG(( DEBUG_LEVEL_TRACE, "could not post close call event." ));
  2727. }
  2728. H323DBG(( DEBUG_LEVEL_TRACE, "CTInitiateExpiredCallback exited." ));
  2729. }
  2730. void
  2731. CH323Call::CTIdentifyExpired()
  2732. {
  2733. if( m_hCTIdentifyTimer != NULL )
  2734. {
  2735. DeleteTimerQueueTimer( H323TimerQueue, m_hCTIdentifyTimer, NULL );
  2736. m_hCTIdentifyTimer = NULL;
  2737. }
  2738. if( m_dwCallDiversionState != H4502_CIIDENTIFY_RRSUCC )
  2739. {
  2740. CloseCall( 0 );
  2741. }
  2742. }
  2743. void
  2744. CH323Call::CTIdentifyRRExpired()
  2745. {
  2746. if( m_hCTIdentifyRRTimer != NULL )
  2747. {
  2748. DeleteTimerQueueTimer( H323TimerQueue, m_hCTIdentifyRRTimer, NULL );
  2749. m_hCTIdentifyRRTimer = NULL;
  2750. }
  2751. if( m_dwCallDiversionState != H4502_CTSETUP_RECV )
  2752. {
  2753. CloseCall( 0 );
  2754. }
  2755. }
  2756. void
  2757. NTAPI CH323Call::CallDivertOnNACallback(
  2758. IN PVOID Parameter1,
  2759. IN BOOLEAN bTimer
  2760. )
  2761. {
  2762. PH323_CALL pCall = NULL;
  2763. H323DBG(( DEBUG_LEVEL_TRACE, "CallDivertOnNACallback entered." ));
  2764. //if the timer expired
  2765. _ASSERTE( bTimer );
  2766. pCall=g_pH323Line -> FindH323CallAndLock( (HDRVCALL)Parameter1 );
  2767. if( pCall != NULL )
  2768. {
  2769. pCall -> CallDivertOnNoAnswer();
  2770. pCall -> Unlock();
  2771. }
  2772. H323DBG(( DEBUG_LEVEL_TRACE, "CallDivertOnNACallback exited." ));
  2773. }
  2774. //!!always called in a lock
  2775. void
  2776. CH323Call::CallDivertOnNoAnswer()
  2777. {
  2778. //stop the timer that caused this event
  2779. if( m_hCallDivertOnNATimer != NULL )
  2780. {
  2781. DeleteTimerQueueTimer(H323TimerQueue, m_hCallDivertOnNATimer, NULL);
  2782. m_hCallDivertOnNATimer = NULL;
  2783. }
  2784. //Make sure that the call is still alerting, it has not ben accepted and
  2785. //it has not been transfered in the mean time
  2786. if( (m_dwCallState != LINECALLSTATE_OFFERING) ||
  2787. (m_fCallAccepted == TRUE) ||
  2788. (m_dwCallType & CALLTYPE_TRANSFERED2_CONSULT)
  2789. )
  2790. {
  2791. return;
  2792. }
  2793. //divert the call. divertedToAlias is already set, so pass NULL
  2794. if( !InitiateCallDiversion( NULL, DiversionReason_cfnr) )
  2795. {
  2796. //shutdown the Q931 call
  2797. CloseCall( 0 );
  2798. }
  2799. }
  2800. BOOL
  2801. CH323Call::SendCTInitiateMessagee(
  2802. IN CTIdentifyRes * pCTIdentifyRes
  2803. )
  2804. {
  2805. H323DBG(( DEBUG_LEVEL_TRACE, "SendCTInitiateMessagee entered:%p.", this ));
  2806. //get the cookie for transferred call
  2807. CopyMemory( (PVOID)m_pCTCallIdentity, (PVOID)pCTIdentifyRes->callIdentity,
  2808. sizeof(pCTIdentifyRes->callIdentity) );
  2809. if( m_pTransferedToAlias != NULL )
  2810. {
  2811. FreeAliasNames( m_pTransferedToAlias );
  2812. m_pTransferedToAlias = NULL;
  2813. }
  2814. //argument.reroutingNr
  2815. if( !AliasAddrToAliasNames( &m_pTransferedToAlias,
  2816. (PSetup_UUIE_sourceAddress)
  2817. (pCTIdentifyRes->reroutingNumber.destinationAddress) ) )
  2818. {
  2819. H323DBG(( DEBUG_LEVEL_ERROR,
  2820. "couldn't allocate for T-2 alias:%p.", this ));
  2821. return FALSE;
  2822. }
  2823. ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pCTIdentifyRes,
  2824. CTIdentifyRes_PDU );
  2825. if( !SendQ931Message( NO_INVOKEID, 0, 0, FACILITYMESSAGETYPE,
  2826. CTINITIATE_OPCODE | H450_INVOKE ) )
  2827. {
  2828. return FALSE;
  2829. }
  2830. m_dwCallDiversionState = H4502_CTINITIATE_SENT;
  2831. //start the timer for CTIdenity message
  2832. if( !CreateTimerQueueTimer(
  2833. &m_hCTInitiateTimer,
  2834. H323TimerQueue,
  2835. CH323Call::CTInitiateExpiredCallback,
  2836. (PVOID)m_hdCall,
  2837. CTINITIATE_SENT_TIMEOUT, 0,
  2838. WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE) )
  2839. {
  2840. CloseCall( 0 );
  2841. }
  2842. H323DBG(( DEBUG_LEVEL_TRACE, "SendCTInitiateMessagee exited:%p.", this ));
  2843. return TRUE;
  2844. }
  2845. BOOL
  2846. CH323Call::InitiateCallDiversion(
  2847. IN PH323_ALIASITEM pwszDivertedToAlias,
  2848. IN DiversionReason eDiversionMode
  2849. )
  2850. {
  2851. H323DBG(( DEBUG_LEVEL_TRACE, "InitiateCallDiversion entered:%p.", this ));
  2852. m_dwCallType |= CALLTYPE_DIVERTED_SERVED;
  2853. if( m_pCallReroutingInfo == NULL )
  2854. {
  2855. m_pCallReroutingInfo = new CALLREROUTINGINFO;
  2856. if( m_pCallReroutingInfo == NULL )
  2857. {
  2858. return FALSE;
  2859. }
  2860. ZeroMemory( (PVOID)m_pCallReroutingInfo, sizeof(CALLREROUTINGINFO) );
  2861. }
  2862. m_pCallReroutingInfo ->diversionReason = eDiversionMode;
  2863. m_pCallReroutingInfo->divertingNrAlias = new H323_ALIASNAMES;
  2864. if( m_pCallReroutingInfo->divertingNrAlias == NULL )
  2865. {
  2866. goto cleanup;
  2867. }
  2868. ZeroMemory( (PVOID)m_pCallReroutingInfo->divertingNrAlias,
  2869. sizeof(H323_ALIASNAMES) );
  2870. if( !AddAliasItem( m_pCallReroutingInfo->divertingNrAlias,
  2871. (BYTE*)m_pCalleeAliasNames->pItems[0].pData,
  2872. sizeof(WCHAR) * (m_pCalleeAliasNames->pItems[0].wDataLength+1),
  2873. m_pCalleeAliasNames->pItems[0].wType ) )
  2874. {
  2875. goto cleanup;
  2876. }
  2877. if( m_pCallReroutingInfo->originalCalledNr == NULL )
  2878. {
  2879. m_pCallReroutingInfo->originalCalledNr = new H323_ALIASNAMES;
  2880. if( m_pCallReroutingInfo->originalCalledNr == NULL )
  2881. {
  2882. goto cleanup;
  2883. }
  2884. ZeroMemory( (PVOID)m_pCallReroutingInfo->originalCalledNr,
  2885. sizeof(H323_ALIASNAMES) );
  2886. if( !AddAliasItem(
  2887. m_pCallReroutingInfo->originalCalledNr,
  2888. (BYTE*)m_pCalleeAliasNames->pItems[0].pData,
  2889. sizeof(WCHAR) * (m_pCalleeAliasNames->pItems[0].wDataLength+1),
  2890. m_pCalleeAliasNames->pItems[0].wType )
  2891. )
  2892. {
  2893. goto cleanup;
  2894. }
  2895. }
  2896. if( m_pCallReroutingInfo->divertedToNrAlias == NULL )
  2897. {
  2898. _ASSERTE( pwszDivertedToAlias );
  2899. m_pCallReroutingInfo->divertedToNrAlias = new H323_ALIASNAMES;
  2900. if( m_pCallReroutingInfo->divertedToNrAlias == NULL )
  2901. {
  2902. goto cleanup;
  2903. }
  2904. ZeroMemory( (PVOID)m_pCallReroutingInfo->divertedToNrAlias,
  2905. sizeof(H323_ALIASNAMES) );
  2906. if( !AddAliasItem( m_pCallReroutingInfo->divertedToNrAlias,
  2907. (BYTE*)pwszDivertedToAlias->pData,
  2908. sizeof(WCHAR) * (wcslen(pwszDivertedToAlias->pData) +1),
  2909. pwszDivertedToAlias->wType
  2910. ) )
  2911. {
  2912. goto cleanup;
  2913. }
  2914. }
  2915. if( !SendQ931Message( NO_INVOKEID, 0, 0, FACILITYMESSAGETYPE,
  2916. CALLREROUTING_OPCODE | H450_INVOKE ) )
  2917. {
  2918. goto cleanup;
  2919. }
  2920. m_dwCallDiversionState = H4503_CALLREROUTING_SENT;
  2921. if( !CreateTimerQueueTimer(
  2922. &m_hCallReroutingTimer,
  2923. H323TimerQueue,
  2924. CH323Call::CallReroutingTimerCallback,
  2925. (PVOID)m_hdCall,
  2926. CALLREROUTING_EXPIRE_TIME, 0,
  2927. WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE) )
  2928. {
  2929. goto cleanup;
  2930. }
  2931. H323DBG(( DEBUG_LEVEL_TRACE, "InitiateCallDiversion exited:%p.", this ));
  2932. return TRUE;
  2933. cleanup:
  2934. FreeCallReroutingInfo();
  2935. return FALSE;
  2936. }