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.

975 lines
24 KiB

  1. /*
  2. * File: connobj.cpp
  3. *
  4. * implementation of Microsoft Network Audio connection object.
  5. *
  6. *
  7. *
  8. * Revision History:
  9. *
  10. * 05/05/96 mikev created
  11. * 08/04/96 philf added support for video
  12. * 09/22/96 mikev dual call control protocols (H.323 & MSICCP)
  13. * 10/14/96 mikev multiple channel support, property I/F
  14. */
  15. #include "precomp.h"
  16. #include "ctrlh323.h"
  17. #include "strutil.h"
  18. CREQ_RESPONSETYPE CConnection::FilterConnectionRequest(
  19. LPIControlChannel lpControlChannel,
  20. P_APP_CALL_SETUP_DATA pAppData)
  21. {
  22. FX_ENTRY ("CConnection::FilterConnectionRequest");
  23. CREQ_RESPONSETYPE cr;
  24. // validate lpControlChannel - this implementation sets it inside
  25. // GetAcceptingObject()
  26. if(m_pControlChannel != lpControlChannel)
  27. {
  28. ERRORMESSAGE(("%s:bad param:my pChan:0x%08lX, param pChan:0x%08lX\r\n",
  29. _fx_, m_pControlChannel, lpControlChannel));
  30. hrLast = CADV_E_INVALID_PARAM;
  31. return CRR_ERROR;
  32. }
  33. m_ConnectionState = CLS_Alerting;
  34. cr = m_pH323CallControl->FilterConnectionRequest(this, pAppData);
  35. switch (cr)
  36. {
  37. case CRR_ASYNC:
  38. // m_ConnectionState = CLS_Alerting; // stays in this state
  39. break;
  40. case CRR_ACCEPT:
  41. m_ConnectionState = CLS_Connecting;
  42. break;
  43. // set summary codes in reject cases
  44. case CRR_BUSY:
  45. m_ConnectionState = CLS_Idle;
  46. SummaryCode(CCR_LOCAL_BUSY);
  47. break;
  48. case CRR_SECURITY_DENIED:
  49. m_ConnectionState = CLS_Idle;
  50. SummaryCode(CCR_LOCAL_SECURITY_DENIED);
  51. break;
  52. default:
  53. case CRR_REJECT:
  54. m_ConnectionState = CLS_Idle;
  55. SummaryCode(CCR_LOCAL_REJECT);
  56. break;
  57. }
  58. return(cr);
  59. }
  60. HRESULT CConnection::FindAcceptingObject(LPIControlChannel *lplpAcceptingObject,
  61. LPVOID lpvConfID)
  62. {
  63. FX_ENTRY ("CConnection::FindAcceptingObject");
  64. HRESULT hr = H323CC_E_CONNECTION_NOT_FOUND;
  65. ULONG ulCount, uNumConnections;
  66. CConnection **ppConnections = NULL;;
  67. LPIControlChannel pCtlChan;
  68. CConnection *pConnection;
  69. if(!lplpAcceptingObject)
  70. {
  71. ERRORMESSAGE(("%s:null lplpAcceptingObject\r\n",_fx_));
  72. return CADV_E_INVALID_PARAM;
  73. }
  74. // zero out the output param
  75. *lplpAcceptingObject = NULL;
  76. hr = m_pH323CallControl->GetNumConnections(&uNumConnections);
  77. if(!HR_SUCCEEDED(hr))
  78. goto EXIT;
  79. if(!uNumConnections)
  80. {
  81. // initialized value hr = H323CC_E_CONNECTION_NOT_FOUND;
  82. goto EXIT;
  83. }
  84. ppConnections = (CConnection **)MemAlloc(uNumConnections * (sizeof(IH323Endpoint * *)));
  85. if(!ppConnections)
  86. {
  87. hr = H323CC_E_INSUFFICIENT_MEMORY;
  88. goto EXIT;
  89. }
  90. // get list of connections and query each one for matching conference ID
  91. hr = m_pH323CallControl->GetConnobjArray(ppConnections, uNumConnections * (sizeof(IH323Endpoint * *)));
  92. if(!HR_SUCCEEDED(hr))
  93. goto EXIT;
  94. for(ulCount=0;ulCount <uNumConnections;ulCount++)
  95. {
  96. pConnection = ppConnections[ulCount];
  97. if(pConnection && (pCtlChan = pConnection->GetControlChannel())
  98. && pCtlChan->IsAcceptingConference(lpvConfID))
  99. {
  100. *lplpAcceptingObject = pCtlChan;
  101. hr = hrSuccess;
  102. break;
  103. }
  104. }
  105. EXIT:
  106. if(ppConnections)
  107. MemFree(ppConnections);
  108. return hr;
  109. }
  110. HRESULT CConnection::GetAcceptingObject(LPIControlChannel *lplpAcceptingObject,
  111. LPGUID pPID)
  112. {
  113. FX_ENTRY ("CConnection::GetAcceptingObject");
  114. HRESULT hr;
  115. CConnection *pNewConnection;
  116. if(!lplpAcceptingObject)
  117. {
  118. ERRORMESSAGE(("%s:null lplpAcceptingObject\r\n",_fx_));
  119. return CADV_E_INVALID_PARAM;
  120. }
  121. // zero out the output param
  122. *lplpAcceptingObject = NULL;
  123. // create a connection object to accept the connection
  124. hr = m_pH323CallControl->CreateConnection(&pNewConnection, *pPID);
  125. if(HR_SUCCEEDED(hr))
  126. {
  127. *lplpAcceptingObject = pNewConnection->GetControlChannel();
  128. }
  129. else
  130. {
  131. ERRORMESSAGE(("%s:CreateConnection failed, hr=0x%08lx\r\n",_fx_, hr));
  132. }
  133. return hr;
  134. }
  135. // This is called by a comm channel. It is only called by a channel that is being
  136. // opened, and only if that channel is not already associated with a control channel.
  137. HRESULT CConnection::AddCommChannel (ICtrlCommChan *pChan)
  138. {
  139. GUID mid;
  140. if(!m_fCapsReady)
  141. {
  142. ASSERT(0);
  143. hrLast = CONN_E_NOT_INITIALIZED; // need better error to indicate why
  144. // (connection is not yet in a state to take new channels)
  145. goto EXIT;
  146. }
  147. // re-initialize channel
  148. hrLast = pChan->GetMediaType(&mid);
  149. ASSERT(m_pH323ConfAdvise != NULL);
  150. if(!pChan->Init(&mid, m_pH323ConfAdvise, TRUE))
  151. {
  152. hrLast = CONN_E_SYSTEM_ERROR;
  153. goto EXIT;
  154. }
  155. // non error case continues here
  156. if(m_pControlChannel)
  157. {
  158. m_ChannelList.AddTail(pChan);
  159. pChan->AddRef();
  160. hrLast = m_pControlChannel->AddChannel(pChan, m_pCapObject);
  161. if(!HR_SUCCEEDED(hrLast))
  162. goto EXIT;
  163. }
  164. EXIT:
  165. return hrLast;
  166. }
  167. HRESULT CConnection::CreateCommChannel(LPGUID pMediaGuid, ICommChannel **ppICommChannel,
  168. BOOL fSend)
  169. {
  170. FX_ENTRY ("CConnection::CreateCommChannel");
  171. ICommChannel *pICommChannel = NULL;
  172. ICtrlCommChan *pICtrlCommChannel = NULL;
  173. if(!pMediaGuid || !ppICommChannel)
  174. {
  175. hrLast = CONN_E_INVALID_PARAM;
  176. goto EXIT;
  177. }
  178. DBG_SAVE_FILE_LINE
  179. if(*pMediaGuid == MEDIA_TYPE_H323_T120)
  180. {
  181. if(!(pICommChannel = (ICommChannel *)new ImpT120Chan))
  182. {
  183. hrLast = CONN_E_OUT_OF_MEMORY;
  184. goto EXIT;
  185. }
  186. }
  187. else if(!(pICommChannel = (ICommChannel *)new ImpICommChan))
  188. {
  189. hrLast = CONN_E_OUT_OF_MEMORY;
  190. goto EXIT;
  191. }
  192. hrLast = pICommChannel->QueryInterface(IID_ICtrlCommChannel, (void **)&pICtrlCommChannel);
  193. if(!HR_SUCCEEDED(hrLast))
  194. {
  195. goto EXIT;
  196. }
  197. ASSERT(m_pH323ConfAdvise != NULL);
  198. if(!pICtrlCommChannel->Init(pMediaGuid, m_pH323ConfAdvise, fSend))
  199. {
  200. hrLast = CONN_E_SYSTEM_ERROR;
  201. goto EXIT;
  202. }
  203. // it's created via this connection, now associate it and this connection
  204. if(m_pControlChannel)
  205. {
  206. m_ChannelList.AddTail(pICtrlCommChannel);
  207. hrLast = m_pControlChannel->AddChannel(pICtrlCommChannel, m_pCapObject);
  208. if(!HR_SUCCEEDED(hrLast))
  209. goto EXIT;
  210. }
  211. // in success case, the calling function gets the ICommChannel reference, and this
  212. // object gets the ICtrlCommChan reference
  213. *ppICommChannel = pICommChannel;
  214. pICommChannel = NULL;
  215. pICtrlCommChannel = NULL;
  216. EXIT:
  217. if(pICommChannel)
  218. pICommChannel->Release();
  219. if(pICtrlCommChannel)
  220. pICtrlCommChannel->Release();
  221. return hrLast;
  222. }
  223. HRESULT CConnection:: ResolveFormats (LPGUID pMediaGuidArray, UINT uNumMedia,
  224. PRES_PAIR pResOutput)
  225. {
  226. ASSERT(NULL !=m_pCapObject);
  227. return (m_pCapObject->ResolveFormats(pMediaGuidArray, uNumMedia, pResOutput));
  228. }
  229. HRESULT CConnection::GetVersionInfo(PCC_VENDORINFO *ppLocalVendorInfo,
  230. PCC_VENDORINFO *ppRemoteVendorInfo)
  231. {
  232. if(!m_pControlChannel)
  233. return CONN_E_NOT_INITIALIZED;
  234. return (m_pControlChannel->GetVersionInfo(ppLocalVendorInfo, ppRemoteVendorInfo));
  235. }
  236. VOID CConnection ::ReleaseAllChannels()
  237. {
  238. ICtrlCommChan *pChan = NULL;
  239. while (!m_ChannelList.IsEmpty())
  240. {
  241. pChan = (ICtrlCommChan *) m_ChannelList.RemoveHead();
  242. if(pChan)
  243. {
  244. pChan->Release();
  245. pChan = NULL;
  246. }
  247. }
  248. }
  249. //
  250. // Implementation of IConfAdvise::OnControlEvent
  251. //
  252. // CAUTION: because Release() can be called by the registered event handler,
  253. // any code path that accesses class instance data after a call to m_pH323ConfAdvise->CallEvent
  254. // must AddRef() before the call, and Release() after all class instance data access
  255. // is done. The DoControlNotification() helper method does this, but beware of
  256. // cases where data is touched after a call to DoControlNotification();
  257. //
  258. HRESULT CConnection::OnControlEvent(DWORD dwEvent, LPVOID lpvData, LPIControlChannel lpControlObject)
  259. {
  260. FX_ENTRY ("CConnection::OnControlEvent");
  261. DWORD dwStatus;
  262. BOOL fPost = FALSE;
  263. HRESULT hr=hrSuccess;
  264. AddRef();
  265. switch(dwEvent)
  266. {
  267. case CCEV_RINGING:
  268. fPost = TRUE;
  269. dwStatus = CONNECTION_PROCEEDING;
  270. break;
  271. case CCEV_CONNECTED:
  272. fPost = TRUE;
  273. dwStatus = CONNECTION_CONNECTED;
  274. NewUserInfo((LPCTRL_USER_INFO)lpvData);
  275. break;
  276. case CCEV_CALLER_ID:
  277. NewUserInfo((LPCTRL_USER_INFO)lpvData);
  278. break;
  279. case CCEV_CAPABILITIES_READY:
  280. m_fCapsReady = TRUE;
  281. break;
  282. case CCEV_CHANNEL_REQUEST:
  283. // another channel (besides the channels supplied by EnumChannels()) is being
  284. // requested - we can't handle arbitrary channels yet.
  285. ERRORMESSAGE(("%s, not handling CCEV_CHANNEL_REQUEST \r\n",_fx_));
  286. hr = CADV_E_NOT_SUPPORTED;
  287. goto out;
  288. break;
  289. case CCEV_DISCONNECTING:
  290. //in the future architecture, this event will be the opportunity to
  291. //cleanup channels
  292. if(lpvData)
  293. {
  294. // keep summary code
  295. SummaryCode((HRESULT) *((HRESULT *)lpvData));
  296. }
  297. Disconnect(CCR_UNKNOWN);
  298. // IConnect doesn't yet define a "disconnecting" event, so don't propagate it
  299. break;
  300. case CCEV_REMOTE_DISCONNECTING:
  301. if(lpvData)
  302. {
  303. SummaryCode((HRESULT) *((HRESULT *)lpvData));
  304. }
  305. // do notification before calling back into Disconnect, so the event
  306. // notifications are posted in the correct order. This is one of
  307. // the cases where Ref count protection is required.
  308. AddRef();
  309. DoControlNotification(CONNECTION_RECEIVED_DISCONNECT);
  310. // opportunity to cleanup channels
  311. Disconnect(CCR_UNKNOWN);
  312. Release();
  313. break;
  314. case CCEV_DISCONNECTED:
  315. fPost = TRUE;
  316. m_ConnectionState = CLS_Idle;
  317. dwStatus = CONNECTION_DISCONNECTED;
  318. if(lpvData)
  319. {
  320. SummaryCode((HRESULT) *((HRESULT *)lpvData));
  321. }
  322. break;
  323. case CCEV_ALL_CHANNELS_READY:
  324. // all *mandatory* channels are open, but not necessarily
  325. // all channels
  326. m_ConnectionState = CLS_Inuse;
  327. dwStatus = CONNECTION_READY;
  328. fPost = TRUE;
  329. break;
  330. case CCEV_ACCEPT_INCOMPLETE:
  331. if(lpvData)
  332. {
  333. // known problem is that control channel has already
  334. // disconnected and may have notified of the disconnect first.
  335. // This could be fixed, but it's not an issue because an incomplete
  336. // accept is not made known to the UI, therefore the summary code
  337. // is dust anyway.
  338. SummaryCode((HRESULT) *((HRESULT *)lpvData));
  339. }
  340. if(lpControlObject && (m_pControlChannel == lpControlObject))
  341. {
  342. // remove interest in control channel events, then nuke it
  343. m_pControlChannel->DeInit((IConfAdvise *) this);
  344. m_pControlChannel->Release();
  345. }
  346. m_pControlChannel = NULL;
  347. if(m_pH323CallControl)
  348. {
  349. m_pH323CallControl->RemoveConnection(this);
  350. }
  351. Release(); // release self - this is by design
  352. break;
  353. case CCEV_CALL_INCOMPLETE:
  354. hr = OnCallIncomplete(lpControlObject, (lpvData)? ((DWORD) *((DWORD *)lpvData)) :0);
  355. goto out;
  356. break;
  357. }
  358. if(fPost)
  359. DoControlNotification(dwStatus);
  360. out:
  361. Release();
  362. return hr;
  363. }
  364. HRESULT CConnection::OnCallIncomplete (LPIControlChannel lpControlObject, HRESULT hIncompleteCode)
  365. {
  366. FX_ENTRY ("CConnection::OnCallIncomplete ");
  367. // check the reason for incomplete call attempt (busy? rejected? nobody home?
  368. HRESULT hSummary;
  369. CloseAllChannels();
  370. // map the protocol-specific (h.323, msiccp, sip, etc) code to the
  371. // connection interface code
  372. // test for gatekeeper admission reject
  373. // FACILITY_GKIADMISSION
  374. if(CUSTOM_FACILITY(hIncompleteCode) == FACILITY_GKIADMISSION)
  375. {
  376. // pass GK codes through intact
  377. hSummary = hIncompleteCode;
  378. }
  379. else
  380. {
  381. switch (hIncompleteCode)
  382. {
  383. case CCCI_GK_NO_RESOURCES:
  384. hSummary = CCR_GK_NO_RESOURCES;
  385. break;
  386. case CCCI_BUSY:
  387. hSummary = CCR_REMOTE_BUSY;
  388. break;
  389. case CCCI_SECURITY_DENIED:
  390. hSummary = CCR_REMOTE_SECURITY_DENIED;
  391. break;
  392. case CCCI_NO_ANSWER_TIMEOUT:
  393. hSummary = CCR_NO_ANSWER_TIMEOUT;
  394. break;
  395. case CCCI_REJECTED:
  396. hSummary = CCR_REMOTE_REJECTED;
  397. break;
  398. case CCCI_REMOTE_ERROR:
  399. hSummary = CCR_REMOTE_SYSTEM_ERROR;
  400. break;
  401. case CCCI_LOCAL_ERROR:
  402. hSummary = CCR_LOCAL_SYSTEM_ERROR;
  403. break;
  404. case CCCI_INCOMPATIBLE:
  405. hSummary = CCR_LOCAL_PROTOCOL_ERROR;
  406. break;
  407. case CCCI_UNKNOWN:
  408. hSummary = CCR_UNKNOWN;
  409. default:
  410. hSummary = CCR_UNKNOWN;
  411. break;
  412. }
  413. }
  414. DEBUGMSG(ZONE_CONN,("%s: incomplete code = 0x%08lX\r\n",
  415. _fx_, hIncompleteCode));
  416. SummaryCode(hSummary);
  417. return hrLast;
  418. }
  419. VOID CConnection::NewUserInfo(LPCTRL_USER_INFO lpNewUserInfo)
  420. {
  421. FX_ENTRY ("CConnection::NewUserInfo");
  422. if(!lpNewUserInfo || !lpNewUserInfo->dwCallerIDSize || !lpNewUserInfo->lpvCallerIDData)
  423. return;
  424. if(m_pUserInfo)
  425. {
  426. DEBUGMSG(ZONE_CONN,("%s:uninitialized m_pUserInfo (0x%08lX) or multiple notification \r\n",
  427. _fx_, m_pUserInfo ));
  428. //
  429. if(!IsBadWritePtr((LPVOID)m_pUserInfo, m_pUserInfo->dwCallerIDSize + sizeof(CTRL_USER_INFO)))
  430. {
  431. // chances are it *is* a multiple notification and not an uninitialized
  432. // variable. Ther may be some control channel protocols that *update* user
  433. // information after connection or accepting, but that is pure speculation.
  434. // the typical case is that caller ID is available before accepting, and
  435. // it is resupplied in the subsequent "connected" notification. We're not
  436. // wasting time realloc'ing and recopying it.
  437. return;
  438. }
  439. // else fallout and overwrite it
  440. }
  441. // copy the structure and caller ID data
  442. m_pUserInfo = (LPCTRL_USER_INFO)MemAlloc(lpNewUserInfo->dwCallerIDSize + sizeof(CTRL_USER_INFO));
  443. if(m_pUserInfo)
  444. {
  445. m_pUserInfo->lpvRemoteProtocolInfo = NULL; // nothing touchess this later, but being safe anyway
  446. m_pUserInfo->lpvLocalProtocolInfo = NULL;
  447. m_pUserInfo->dwCallerIDSize = lpNewUserInfo->dwCallerIDSize;
  448. // point past the structure
  449. m_pUserInfo->lpvCallerIDData = ((BYTE *)m_pUserInfo) + sizeof(CTRL_USER_INFO);
  450. memcpy(m_pUserInfo->lpvCallerIDData,
  451. lpNewUserInfo->lpvCallerIDData,
  452. m_pUserInfo->dwCallerIDSize);
  453. }
  454. else
  455. {
  456. ERRORMESSAGE(("%s:allocation of m_pUserInfo failed\r\n",_fx_));
  457. }
  458. }
  459. //
  460. // Utility function for passing control channel events to the registered handler
  461. // This is callable only by the control channel code running in the same thread
  462. // as that which created the connection.
  463. VOID CConnection::DoControlNotification(DWORD dwStatus)
  464. {
  465. FX_ENTRY ("CConnection::DoControlNotification");
  466. // issue notification to registered entity
  467. if(m_pH323ConfAdvise)
  468. {
  469. AddRef(); // protect ourselves from calls back into methods that
  470. // wind up in Release().
  471. DEBUGMSG(ZONE_CONN,("%s:issuing notification 0x%08lX\r\n",_fx_, dwStatus));
  472. m_pH323ConfAdvise->CallEvent((IH323Endpoint *)&m_ImpConnection, dwStatus);
  473. Release();
  474. }
  475. }
  476. CConnection::CConnection()
  477. :m_pH323CallControl(NULL),
  478. hrLast(hrSuccess),
  479. next(NULL),
  480. m_fCapsReady(FALSE),
  481. m_ConnectionState(CLS_Idle),
  482. m_pH323ConfAdvise(NULL),
  483. m_pUserInfo(NULL),
  484. m_pControlChannel(NULL),
  485. m_pCapObject(NULL),
  486. m_hSummaryCode(hrSuccess),
  487. uRef(1)
  488. {
  489. m_ImpConnection.Init(this);
  490. }
  491. CConnection::~CConnection()
  492. {
  493. ReleaseAllChannels();
  494. if(m_pH323CallControl)
  495. m_pH323CallControl->RemoveConnection(this);
  496. if(m_pCapObject)
  497. m_pCapObject->Release();
  498. // we really don't allocate much
  499. if(m_pUserInfo)
  500. MemFree(m_pUserInfo);
  501. }
  502. HRESULT CConnection::Init(CH323CallControl *pH323CallControl, GUID PIDofProtocolType)
  503. {
  504. FX_ENTRY(("CConnection::Init"));
  505. hrLast = hrSuccess;
  506. BOOL bAdvertise;
  507. m_pH323CallControl = pH323CallControl;
  508. GUID mid;
  509. if(!pH323CallControl)
  510. return CCO_E_INVALID_PARAM;
  511. if(m_pControlChannel)
  512. {
  513. ASSERT(0);
  514. // don't cleanup in this case
  515. return CONN_E_ALREADY_INITIALIZED;
  516. }
  517. if(PIDofProtocolType != PID_H323)
  518. {
  519. hrLast = CONN_E_INIT_FAILED;
  520. goto ERROR_CLEANUP;
  521. }
  522. DBG_SAVE_FILE_LINE
  523. if(!(m_pControlChannel = (LPIControlChannel) new CH323Ctrl))
  524. {
  525. hrLast = CONN_E_INIT_FAILED;
  526. goto ERROR_CLEANUP;
  527. }
  528. DBG_SAVE_FILE_LINE
  529. if(!m_pCapObject && !(m_pCapObject = new CapsCtl()))
  530. {
  531. ERRORMESSAGE(("%s:cannot create capability resolver\r\n",_fx_));
  532. hrLast = CONN_E_INIT_FAILED;
  533. goto ERROR_CLEANUP;;
  534. }
  535. if(!m_pCapObject->Init())
  536. {
  537. ERRORMESSAGE(("%s:cannot init capability resolver\r\n",_fx_));
  538. hrLast = CONN_E_INIT_FAILED;
  539. goto ERROR_CLEANUP;
  540. }
  541. bAdvertise = ((g_capFlags & CAPFLAGS_AV_STREAMS) != 0);
  542. mid = MEDIA_TYPE_H323AUDIO;
  543. hrLast = m_pCapObject->EnableMediaType(bAdvertise, &mid);
  544. if(!HR_SUCCEEDED(hrLast))
  545. goto ERROR_CLEANUP;
  546. bAdvertise = ((g_capFlags & CAPFLAGS_AV_STREAMS) != 0);
  547. mid = MEDIA_TYPE_H323VIDEO;
  548. hrLast = m_pCapObject->EnableMediaType(bAdvertise, &mid);
  549. if(!HR_SUCCEEDED(hrLast))
  550. goto ERROR_CLEANUP;
  551. hrLast = m_pControlChannel->Init((IConfAdvise *) this);
  552. if(!HR_SUCCEEDED(hrLast))
  553. goto ERROR_CLEANUP;
  554. return hrLast;
  555. ERROR_CLEANUP:
  556. ERRORMESSAGE(("%s:ERROR_CLEANUP\r\n",_fx_));
  557. if(m_pControlChannel)
  558. m_pControlChannel->Release();
  559. if(m_pCapObject)
  560. m_pCapObject->Release();
  561. m_pControlChannel = NULL;
  562. m_pCapObject = NULL;
  563. return hrLast;
  564. }
  565. BOOL CConnection::ListenOn(PORT port)
  566. {
  567. if(!m_pControlChannel)
  568. {
  569. hrLast = H323CC_E_NOT_INITIALIZED;
  570. goto EXIT;
  571. }
  572. hrLast = m_pControlChannel->ListenOn(port);
  573. EXIT:
  574. return((HR_SUCCEEDED(hrLast))?TRUE:FALSE);
  575. }
  576. // start the asynchronous stuff that will instantiate a control channel
  577. HRESULT CConnection::PlaceCall (BOOL bUseGKResolution, PSOCKADDR_IN pCallAddr,
  578. P_H323ALIASLIST pDestinationAliases, P_H323ALIASLIST pExtraAliases,
  579. LPCWSTR pCalledPartyNumber, P_APP_CALL_SETUP_DATA pAppData)
  580. {
  581. if(m_ConnectionState != CLS_Idle)
  582. return CONN_E_NOT_IDLE;
  583. m_fCapsReady = FALSE;
  584. // reset summary code
  585. m_hSummaryCode = CCR_INVALID_REASON;
  586. hrLast = m_pH323CallControl->GetGKCallPermission();
  587. if(!HR_SUCCEEDED(hrLast))
  588. {
  589. m_hSummaryCode = hrLast;
  590. return hrLast;
  591. }
  592. hrLast = m_pControlChannel->PlaceCall (bUseGKResolution, pCallAddr,
  593. pDestinationAliases, pExtraAliases,
  594. pCalledPartyNumber, pAppData);
  595. if(HR_SUCCEEDED(hrLast))
  596. m_ConnectionState = CLS_Connecting;
  597. return hrLast;
  598. }
  599. HRESULT CConnection::AcceptRejectConnection(CREQ_RESPONSETYPE Response)
  600. {
  601. if(Response == CRR_ACCEPT)
  602. {
  603. m_ConnectionState = CLS_Connecting;
  604. m_fCapsReady = FALSE;
  605. // reset summary code
  606. m_hSummaryCode = CCR_INVALID_REASON;
  607. }
  608. return m_pControlChannel->AsyncAcceptRejectCall(Response);
  609. }
  610. HRESULT CConnection::SetAdviseInterface(IH323ConfAdvise *pH323ConfAdvise)
  611. {
  612. ASSERT(pH323ConfAdvise != NULL);
  613. if(!pH323ConfAdvise)
  614. {
  615. return CONN_E_INVALID_PARAM;
  616. }
  617. m_pH323ConfAdvise = pH323ConfAdvise;
  618. //EXIT:
  619. return hrSuccess;
  620. }
  621. HRESULT CConnection::ClearAdviseInterface()
  622. {
  623. m_pH323ConfAdvise = NULL;
  624. return hrSuccess;
  625. }
  626. // LOOKLOOK - the H323 control channel needs to get the combined cap object
  627. // implementation of IConfAdvise::GetCapResolver()
  628. HRESULT CConnection::GetCapResolver(LPVOID *lplpCapObject, GUID CapType)
  629. {
  630. if(!lplpCapObject)
  631. return CONN_E_INVALID_PARAM;
  632. if(!m_pH323CallControl || !m_pCapObject)
  633. return CONN_E_NOT_INITIALIZED;
  634. if(CapType == OID_CAP_ACM_TO_H323)
  635. {
  636. *lplpCapObject = m_pCapObject;
  637. }
  638. else
  639. {
  640. return CONN_E_INVALID_PARAM;
  641. }
  642. return hrSuccess;
  643. }
  644. HRESULT CConnection::GetState(ConnectStateType *pState)
  645. {
  646. HRESULT hResult = hrSuccess;
  647. if(!pState)
  648. {
  649. hResult = CONN_E_INVALID_PARAM;
  650. goto EXIT;
  651. }
  652. *pState = m_ConnectionState;
  653. EXIT:
  654. return hResult;
  655. }
  656. // IConfAdvise::GetUserDisplayName()
  657. LPWSTR CConnection::GetUserDisplayName()
  658. {
  659. if(!m_pH323CallControl)
  660. return NULL;
  661. return m_pH323CallControl->GetUserDisplayName();
  662. }
  663. PCC_ALIASITEM CConnection::GetUserDisplayAlias()
  664. {
  665. if(!m_pH323CallControl)
  666. return NULL;
  667. return m_pH323CallControl->GetUserDisplayAlias();
  668. }
  669. PCC_ALIASNAMES CConnection:: GetUserAliases()
  670. {
  671. if(!m_pH323CallControl)
  672. return NULL;
  673. return m_pH323CallControl->GetUserAliases();
  674. }
  675. HRESULT CConnection::GetLocalPort(PORT *lpPort)
  676. {
  677. if(!m_pControlChannel)
  678. return CONN_E_NOT_INITIALIZED;
  679. return m_pControlChannel->GetLocalPort(lpPort);
  680. }
  681. HRESULT CConnection::GetRemoteUserName(LPWSTR lpwszName, UINT uSize)
  682. {
  683. if(!lpwszName)
  684. {
  685. hrLast = MakeResult(CONN_E_INVALID_PARAM);
  686. goto EXIT;
  687. }
  688. if(!m_pUserInfo)
  689. {
  690. // LOOKLOOK - need CONN_E_UNAVAILABLE or something
  691. hrLast = MakeResult(CONN_E_INVALID_PARAM);
  692. goto EXIT;
  693. }
  694. LStrCpyNW((LPWSTR)lpwszName,(LPWSTR)m_pUserInfo->lpvCallerIDData, uSize);
  695. hrLast = hrSuccess;
  696. EXIT:
  697. return hrLast;
  698. }
  699. HRESULT CConnection::GetRemoteUserAddr(PSOCKADDR_IN psinUser)
  700. {
  701. PSOCKADDR_IN psin = NULL;
  702. if(!m_pControlChannel)
  703. return CONN_E_NOT_INITIALIZED;
  704. if(psinUser)
  705. { // get ptr to address, then copy it
  706. hrLast = m_pControlChannel->GetRemoteAddress(&psin);
  707. if(HR_SUCCEEDED(hrLast) && psin)
  708. {
  709. *psinUser = *psin;
  710. }
  711. }
  712. else
  713. {
  714. hrLast = H323CC_E_INVALID_PARAM;
  715. }
  716. //EXIT:
  717. return hrLast;
  718. }
  719. HRESULT CConnection ::Disconnect()
  720. {
  721. SummaryCode(CCR_LOCAL_DISCONNECT);
  722. Disconnect(CCR_LOCAL_DISCONNECT);
  723. return hrSuccess;
  724. }
  725. HRESULT CConnection::CloseAllChannels()
  726. {
  727. ICtrlCommChan *pChan = NULL;
  728. HRESULT hr; // temp return value so error code does not get overwritten
  729. FX_ENTRY ("CConnection::CloseAllChannels");
  730. // This doesn't actually cause channel close PDU's to be sent. It only
  731. // shuts off all streams associated with all channels.
  732. while (!m_ChannelList.IsEmpty())
  733. {
  734. pChan = (ICtrlCommChan *) m_ChannelList.RemoveHead();
  735. if(pChan)
  736. {
  737. hr = pChan->OnChannelClose(CHANNEL_CLOSED);
  738. if(!HR_SUCCEEDED(hr))
  739. hrLast = hr;
  740. hr = pChan->EndControlSession();
  741. if(!HR_SUCCEEDED(hr))
  742. hrLast = hr;
  743. pChan->Release();
  744. }
  745. }
  746. return hrLast;
  747. }
  748. VOID CConnection::Disconnect(DWORD dwResponse)
  749. {
  750. AddRef(); // prevent releasing while handling disconnect events
  751. if(!m_pControlChannel)
  752. {
  753. m_ConnectionState = CLS_Idle;
  754. goto EXIT;
  755. }
  756. if((m_ConnectionState == CLS_Disconnecting)
  757. || (m_ConnectionState == CLS_Idle))
  758. {
  759. goto EXIT;
  760. }
  761. m_ConnectionState = CLS_Disconnecting;
  762. // CloseAllChannels() forces the action that would be taken when all
  763. // channels are closed via call control. Anal channel cleanup is not
  764. // implemented on disconnect- CloseAllChannels() turns off all streaming,
  765. // then we just end the session. It takes too long to go through the
  766. // protocol overhead of closing & acking channel close, and it's legal in
  767. // H.323 to end the session. Ending the session implies channel closure
  768. // for all channels.
  769. //
  770. CloseAllChannels();
  771. // this call can result in callbacks to the UI, which can result in
  772. // calls back in, which results in releasing the object. If we're
  773. // about to go in, we need to be sure we can get back out, so AddRef()
  774. m_pControlChannel->AddRef();
  775. m_pControlChannel->Disconnect(dwResponse);
  776. m_pControlChannel->Release();
  777. EXIT:
  778. Release();
  779. }
  780. STDMETHODIMP CConnection::QueryInterface( REFIID iid, void ** ppvObject)
  781. {
  782. HRESULT hr = E_NOINTERFACE;
  783. if(!ppvObject)
  784. return hr;
  785. *ppvObject = 0;
  786. if((iid == IID_IPhoneConnection)
  787. || (iid == IID_IUnknown)) // satisfy symmetric property of QI
  788. {
  789. *ppvObject = this;
  790. hr = hrSuccess;
  791. AddRef();
  792. }
  793. else if(iid == IID_IConfAdvise)
  794. {
  795. *ppvObject = (IConfAdvise *)this;
  796. hr = hrSuccess;
  797. AddRef();
  798. }
  799. else if((iid == IID_IAppAudioCap ) && m_pCapObject)
  800. {
  801. ASSERT(0);
  802. hr = m_pCapObject->QueryInterface(iid, ppvObject);
  803. }
  804. else if((iid == IID_IAppVidCap ) && m_pCapObject)
  805. {
  806. /// ASSERT(0); CVideoProp still uses this
  807. hr = m_pCapObject->QueryInterface(iid, ppvObject);
  808. }
  809. else if((iid == IID_IDualPubCap) && m_pCapObject)
  810. {
  811. ASSERT(0);
  812. hr = m_pCapObject->QueryInterface(iid, ppvObject);
  813. }
  814. return (hr);
  815. }
  816. ULONG CConnection::AddRef()
  817. {
  818. FX_ENTRY ("CConnection::AddRef");
  819. uRef++;
  820. DEBUGMSG(ZONE_REFCOUNT,("%s:(0x%08lX)->AddRef() uRef = 0x%08lX\r\n",_fx_, this, uRef ));
  821. return uRef;
  822. }
  823. ULONG CConnection::Release()
  824. {
  825. FX_ENTRY ("CConnection::Release");
  826. uRef--;
  827. if(uRef == 0)
  828. {
  829. DEBUGMSG(ZONE_CONN,("%s:(0x%08lX)->Releasing in state:%d\r\n",_fx_, this, m_ConnectionState));
  830. // remove our interest in the control channel
  831. if(m_pControlChannel)
  832. {
  833. hrLast = m_pControlChannel->DeInit((IConfAdvise *) this);
  834. m_pControlChannel->Release();
  835. }
  836. // m_pControlChannel = NULL;
  837. delete this;
  838. return 0;
  839. }
  840. else
  841. {
  842. DEBUGMSG(ZONE_REFCOUNT,("%s:(0x%08lX)->Release() uRef = 0x%08lX\r\n",_fx_, this, uRef ));
  843. return uRef;
  844. }
  845. }
  846. STDMETHODIMP CConnection::GetSummaryCode(VOID)
  847. {
  848. return m_hSummaryCode;
  849. }
  850. VOID CConnection::SummaryCode(HRESULT hCode)
  851. {
  852. // assign code only if it has not yet been assigned
  853. if(m_hSummaryCode != CCR_INVALID_REASON)
  854. return;
  855. m_hSummaryCode = hCode;
  856. }