Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1845 lines
38 KiB

  1. // File: call.cpp
  2. #include "precomp.h"
  3. #include "resource.h"
  4. #include "call.h"
  5. #include "dlgcall.h"
  6. #include "confapi.h"
  7. #include "popupmsg.h"
  8. #include "passdlg.h"
  9. #include "chcondlg.h"
  10. #include "dshowdlg.h"
  11. #include "conf.h"
  12. #include "calllog.h"
  13. #include "rostinfo.h"
  14. #include "..\..\core\cncodes.h" // for CN_* codes
  15. #include <inodecnt.h> // for UI_RC_...
  16. #include "cr.h" // for CreateConfRoomWindow, UpdateUI
  17. #include "confroom.h"
  18. #include "confman.h"
  19. #include "NmLdap.h"
  20. #include "nmremote.h"
  21. #include <tsecctrl.h>
  22. #include "ConfPolicies.h"
  23. #include "StatBar.h"
  24. #include "certui.h"
  25. #include "cmd.h"
  26. #include "callto.h"
  27. #include "dlgacd.h"
  28. // External SDK stuff...
  29. #include "NmCall.h"
  30. #include "NmApp.h"
  31. COBLIST * g_pCallList = NULL; // Global list of calls in progress
  32. extern INmSysInfo2 * g_pNmSysInfo;
  33. static HRESULT OnUIRemotePassword(BSTR bstrConference, BSTR *pbstrPassword, LPCTSTR pCertText, BOOL fIsService);
  34. extern BOOL FRejectIncomingCalls(void);
  35. extern BOOL FIsConfRoomClosing(void);
  36. extern GUID g_csguidSecurity;
  37. extern GUID g_csguidMeetingSettings;
  38. /* C C A L L */
  39. /*-------------------------------------------------------------------------
  40. %%Function: CCall
  41. -------------------------------------------------------------------------*/
  42. CCall::CCall(LPCTSTR pszCallTo, LPCTSTR pszDisplayName, NM_ADDR_TYPE nmAddrType, BOOL bAddToMru, BOOL fIncoming) :
  43. RefCount(NULL),
  44. m_fIncoming (fIncoming),
  45. m_pszDisplayName (PszAlloc(pszDisplayName)),
  46. m_pszCallTo (PszAlloc(pszCallTo)),
  47. m_nmAddrType (nmAddrType),
  48. m_bAddToMru (bAddToMru),
  49. m_fSelectedConference (FALSE),
  50. m_pDlgCall (NULL),
  51. m_pInternalICall(NULL),
  52. m_pos (NULL),
  53. m_dwCookie (0),
  54. m_ppm (NULL),
  55. m_fInRespond (FALSE)
  56. {
  57. DbgMsg(iZONE_OBJECTS, "Obj: %08X created CCall", this);
  58. USES_CONVERSION;
  59. if (FEmptySz(m_pszDisplayName))
  60. {
  61. delete m_pszDisplayName;
  62. // Default to "another person" if no name available in the call data
  63. m_pszDisplayName = PszLoadString(IDS_UNKNOWN_PERSON);
  64. }
  65. m_dwTick = ::GetTickCount();
  66. DbgMsgCall("CCall: %08X Created Name=[%s] CallTo=[%s]",
  67. this, m_pszDisplayName, m_pszCallTo ? m_pszCallTo : _TEXT("<NULL>"));
  68. // add it to the global call list
  69. if (NULL == g_pCallList)
  70. {
  71. g_pCallList = new COBLIST;
  72. if (NULL == g_pCallList)
  73. {
  74. ERROR_OUT(("CCall::CCall - unable to allocate g_pCallList"));
  75. return;
  76. }
  77. }
  78. m_pos = g_pCallList->AddTail(this);
  79. }
  80. CCall::~CCall()
  81. {
  82. DBGENTRY(CCall::~CCall);
  83. RemoveFromList();
  84. delete m_pszDisplayName;
  85. delete m_pszCallTo;
  86. if(m_pInternalICall)
  87. {
  88. m_pInternalICall->Release();
  89. m_pInternalICall = NULL;
  90. }
  91. DbgMsg(iZONE_OBJECTS, "Obj: %08X destroyed CCall", this);
  92. DBGEXIT(CCall::~CCall);
  93. }
  94. /* S E T N M C A L L */
  95. /*-------------------------------------------------------------------------
  96. %%Function: SetNmCall
  97. -------------------------------------------------------------------------*/
  98. VOID CCall::SetNmCall(INmCall * pCall)
  99. {
  100. ASSERT(NULL != pCall);
  101. ASSERT((!m_pInternalICall) || (m_pInternalICall == pCall));
  102. if(!m_pInternalICall)
  103. {
  104. pCall->AddRef();
  105. m_pInternalICall = pCall;
  106. }
  107. if(!m_dwCookie)
  108. {
  109. NmAdvise(m_pInternalICall, this, IID_INmCallNotify2, &m_dwCookie);
  110. }
  111. Update();
  112. }
  113. BOOL CCall::RemoveFromList(void)
  114. {
  115. // Remove the call from the global list
  116. if (NULL == m_pos)
  117. return FALSE;
  118. ASSERT(NULL != g_pCallList);
  119. CCall * pCall = (CCall *) g_pCallList->RemoveAt(m_pos);
  120. ASSERT(this == pCall);
  121. m_pos = NULL;
  122. if(m_pInternalICall)
  123. {
  124. NmUnadvise(m_pInternalICall, IID_INmCallNotify2, m_dwCookie);
  125. m_dwCookie = NULL;
  126. }
  127. return TRUE;
  128. }
  129. VOID CCall::Cancel(BOOL fDisplayCancelMsg)
  130. {
  131. if (!FComplete())
  132. {
  133. if (fDisplayCancelMsg & !FIncoming())
  134. {
  135. DisplayPopup(); // Inform the user with a small popup message
  136. }
  137. if (m_pInternalICall)
  138. {
  139. m_pInternalICall->Cancel();
  140. }
  141. Update();
  142. }
  143. }
  144. ///////////////////////////////////////////////////////////////////////////
  145. // IUnknown methods
  146. STDMETHODIMP_(ULONG) CCall::AddRef(void)
  147. {
  148. return RefCount::AddRef();
  149. }
  150. STDMETHODIMP_(ULONG) CCall::Release(void)
  151. {
  152. return RefCount::Release();
  153. }
  154. STDMETHODIMP CCall::QueryInterface(REFIID riid, PVOID *ppv)
  155. {
  156. HRESULT hr = S_OK;
  157. if ((riid == IID_INmCallNotify2) || (riid == IID_INmCallNotify) || (riid == IID_IUnknown))
  158. {
  159. *ppv = (INmCallNotify2 *)this;
  160. ApiDebugMsg(("CCall::QueryInterface()"));
  161. }
  162. else
  163. {
  164. hr = E_NOINTERFACE;
  165. *ppv = NULL;
  166. ApiDebugMsg(("CCall::QueryInterface(): Called on unknown interface."));
  167. }
  168. if (S_OK == hr)
  169. {
  170. AddRef();
  171. }
  172. return hr;
  173. }
  174. ///////////////////////////////////////////////////////////////////////////
  175. // INmCallNotify methods
  176. STDMETHODIMP CCall::NmUI(CONFN uNotify)
  177. {
  178. return S_OK;
  179. }
  180. STDMETHODIMP CCall::StateChanged(NM_CALL_STATE uState)
  181. {
  182. Update();
  183. return S_OK;
  184. }
  185. STDMETHODIMP CCall::Failed(ULONG uError)
  186. {
  187. DbgMsgCall("CCall: %08X Failed uError=%d", this, uError);
  188. return S_OK;
  189. }
  190. STDMETHODIMP CCall::Accepted(INmConference *pConference)
  191. {
  192. DbgMsgCall("CCall: %08X Accepted pConference=0x%08X", this, pConference);
  193. return S_OK;
  194. }
  195. VOID CCall::ShowProgress(BOOL fShow)
  196. {
  197. if (NULL == m_pDlgCall)
  198. return;
  199. ShowWindow(m_pDlgCall->GetHwnd(), fShow ? SW_SHOWNORMAL : SW_HIDE);
  200. }
  201. VOID CCall::RemoveProgress(void)
  202. {
  203. if (NULL == m_pDlgCall)
  204. return;
  205. m_pDlgCall->Destroy();
  206. m_pDlgCall->Release();
  207. m_pDlgCall = NULL;
  208. }
  209. /* C A L L E R R O R */
  210. /*-------------------------------------------------------------------------
  211. %%Function: CallError
  212. -------------------------------------------------------------------------*/
  213. STDMETHODIMP CCall::CallError(UINT cns)
  214. {
  215. UINT ids = 0;
  216. ShowProgress(FALSE);
  217. ASSERT(m_pInternalICall != NULL);
  218. DbgMsgCall("CCall: %08X CallError cns=%08X", this, cns);
  219. // Translate cns to normal error message
  220. switch (cns)
  221. {
  222. case CN_RC_NAME_RESOLUTION_FAILED:
  223. ids = IDS_RESOLVE_FAILED;
  224. break;
  225. case CN_RC_CONNECT_FAILED:
  226. case CN_RC_AUDIO_CONNECT_FAILED:
  227. ids = IDS_COULD_NOT_CONNECT;
  228. break;
  229. case CN_RC_CONNECT_REMOTE_NO_SECURITY:
  230. ids = IDS_CONNECT_REMOTE_NO_SECURITY;
  231. break;
  232. case CN_RC_CONNECT_REMOTE_DOWNLEVEL_SECURITY:
  233. ids = IDS_CONNECT_REMOTE_DOWNLEVEL_SECURITY;
  234. break;
  235. case CN_RC_CONNECT_AUTHENTICATION_FAILED:
  236. ids = IDS_CONNECT_AUTHENTICATION_FAILED;
  237. break;
  238. case CN_RC_SECURITY_FAILED:
  239. ids = IDS_CONNECT_SECURITY_FAILED;
  240. break;
  241. case CN_RC_CONNECT_REMOTE_REQUIRE_SECURITY:
  242. ids = IDS_CONNECT_REMOTE_REQUIRE_SECURITY;
  243. break;
  244. case CN_RC_CONFERENCE_JOIN_DENIED:
  245. ids = IDS_JOIN_DENIED;
  246. break;
  247. case CN_RC_CONFERENCE_INVITE_DENIED:
  248. ids = IDS_INVITE_DENIED;
  249. break;
  250. case CN_RC_INVITE_DENIED_REMOTE_IN_CONF:
  251. ids = IDS_INVITE_DENIED_REMOTE_CONF;
  252. break;
  253. case CN_RC_CONFERENCE_DOES_NOT_EXIST:
  254. ids = m_fSelectedConference ?
  255. IDS_CONFERENCE_DOES_NOT_EXIST : IDS_CONFERENCE_ENDED_BEFORE_JOIN;
  256. break;
  257. case CN_RC_CONFERENCE_ENDED_BEFORE_JOIN:
  258. // REVIEW: This is no longer sent?
  259. ids = IDS_CONFERENCE_ENDED_BEFORE_JOIN;
  260. break;
  261. case CN_RC_AUDIO_NOT_AVAILABLE:
  262. ids = IDS_AUDIO_NOT_AVAILABLE;
  263. break;
  264. case CN_RC_AUDIO_FAILED_AFTER_DATA:
  265. ids = IDS_AUDIO_FAILED_AFTER_DATA;
  266. break;
  267. case CN_RC_AUDIO_IN_USE_REMOTE_AFTER_DATA:
  268. ids = IDS_AUDIO_IN_USE_REMOTE_AFTER_DATA;
  269. break;
  270. case CN_RC_AUDIO_IN_USE_REMOTE:
  271. ids = IDS_AUDIO_IN_USE_REMOTE;
  272. break;
  273. case CN_RC_AUDIO_IN_USE_LOCAL_AFTER_DATA:
  274. ids = IDS_AUDIO_IN_USE_LOCAL_AFTER_DATA;
  275. break;
  276. case CN_RC_AUDIO_IN_USE_LOCAL:
  277. ids = IDS_AUDIO_IN_USE_LOCAL;
  278. break;
  279. case CN_RC_CANT_INVITE_MCU:
  280. ids = IDS_CANT_INVITE_MCU;
  281. break;
  282. case CN_RC_REMOTE_PLACING_CALL:
  283. ids = IDS_REMOTE_PLACING_CALL;
  284. break;
  285. case CN_RC_TRANSPORT_FAILURE:
  286. ids = IDS_TRANSPORT_UNAVAILABLE;
  287. break;
  288. case CN_RC_CANT_JOIN_ALREADY_IN_CALL:
  289. ids = IDS_INCALL_JOIN_FAILED;
  290. break;
  291. case CN_RC_CONFERENCE_ENDED_BEFORE_ACCEPTED:
  292. ids = IDS_INVITE_CONF_ENDED;
  293. break;
  294. case CN_RC_GK_CALLEE_NOT_REGISTERED:
  295. ids = IDS_GK_CALLEE_NOT_REGISTERED;
  296. break;
  297. case CN_RC_GK_TIMEOUT:
  298. ids = IDS_GK_TIMEOUT;
  299. break;
  300. case CN_RC_GK_REJECTED:
  301. ids = IDS_GK_REJECTED;
  302. break;
  303. case CN_RC_GK_NOT_REGISTERED:
  304. ids = IDS_GK_NOT_REGISTERED;
  305. break;
  306. default:
  307. return S_FALSE;
  308. } /* switch (cns) */
  309. DisplayMsgIdsParam(ids, m_pszDisplayName);
  310. return S_OK;
  311. }
  312. STDMETHODIMP CCall::RemoteConference(BOOL fMCU, BSTR *pwszConfNames, BSTR *pbstrConfToJoin)
  313. {
  314. return OnUIRemoteConference(fMCU, (PWSTR *)pwszConfNames, pbstrConfToJoin);
  315. }
  316. STDMETHODIMP CCall::RemotePassword(BSTR bstrConference, BSTR *pbstrPassword, PBYTE pb, DWORD cb, BOOL fIsService)
  317. {
  318. TCHAR* pLastCertText = NULL;
  319. if (NULL != pb) {
  320. ASSERT(cb > 0);
  321. if (!(pLastCertText = FormatCert(pb, cb)))
  322. {
  323. ERROR_OUT(("FormatCert failed"));
  324. }
  325. }
  326. ShowProgress(FALSE);
  327. HRESULT hr = OnUIRemotePassword(bstrConference, pbstrPassword, pLastCertText, fIsService);
  328. if (pLastCertText) delete pLastCertText;
  329. return hr;
  330. }
  331. NM_CALL_STATE CCall::GetState()
  332. {
  333. NM_CALL_STATE callState = NM_CALL_INVALID;
  334. if(m_pInternalICall)
  335. {
  336. m_pInternalICall->GetState(&callState);
  337. }
  338. return callState;
  339. }
  340. /* U P D A T E */
  341. /*-------------------------------------------------------------------------
  342. %%Function: Update
  343. Update the cached information about the call
  344. -------------------------------------------------------------------------*/
  345. VOID CCall::Update(void)
  346. {
  347. DBGENTRY(CCall::Update);
  348. NM_CALL_STATE callState = GetState();;
  349. switch (callState)
  350. {
  351. case NM_CALL_CANCELED:
  352. case NM_CALL_ACCEPTED:
  353. case NM_CALL_REJECTED:
  354. // Remove the call from the global list because we'll never get
  355. // any more notifications for this.
  356. if (RemoveFromList())
  357. {
  358. if (FIncoming())
  359. {
  360. if ((NM_CALL_CANCELED == callState) && (NULL != m_ppm))
  361. {
  362. //
  363. // if m_fInRespond is set then we've already
  364. // dismissed the dialog and the call is being
  365. // cancelled because we discovered the underlying
  366. // connection is gone.
  367. //
  368. if ( !m_fInRespond )
  369. {
  370. delete m_ppm;
  371. m_ppm = NULL;
  372. // Release the lock added by OnRing
  373. Release();
  374. }
  375. }
  376. LogCall(NM_CALL_ACCEPTED == callState);
  377. }
  378. else
  379. {
  380. RemoveProgress();
  381. if (NM_CALL_ACCEPTED == callState)
  382. {
  383. if(m_bAddToMru)
  384. {
  385. CAcdMru CallList;
  386. CallList.AddEntry(m_pszDisplayName, m_pszCallTo, m_nmAddrType);
  387. CallList.Save();
  388. }
  389. }
  390. }
  391. // Release the initial lock on this object
  392. Release();
  393. }
  394. break;
  395. case NM_CALL_RING:
  396. OnRing();
  397. break;
  398. case NM_CALL_SEARCH:
  399. ASSERT(NULL == m_pDlgCall);
  400. m_pDlgCall = new CDlgCall(this);
  401. break;
  402. case NM_CALL_WAIT:
  403. if (NULL != m_pDlgCall)
  404. {
  405. m_pDlgCall->OnStateChange();
  406. }
  407. break;
  408. default:
  409. ERROR_OUT(("CCall::Update: Unknown state %08X", callState));
  410. case NM_CALL_INVALID:
  411. case NM_CALL_INIT:
  412. break;
  413. }
  414. ::UpdateUI(CRUI_CALLANIM | CRUI_TOOLBAR | CRUI_STATUSBAR);
  415. DBGEXIT(CCall::Update);
  416. }
  417. /* F C O M P L E T E */
  418. /*-------------------------------------------------------------------------
  419. %%Function: FComplete
  420. Return TRUE if the call has completed
  421. -------------------------------------------------------------------------*/
  422. BOOL CCall::FComplete(void)
  423. {
  424. switch (GetState())
  425. {
  426. case NM_CALL_ACCEPTED:
  427. case NM_CALL_REJECTED:
  428. case NM_CALL_CANCELED:
  429. return TRUE;
  430. case NM_CALL_INVALID:
  431. case NM_CALL_INIT:
  432. case NM_CALL_RING:
  433. case NM_CALL_SEARCH:
  434. case NM_CALL_WAIT:
  435. default:
  436. return FALSE;
  437. }
  438. }
  439. /* P O P U P M S G R I N G I N G C A L L B A C K */
  440. /*-------------------------------------------------------------------------
  441. %%Function: CCall::PopupMsgRingingCallback
  442. -------------------------------------------------------------------------*/
  443. VOID CALLBACK CCall::PopupMsgRingingCallback(LPVOID pContext, DWORD dwFlags)
  444. {
  445. CCall *pCall = (CCall *) pContext;
  446. ASSERT(NULL != pCall);
  447. DbgMsgCall("CCall: %08X Responding from invite popup - result is 0x%08X", pCall, dwFlags);
  448. DWORD dwCLEF;
  449. if(!( PMF_KILLED & dwFlags ))
  450. {
  451. dwCLEF = (PMF_OK & dwFlags) ? CLEF_ACCEPTED : CLEF_REJECTED;
  452. if (PMF_TIMEOUT & dwFlags)
  453. {
  454. dwCLEF |= CLEF_TIMED_OUT;
  455. }
  456. pCall->RespondToRinging(dwCLEF);
  457. }
  458. if(pCall->m_ppm)
  459. {
  460. // pop up message will be destroyed after callback returns
  461. pCall->m_ppm = NULL;
  462. // Release the lock added by OnRing
  463. pCall->Release();
  464. }
  465. }
  466. /* O N R I N G */
  467. /*-------------------------------------------------------------------------
  468. %%Function: OnRing
  469. Handling an incoming call that just started to "ring".
  470. -------------------------------------------------------------------------*/
  471. VOID CCall::OnRing(void)
  472. {
  473. DbgMsgCall("CCall: %08X OnRing", this);
  474. if (FRejectIncomingCalls())
  475. {
  476. // Respond negatively
  477. WARNING_OUT(("Rejecting invite - not listening or sys pol disabled"));
  478. RespondToRinging(CLEF_REJECTED);
  479. return;
  480. }
  481. if( ConfPolicies::IsAutoAcceptCallsEnabled() && !_Module.InitControlMode())
  482. {
  483. // Respond with success
  484. RespondToRinging(CLEF_ACCEPTED | CLEF_AUTO_ACCEPTED);
  485. return;
  486. }
  487. if(!_Module.InitControlMode())
  488. {
  489. // Display a message for the user
  490. TCHAR szFormatBuf[MAX_PATH];
  491. TCHAR szMsgBuf[MAX_PATH];
  492. if (FLoadString(IDS_INVITE_PERMISSION, szFormatBuf, CCHMAX(szFormatBuf)))
  493. {
  494. TCHAR szName[MAX_PATH];
  495. LPTSTR psz = m_pszDisplayName;
  496. if (FEmptySz(psz))
  497. {
  498. // The name string is blank, so fill it in with a default:
  499. ::LoadString(::GetInstanceHandle(), IDS_UNKNOWN_PERSON,
  500. szName, CCHMAX(szName));
  501. psz = szName;
  502. }
  503. wsprintf(szMsgBuf, szFormatBuf, psz);
  504. }
  505. ASSERT(NULL == m_ppm);
  506. m_ppm = new CPopupMsg(PopupMsgRingingCallback, this);
  507. if (NULL != m_ppm)
  508. {
  509. RegEntry re(UI_KEY, HKEY_CURRENT_USER);
  510. UINT uTime = re.GetNumber(REGVAL_RING_TIMEOUT, DEFAULT_RING_TIMEOUT) * 1000;
  511. AddRef(); // Released in PopupMsgRingingCallback
  512. m_ppm->CreateDlg(szMsgBuf, TRUE, MAKEINTRESOURCE(IDI_CONFROOM),
  513. ::GetInstanceHandle(), IDS_INVITE_SOUND, uTime);
  514. }
  515. }
  516. }
  517. /* R E S P O N D T O R I N G I N G */
  518. /*-------------------------------------------------------------------------
  519. %%Function: RespondToRinging
  520. -------------------------------------------------------------------------*/
  521. BOOL CCall::RespondToRinging(DWORD dwCLEF)
  522. {
  523. BOOL fAccept = FALSE;
  524. m_fInRespond = TRUE;
  525. if (NM_CALL_RING == GetState())
  526. {
  527. if (!FIsConfRoomClosing() && (CLEF_ACCEPTED & dwCLEF))
  528. {
  529. fAccept = TRUE;
  530. if(_Module.IsUIActive())
  531. {
  532. CConfRoom * pcr = ::GetConfRoom();
  533. ASSERT(pcr);
  534. pcr->BringToFront();
  535. }
  536. }
  537. CNmCallObj::StateChanged(m_pInternalICall, fAccept ? NM_CALL_ACCEPTED : NM_CALL_REJECTED);
  538. if (fAccept)
  539. {
  540. m_pInternalICall->Accept();
  541. }
  542. else
  543. {
  544. m_pInternalICall->Reject();
  545. }
  546. }
  547. else
  548. {
  549. CallError(CN_RC_CONFERENCE_ENDED_BEFORE_ACCEPTED);
  550. }
  551. m_fInRespond = FALSE;
  552. return fAccept;
  553. }
  554. /* D I S P L A Y P O P U P */
  555. /*-------------------------------------------------------------------------
  556. %%Function: DisplayPopup
  557. -------------------------------------------------------------------------*/
  558. VOID CCall::DisplayPopup(void)
  559. {
  560. CPopupMsg* ppm = new CPopupMsg(NULL);
  561. if (NULL == ppm)
  562. return;
  563. TCHAR szMsg[MAX_PATH*2];
  564. if (FLoadString1(IDS_CALL_CANCELED_FORMAT, szMsg, m_pszDisplayName))
  565. {
  566. ppm->Create(szMsg, FALSE, MAKEINTRESOURCE(IDI_CONFROOM),
  567. ::GetInstanceHandle(), IDS_PERSON_LEFT_SOUND,
  568. ROSTER_TIP_TIMEOUT);
  569. }
  570. else
  571. {
  572. delete ppm;
  573. }
  574. }
  575. /* P L A C E C A L L */
  576. /*-------------------------------------------------------------------------
  577. %%Function: PlaceCall
  578. Place an outgoing call.
  579. -------------------------------------------------------------------------*/
  580. HRESULT
  581. CCall::PlaceCall
  582. (
  583. DWORD dwFlags,
  584. NM_ADDR_TYPE addrType,
  585. const TCHAR * const setupAddress,
  586. const TCHAR * const destinationAddress,
  587. const TCHAR * const alias,
  588. const TCHAR * const url,
  589. const TCHAR * const conference,
  590. const TCHAR * const password,
  591. const TCHAR * const userData
  592. ){
  593. USES_CONVERSION;
  594. DBGENTRY(CCall::PlaceCall);
  595. HRESULT hr = E_FAIL;
  596. ASSERT(m_pInternalICall == NULL);
  597. INmManager2 *pNmMgr = CConfMan::GetNmManager();
  598. ASSERT (NULL != pNmMgr);
  599. hr = pNmMgr->CallEx( &m_pInternalICall,
  600. dwFlags,
  601. addrType,
  602. CComBSTR( GetPszName() ),
  603. CComBSTR( setupAddress ),
  604. CComBSTR( destinationAddress ),
  605. CComBSTR( alias ),
  606. CComBSTR( url ),
  607. CComBSTR( conference ),
  608. CComBSTR( password ),
  609. CComBSTR( userData ) );
  610. if(m_pInternalICall && (CRPCF_JOIN & dwFlags) )
  611. {
  612. SetSelectedConference();
  613. }
  614. // Force an update of the status bar, animation, etc.
  615. ::UpdateUI(CRUI_DEFAULT);
  616. pNmMgr->Release();
  617. TRACE_OUT(("CCall::PlaceCall(%s) result=%08X", m_pszCallTo? m_pszCallTo: g_szEmpty, hr));
  618. DBGEXIT_HR(CCall::PlaceCall, hr);
  619. return hr;
  620. }
  621. VOID CCall::LogCall(BOOL fAccepted)
  622. {
  623. LPCTSTR pcszName = GetPszName();
  624. TCHAR szName[MAX_PATH];
  625. if (FEmptySz(pcszName))
  626. {
  627. if (FLoadString(IDS_UNKNOWN_PERSON, szName, CCHMAX(szName)))
  628. pcszName = szName;
  629. }
  630. LOGHDR logHdr;
  631. CRosterInfo ri;
  632. LPBYTE pb;
  633. ULONG cb;
  634. LPBYTE pbCert = NULL;
  635. ULONG cbCert = 0;
  636. if (SUCCEEDED(GetINmCall()->GetUserData(g_csguidRostInfo, &pb, &cb)))
  637. {
  638. ri.Load(pb);
  639. }
  640. GetINmCall()->GetUserData(g_csguidSecurity, &pbCert, &cbCert);
  641. DWORD dwCLEF = fAccepted ? CLEF_ACCEPTED : CLEF_REJECTED;
  642. if (ri.IsEmpty())
  643. {
  644. // No caller data - not NetMeeting
  645. dwCLEF |= CLEF_NO_CALL;
  646. }
  647. if (pbCert)
  648. {
  649. ASSERT(cbCert);
  650. dwCLEF |= CLEF_SECURE;
  651. }
  652. ZeroMemory(&logHdr, sizeof(LOGHDR));
  653. logHdr.dwCLEF = dwCLEF;
  654. if (NULL != ::GetIncomingCallLog() )
  655. {
  656. // Write the data to the log file
  657. ::GetIncomingCallLog()->AddCall(pcszName, &logHdr, &ri, pbCert, cbCert);
  658. }
  659. }
  660. /* C R E A T E I N C O M I N G C A L L */
  661. /*-------------------------------------------------------------------------
  662. %%Function: CreateIncomingCall
  663. Create an CCall object for the incoming call.
  664. -------------------------------------------------------------------------*/
  665. CCall * CreateIncomingCall(INmCall * pNmCall)
  666. {
  667. HRESULT hr;
  668. BSTR bstr;
  669. LPTSTR pszName = NULL;
  670. LPTSTR pszAddr = NULL;
  671. NM_ADDR_TYPE addrType = NM_ADDR_UNKNOWN;
  672. ASSERT(NULL != pNmCall);
  673. // Get the display name
  674. hr = pNmCall->GetName(&bstr);
  675. if (SUCCEEDED(hr))
  676. {
  677. hr = BSTR_to_LPTSTR(&pszName, bstr);
  678. SysFreeString(bstr);
  679. }
  680. // Get the address and type
  681. hr = pNmCall->GetAddr(&bstr, &addrType);
  682. if (SUCCEEDED(hr))
  683. {
  684. hr = BSTR_to_LPTSTR(&pszAddr, bstr);
  685. SysFreeString(bstr);
  686. }
  687. CCall * pCall = new CCall(pszAddr, pszName, NM_ADDR_CALLTO, FALSE, TRUE /* fIncoming */);
  688. delete pszName;
  689. delete pszAddr;
  690. return pCall;
  691. }
  692. ///////////////////////////////////////////////////////////////////////////
  693. // Global Functions
  694. /* C A L L F R O M N M C A L L */
  695. /*-------------------------------------------------------------------------
  696. %%Function: CallFromNmCall
  697. -------------------------------------------------------------------------*/
  698. CCall * CallFromNmCall(INmCall * pNmCall)
  699. {
  700. if (NULL == g_pCallList)
  701. return NULL;
  702. POSITION pos = g_pCallList->GetHeadPosition();
  703. while (pos)
  704. {
  705. CCall * pCall = (CCall *) g_pCallList->GetNext(pos);
  706. ASSERT(NULL != pCall);
  707. if (pNmCall == pCall->GetINmCall())
  708. {
  709. return pCall;
  710. }
  711. }
  712. // no matching call?
  713. return NULL;
  714. }
  715. /* F I S C A L L I N P R O G R E S S */
  716. /*-------------------------------------------------------------------------
  717. %%Function: FIsCallInProgress
  718. Return TRUE if there is an incoming or outgoing call in progress.
  719. -------------------------------------------------------------------------*/
  720. BOOL FIsCallInProgress(void)
  721. {
  722. if (NULL == g_pCallList)
  723. return FALSE;
  724. return !g_pCallList->IsEmpty();
  725. }
  726. /* G E T L A S T O U T G O I N G C A L L */
  727. /*-------------------------------------------------------------------------
  728. %%Function: GetLastOutgoingCall
  729. -------------------------------------------------------------------------*/
  730. CCall * GetLastOutgoingCall(void)
  731. {
  732. if (NULL == g_pCallList)
  733. return NULL;
  734. CCall * pCall = NULL;
  735. POSITION pos = g_pCallList->GetHeadPosition();
  736. while (pos)
  737. {
  738. CCall * pCallTemp = (CCall *) g_pCallList->GetNext(pos);
  739. ASSERT(NULL != pCallTemp);
  740. if (!pCallTemp->FIncoming())
  741. {
  742. pCall = pCallTemp;
  743. }
  744. }
  745. return pCall;
  746. }
  747. /* G E T C A L L S T A T U S */
  748. /*-------------------------------------------------------------------------
  749. %%Function: GetCallStatus
  750. Check the current call status and return a string for the status bar.
  751. Return 0 if no call information is available
  752. -------------------------------------------------------------------------*/
  753. DWORD GetCallStatus(LPTSTR pszStatus, int cchMax, UINT * puID)
  754. {
  755. ASSERT(NULL != pszStatus);
  756. ASSERT(NULL != puID);
  757. ASSERT(cchMax > 0);
  758. *pszStatus = _T('\0');
  759. *puID = 0;
  760. CCall *pCall = GetLastOutgoingCall();
  761. if (NULL == pCall)
  762. return 0; // not in a call
  763. // Use the status info from the most recent connection attempt:
  764. switch (pCall->GetState())
  765. {
  766. case NM_CALL_INIT:
  767. {
  768. *puID = IDS_STATUS_SETTING_UP;
  769. break;
  770. }
  771. case NM_CALL_SEARCH:
  772. {
  773. *puID = IDS_STATUS_FINDING;
  774. break;
  775. }
  776. case NM_CALL_WAIT:
  777. {
  778. *puID = IDS_STATUS_WAITING;
  779. break;
  780. }
  781. default:
  782. {
  783. // unknown/useless call state
  784. return 0;
  785. }
  786. } /* switch */
  787. if (FEmptySz(pCall->GetPszName()))
  788. {
  789. return 0;
  790. }
  791. if (!FLoadString1(*puID, pszStatus, pCall->GetPszName()))
  792. {
  793. return 0;
  794. }
  795. return pCall->GetTickCount();
  796. }
  797. ///////////////////////////////////////////////////////////////////////////
  798. // TODO: Replace these with real connection points
  799. /* O N U I C A L L C R E A T E D */
  800. /*-------------------------------------------------------------------------
  801. %%Function: OnUICallCreated
  802. -------------------------------------------------------------------------*/
  803. HRESULT OnUICallCreated(INmCall *pNmCall)
  804. {
  805. CCall * pCall;
  806. // Notify the API
  807. if (S_OK == pNmCall->IsIncoming())
  808. {
  809. pCall = CreateIncomingCall(pNmCall);
  810. if (NULL == pCall)
  811. {
  812. return S_FALSE;
  813. }
  814. }
  815. else
  816. {
  817. pCall = CallFromNmCall(pNmCall);
  818. if (NULL == pCall)
  819. {
  820. WARNING_OUT(("OnUiCallCreated: Unable to find outgoing call=%08X", pNmCall));
  821. return S_FALSE;
  822. }
  823. }
  824. pCall->SetNmCall(pNmCall);
  825. return S_OK;
  826. }
  827. HRESULT OnUIRemotePassword(BSTR bstrConference, BSTR * pbstrPassword, LPCTSTR pCertText, BOOL fIsService)
  828. {
  829. HRESULT hr = S_FALSE;
  830. USES_CONVERSION;
  831. CPasswordDlg dlgPw(::GetMainWindow(), OLE2T(bstrConference), pCertText, fIsService);
  832. if (IDOK == dlgPw.DoModal())
  833. {
  834. TRACE_OUT(("password dialog complete (OK pressed)"));
  835. LPTSTR_to_BSTR(pbstrPassword, dlgPw.GetPassword());
  836. hr = S_OK;
  837. }
  838. return hr;
  839. }
  840. HRESULT CCall::OnUIRemoteConference(BOOL fMCU, PWSTR* pwszConfNames, BSTR *pbstrConfToJoin)
  841. {
  842. HRESULT hr = S_FALSE;
  843. ShowProgress(FALSE);
  844. // We bring up the "choose a conference" dialog
  845. // when calling an MCU or another node with more than
  846. // one "listed" conference
  847. CChooseConfDlg dlgChoose(::GetMainWindow(), pwszConfNames);
  848. if (IDOK == dlgChoose.DoModal())
  849. {
  850. TRACE_OUT(("choose conference dialog complete (OK pressed)"));
  851. LPTSTR_to_BSTR(pbstrConfToJoin, dlgChoose.GetName());
  852. hr = S_OK;
  853. m_fSelectedConference = TRUE;
  854. }
  855. ShowProgress(TRUE);
  856. return hr;
  857. }
  858. /* F R E E C A L L L I S T */
  859. /*-------------------------------------------------------------------------
  860. %%Function: FreeCallList
  861. Free any remaining calls
  862. -------------------------------------------------------------------------*/
  863. VOID FreeCallList(void)
  864. {
  865. if (NULL == g_pCallList)
  866. return;
  867. while (!g_pCallList->IsEmpty())
  868. {
  869. CCall * pCall = (CCall *) g_pCallList->GetHead();
  870. WARNING_OUT(("FreeCallList: Orphan call=%08X", pCall));
  871. pCall->RemoveFromList();
  872. pCall->Release();
  873. }
  874. delete g_pCallList;
  875. g_pCallList = NULL;
  876. }
  877. /* C A N C E L A L L O U T G O I N G C A L L S */
  878. /*-------------------------------------------------------------------------
  879. %%Function: CancelAllOutgoingCalls
  880. -------------------------------------------------------------------------*/
  881. VOID CancelAllOutgoingCalls(void)
  882. {
  883. if (NULL == g_pCallList)
  884. return;
  885. POSITION pos = g_pCallList->GetHeadPosition();
  886. while (pos)
  887. {
  888. CCall * pCall = (CCall *) g_pCallList->GetNext(pos);
  889. ASSERT(NULL != pCall);
  890. if (!pCall->FIncoming())
  891. {
  892. // Cancel will release the call object.
  893. // Ensure that there is at least one reference.
  894. pCall->AddRef();
  895. pCall->Cancel(TRUE);
  896. pCall->Release();
  897. }
  898. }
  899. }
  900. /* C A N C E L A L L C A L L S */
  901. /*-------------------------------------------------------------------------
  902. %%Function: CancelAllCalls
  903. -------------------------------------------------------------------------*/
  904. VOID CancelAllCalls(void)
  905. {
  906. if (NULL == g_pCallList)
  907. return;
  908. POSITION pos = g_pCallList->GetHeadPosition();
  909. while (pos)
  910. {
  911. CCall * pCall = (CCall *) g_pCallList->GetNext(pos);
  912. ASSERT(NULL != pCall);
  913. // Cancel will release the call object.
  914. // Ensure that there is at least one reference.
  915. pCall->AddRef();
  916. pCall->Cancel(TRUE);
  917. pCall->Release();
  918. }
  919. }
  920. ///////////////////////////////////////////////////////////////////////////
  921. // IP Utilities
  922. /* F L O C A L I P A D D R E S S */
  923. /*-------------------------------------------------------------------------
  924. %%Function: FLocalIpAddress
  925. Return TRUE if the parameter matches the local IP address.
  926. -------------------------------------------------------------------------*/
  927. BOOL FLocalIpAddress(DWORD dwIP)
  928. {
  929. if (dwIP == 0x0100007F)
  930. {
  931. WARNING_OUT(("t-bkrav is trying to call himself"));
  932. return TRUE;
  933. }
  934. // Get own host name
  935. TCHAR sz[MAX_PATH];
  936. if (0 != gethostname(sz, CCHMAX(sz)))
  937. {
  938. WARNING_OUT(("FLocalIpAddress: gethostname failed? err=%s", PszWSALastError()));
  939. return FALSE;
  940. }
  941. HOSTENT * pHostInfo = gethostbyname(sz);
  942. if (NULL == pHostInfo)
  943. {
  944. WARNING_OUT(("FLocalIpAddress: gethostbyname failed? err=%s", PszWSALastError()));
  945. return FALSE;
  946. }
  947. return (dwIP == *(DWORD *) pHostInfo->h_addr);
  948. }
  949. /* F I P A D D R E S S */
  950. /*-------------------------------------------------------------------------
  951. %%Function: FIpAddress
  952. Return TRUE if the string is in the form: a.b.c.d
  953. where a,b,c,d < 256.
  954. Note that inet_addr returns success on strings like "55534" and "3102.550"
  955. FUTURE: Return the converted DWORD
  956. -------------------------------------------------------------------------*/
  957. BOOL FIpAddress(LPCTSTR pcsz)
  958. {
  959. TCHAR ch;
  960. int cPeriods = 0;
  961. int uVal = 0;
  962. ASSERT(NULL != pcsz);
  963. while (_T('\0') != (ch = *pcsz++))
  964. {
  965. switch (ch)
  966. {
  967. case _T('0'):
  968. case _T('1'):
  969. case _T('2'):
  970. case _T('3'):
  971. case _T('4'):
  972. case _T('5'):
  973. case _T('6'):
  974. case _T('7'):
  975. case _T('8'):
  976. case _T('9'):
  977. uVal = (uVal *= 10) + (ch - _T('0'));
  978. if (uVal > 255)
  979. return FALSE;
  980. break;
  981. case _T('.'):
  982. cPeriods++;
  983. uVal = 0;
  984. break;
  985. default:
  986. return FALSE;
  987. } /* switch (ch) */
  988. }
  989. return (3 == cPeriods);
  990. }
  991. VOID DisplayCallError(HRESULT hr, LPCTSTR pcszName)
  992. {
  993. int ids;
  994. WARNING_OUT(("DisplayCallError pcsz=[%s] err=%s", pcszName, PszHResult(hr)));
  995. switch (hr)
  996. {
  997. case S_OK:
  998. case S_FALSE:
  999. return; // no error
  1000. default:
  1001. case E_FAIL:
  1002. WARNING_OUT(("DisplayCallError - message is not very informative. HRESULT=%08X", hr));
  1003. // fall thru to IDS_RESOLVE_FAILED
  1004. case NM_CALLERR_NAME_RESOLUTION:
  1005. ids = IDS_RESOLVE_FAILED;
  1006. break;
  1007. case NM_CALLERR_NOT_INITIALIZED:
  1008. case NM_CALLERR_NOT_FOUND:
  1009. ids = IDS_COULD_NOT_INVITE;
  1010. break;
  1011. case NM_CALLERR_LOOPBACK:
  1012. ids = IDS_CALL_LOOPBACK;
  1013. break;
  1014. case NM_CALLERR_ALREADY_CALLING:
  1015. ids = IDS_ALREADY_CALLING;
  1016. break;
  1017. case E_OUTOFMEMORY:
  1018. ids = IDS_ULSLOGON_OUTOFMEMORY;
  1019. break;
  1020. case NM_CALLERR_INVALID_PHONE_NUMBER:
  1021. ids = IDS_CALLERR_E_BAD_PHONE_NUMBER;
  1022. break;
  1023. case NM_CALLERR_NO_PHONE_SUPPORT:
  1024. ids = IDS_CALLERR_E_NO_PHONE_SUPPORT;
  1025. break;
  1026. case NM_CALLERR_INVALID_IPADDRESS:
  1027. ids = IDS_CALLERR_E_BAD_IPADDRESS;
  1028. break;
  1029. case NM_CALLERR_HOST_RESOLUTION_FAILED:
  1030. ids = IDS_CALLERR_E_BAD_HOSTNAME;
  1031. break;
  1032. case NM_CALLERR_NO_ILS:
  1033. ids = IDS_CALLERR_E_NO_ILS;
  1034. break;
  1035. case NM_CALLERR_ILS_RESOLUTION_FAILED:
  1036. ids = IDS_CALLERR_E_ILS_RESOLUTION_FAILED;
  1037. break;
  1038. case NM_CALLERR_NO_ADDRESS:
  1039. ids = IDS_CALLERR_E_NO_ADDRESS;
  1040. break;
  1041. case NM_CALLERR_INVALID_ADDRESS:
  1042. ids = IDS_CALLERR_E_INVALID_ADDRESS;
  1043. break;
  1044. case NM_CALLERR_NO_GATEKEEPER:
  1045. ids = IDS_CALLERR_E_NO_GATEKEEPER;
  1046. break;
  1047. case NM_CALLERR_NOT_REGISTERED:
  1048. ids = IDS_GK_NOT_REGISTERED;
  1049. break;
  1050. case NM_CALLERR_NO_GATEWAY:
  1051. ids = IDS_CALLERR_E_NO_GATEWAY;
  1052. break;
  1053. case NM_CALLERR_PARAM_ERROR:
  1054. ids = IDS_CALLERR_E_PARAM_ERROR;
  1055. break;
  1056. case NM_CALLERR_SECURITY_MISMATCH:
  1057. ids = IDS_CALLERR_E_SECURITY_MISMATCH;
  1058. break;
  1059. case NM_CALLERR_UNESCAPE_ERROR:
  1060. ids = IDS_CALLERR_E_UNESCAPE_ERROR;
  1061. break;
  1062. case NM_CALLERR_IN_CONFERENCE:
  1063. ids = IDS_INVITE_DENIED_REMOTE_CONF;
  1064. break;
  1065. }
  1066. DisplayMsgIdsParam(ids, pcszName);
  1067. }
  1068. ///////////////////////////////////////////////////////////////////////
  1069. // Gateway utility routines
  1070. /* G E T D E F A U L T G A T E W A Y */
  1071. /*-------------------------------------------------------------------------
  1072. %%Function: GetDefaultGateway
  1073. -------------------------------------------------------------------------*/
  1074. int GetDefaultGateway(LPTSTR psz, UINT cchMax)
  1075. {
  1076. RegEntry re(CONFERENCING_KEY, HKEY_CURRENT_USER);
  1077. // Make sure it's enabled
  1078. if (0 == re.GetNumber(REGVAL_USE_H323_GATEWAY, DEFAULT_USE_H323_GATEWAY))
  1079. {
  1080. SetEmptySz(psz);
  1081. return 0;
  1082. }
  1083. lstrcpyn(psz, re.GetString(REGVAL_H323_GATEWAY), cchMax);
  1084. return lstrlen(psz);
  1085. }
  1086. BOOL FH323GatewayEnabled(VOID)
  1087. {
  1088. if (!::FIsAudioAllowed())
  1089. return FALSE;
  1090. TCHAR sz[MAX_PATH];
  1091. return 0 != GetDefaultGateway(sz, CCHMAX(sz));
  1092. }
  1093. /* C R E A T E G A T E W A Y A D D R E S S */
  1094. /*-------------------------------------------------------------------------
  1095. %%Function: CreateGatewayAddress
  1096. Create a gateway address in the form: gateway/address
  1097. e.g. "157.59.0.40/65000"
  1098. -------------------------------------------------------------------------*/
  1099. HRESULT CreateGatewayAddress(LPTSTR pszResult, UINT cchMax, LPCTSTR pszAddr)
  1100. {
  1101. int cch = GetDefaultGateway(pszResult, cchMax);
  1102. if (0 == cch)
  1103. return E_FAIL;
  1104. if (cchMax <= (UINT) (cch + 1 + lstrlen(pszAddr)))
  1105. return E_FAIL;
  1106. *(pszResult+cch) = _T('/');
  1107. pszResult += cch+1;
  1108. lstrcpy(pszResult, pszAddr);
  1109. return S_OK;
  1110. }
  1111. ///////////////////////////////////////////////////////////////////////
  1112. // Gatekeeper utility routines
  1113. NM_GK_STATE g_GkLogonState = NM_GK_NOT_IN_GK_MODE;
  1114. BOOL FGkEnabled(VOID)
  1115. {
  1116. return ( ConfPolicies::CallingMode_GateKeeper == ConfPolicies::GetCallingMode() );
  1117. }
  1118. inline bool ISE164CHAR(TCHAR digit)
  1119. {
  1120. if ((digit >= '0') && (digit <= '9'))
  1121. {
  1122. return true;
  1123. }
  1124. if ((digit == '#') || (digit == '*'))
  1125. {
  1126. return true;
  1127. }
  1128. return false;
  1129. }
  1130. // removes non E-164 chars from a phone number string
  1131. int CleanupE164String(LPTSTR szPhoneNumber)
  1132. {
  1133. int nLength;
  1134. int nIndex, nIndexWrite;
  1135. if ((szPhoneNumber == NULL) || (szPhoneNumber[0] == '\0'))
  1136. {
  1137. return 0;
  1138. }
  1139. nIndexWrite = 0;
  1140. nLength = lstrlen(szPhoneNumber);
  1141. for (nIndex = 0; nIndex < nLength; nIndex++)
  1142. {
  1143. if (ISE164CHAR(szPhoneNumber[nIndex]))
  1144. {
  1145. if (nIndex != nIndexWrite)
  1146. {
  1147. szPhoneNumber[nIndexWrite] = szPhoneNumber[nIndex];
  1148. }
  1149. nIndexWrite++;
  1150. }
  1151. }
  1152. szPhoneNumber[nIndexWrite] = '\0';
  1153. return nIndexWrite; // length of the new string
  1154. }
  1155. // removes non E-164 & non-comma chars from a phone number string
  1156. int CleanupE164StringEx(LPTSTR szPhoneNumber)
  1157. {
  1158. int nLength;
  1159. int nIndex, nIndexWrite;
  1160. if ((szPhoneNumber == NULL) || (szPhoneNumber[0] == '\0'))
  1161. {
  1162. return 0;
  1163. }
  1164. nIndexWrite = 0;
  1165. nLength = lstrlen(szPhoneNumber);
  1166. for (nIndex = 0; nIndex < nLength; nIndex++)
  1167. {
  1168. if (ISE164CHAR(szPhoneNumber[nIndex]) || (szPhoneNumber[nIndex] == ',') )
  1169. {
  1170. if (nIndex != nIndexWrite)
  1171. {
  1172. szPhoneNumber[nIndexWrite] = szPhoneNumber[nIndex];
  1173. }
  1174. nIndexWrite++;
  1175. }
  1176. }
  1177. szPhoneNumber[nIndexWrite] = '\0';
  1178. return nIndexWrite; // length of the new string
  1179. }
  1180. static bool _CanLogonToGk()
  1181. {
  1182. return (NULL != g_pNmSysInfo) &&
  1183. FGkEnabled() &&
  1184. ( ( NM_GK_IDLE == g_GkLogonState ) || ( NM_GK_NOT_IN_GK_MODE == g_GkLogonState ) );
  1185. }
  1186. void GkLogon(void)
  1187. {
  1188. if(_CanLogonToGk())
  1189. {
  1190. // In case the logon fails, we set this to idle
  1191. SetGkLogonState(NM_GK_IDLE);
  1192. RegEntry reConf(CONFERENCING_KEY, HKEY_CURRENT_USER);
  1193. LPCTSTR pszServer = reConf.GetString(REGVAL_GK_SERVER);
  1194. g_pCCallto->SetGatekeeperName( pszServer );
  1195. RegEntry reULS(ISAPI_CLIENT_KEY, HKEY_CURRENT_USER);
  1196. LPTSTR pszAliasID = NULL;
  1197. LPTSTR pszAliasE164 = NULL;
  1198. ConfPolicies::eGKAddressingMode mode = ConfPolicies::GKAddressing_Invalid;
  1199. mode = ConfPolicies::GetGKAddressingMode();
  1200. if( (ConfPolicies::GKAddressing_PhoneNum == mode) || (ConfPolicies::GKAddressing_Both == mode) )
  1201. {
  1202. pszAliasE164 = PszAlloc(reULS.GetString( REGVAL_ULS_PHONENUM_NAME ));
  1203. CleanupE164String(pszAliasE164);
  1204. }
  1205. if( (ConfPolicies::GKAddressing_Account == mode) || (ConfPolicies::GKAddressing_Both == mode) )
  1206. {
  1207. pszAliasID = PszAlloc(reULS.GetString( REGVAL_ULS_GK_ACCOUNT ));
  1208. }
  1209. HRESULT hr = g_pNmSysInfo->GkLogon(CComBSTR(pszServer),
  1210. CComBSTR(pszAliasID ? pszAliasID : g_szEmpty),
  1211. CComBSTR(pszAliasE164 ? pszAliasE164 : g_szEmpty));
  1212. delete pszAliasID;
  1213. delete pszAliasE164;
  1214. if( SUCCEEDED( hr ) )
  1215. {
  1216. SetGkLogonState(NM_GK_LOGGING_ON);
  1217. }
  1218. else
  1219. {
  1220. PostConfMsgBox(IDS_ERR_GK_NOT_FOUND);
  1221. }
  1222. }
  1223. }
  1224. void GkLogoff(void)
  1225. {
  1226. if (NULL != g_pNmSysInfo)
  1227. {
  1228. g_pNmSysInfo->GkLogoff();
  1229. }
  1230. SetGkLogonState( NM_GK_IDLE );
  1231. }
  1232. bool IsGatekeeperLoggedOn(void)
  1233. {
  1234. return ( NM_GK_LOGGED_ON == g_GkLogonState );
  1235. }
  1236. bool IsGatekeeperLoggingOn(void)
  1237. {
  1238. return ( NM_GK_LOGGING_ON == g_GkLogonState );
  1239. }
  1240. void SetGkLogonState( NM_GK_STATE state )
  1241. {
  1242. if( FGkEnabled() )
  1243. {
  1244. if( g_GkLogonState != state )
  1245. {
  1246. // Set the new state
  1247. g_GkLogonState = state;
  1248. }
  1249. }
  1250. else
  1251. {
  1252. // We are not in GK mode anymore
  1253. g_GkLogonState = NM_GK_NOT_IN_GK_MODE;
  1254. }
  1255. ::UpdateUI(CRUI_STATUSBAR, TRUE);
  1256. g_pCCallto->SetGatekeeperEnabled( IsGatekeeperLoggedOn() || IsGatekeeperLoggingOn() );
  1257. }
  1258. CCallResolver::CCallResolver(LPCTSTR pszAddr, NM_ADDR_TYPE addrType) :
  1259. m_pszAddr(PszAlloc(pszAddr)),
  1260. m_pszAddrIP(NULL),
  1261. m_addrType(addrType)
  1262. {
  1263. }
  1264. CCallResolver::~CCallResolver()
  1265. {
  1266. delete m_pszAddr;
  1267. delete m_pszAddrIP;
  1268. }
  1269. ///////////////////////////////////////////////////////////////////////////
  1270. // Name Resolution
  1271. HRESULT CCallResolver::CheckHostEnt(HOSTENT * pHostInfo)
  1272. {
  1273. // Only expecting IP addresses..
  1274. if ((AF_INET != pHostInfo->h_addrtype) || (sizeof(DWORD) != pHostInfo->h_length))
  1275. {
  1276. WARNING_OUT(("CCallResolver: %08X CheckHostEnt - address type=%d",this, pHostInfo->h_addrtype));
  1277. return E_FAIL;
  1278. }
  1279. struct in_addr inAddr;
  1280. inAddr.s_addr = *((DWORD *)pHostInfo->h_addr);
  1281. if (FLocalIpAddress(inAddr.s_addr))
  1282. {
  1283. WARNING_OUT(("CCallResolver: %08X CheckHostEnt - Attempted to call local machine", this));
  1284. return NM_CALLERR_LOOPBACK;
  1285. }
  1286. m_pszAddrIP = PszAlloc(inet_ntoa(inAddr));
  1287. if (NULL == m_pszAddrIP)
  1288. return E_OUTOFMEMORY;
  1289. return S_OK;
  1290. }
  1291. HRESULT CCallResolver::ResolveMachineName(LPCTSTR pcszAddr)
  1292. {
  1293. TCHAR szOem[MAX_PATH];
  1294. lstrcpyn(szOem, pcszAddr, CCHMAX(szOem));
  1295. CharUpper(szOem);
  1296. CharToOem(szOem, szOem);
  1297. HOSTENT * pHostInfo = gethostbyname(szOem);
  1298. if (NULL == pHostInfo)
  1299. {
  1300. WARNING_OUT(("CCallResolver: %08X ResolveMachineName(%s) gethostbyname failed. err=%s",
  1301. this, szOem, PszWSALastError()));
  1302. return NM_CALLERR_NAME_RESOLUTION;
  1303. }
  1304. return CheckHostEnt(pHostInfo);
  1305. }
  1306. HRESULT CCallResolver::ResolveUlsName(LPCTSTR pcszAddr)
  1307. {
  1308. TCHAR szIP[MAX_PATH];
  1309. TCHAR szServer[MAX_PATH];
  1310. LPCTSTR pcsz = ExtractServerName(pcszAddr, szServer, CCHMAX(szServer));
  1311. if (pcsz == pcszAddr)
  1312. return NM_CALLERR_NAME_RESOLUTION;
  1313. HRESULT hr = S_OK;
  1314. if( SUCCEEDED( hr = CNmLDAP::ResolveUser( pcsz, szServer, szIP, CCHMAX( szIP ) ) ) )
  1315. {
  1316. hr = ResolveIpName( szIP );
  1317. }
  1318. return hr;
  1319. }
  1320. HRESULT CCallResolver::ResolveIpName(LPCTSTR pcszAddr)
  1321. {
  1322. DWORD dwIP = inet_addr(pcszAddr);
  1323. if (INADDR_NONE == dwIP)
  1324. return NM_CALLERR_NAME_RESOLUTION;
  1325. char * pAddr = (char *) &dwIP;
  1326. HOSTENT hostInfo;
  1327. ClearStruct(&hostInfo);
  1328. hostInfo.h_addrtype = AF_INET;
  1329. hostInfo.h_length = sizeof(DWORD);
  1330. hostInfo.h_addr_list = &pAddr;
  1331. return CheckHostEnt(&hostInfo);
  1332. }
  1333. HRESULT CCallResolver::ResolveGateway(LPCTSTR pcszAddr)
  1334. {
  1335. TCHAR szGateway[MAX_PATH];
  1336. LPCTSTR pchSlash = _StrChr(pcszAddr, _T('/'));
  1337. if (NULL == pchSlash)
  1338. {
  1339. WARNING_OUT(("CCallResolver: %08X ResolveGateway(%s) no separator?", this, pcszAddr));
  1340. return NM_CALLERR_NAME_RESOLUTION;
  1341. }
  1342. lstrcpyn(szGateway, pcszAddr, (int)(1 + (pchSlash-pcszAddr)));
  1343. return ResolveIpName(szGateway);
  1344. }
  1345. /* R E S O L V E */
  1346. /*-------------------------------------------------------------------------
  1347. %%Function: Resolve
  1348. Attempt to resolve the string into a standard IP address.
  1349. -------------------------------------------------------------------------*/
  1350. HRESULT CCallResolver::Resolve()
  1351. {
  1352. DBGENTRY(CCallResolver::Resolve);
  1353. HRESULT hr = E_FAIL;
  1354. switch (m_addrType)
  1355. {
  1356. case NM_ADDR_UNKNOWN:
  1357. {
  1358. if (NULL != _StrChr(m_pszAddr, _T('/')))
  1359. {
  1360. if(SUCCEEDED(hr = ResolveUlsName(m_pszAddr)))
  1361. {
  1362. m_addrType = NM_ADDR_ULS;
  1363. }
  1364. break;
  1365. }
  1366. if (FIpAddress(m_pszAddr))
  1367. {
  1368. if(SUCCEEDED(hr = ResolveIpName(m_pszAddr)))
  1369. {
  1370. m_addrType = NM_ADDR_IP;
  1371. }
  1372. break;
  1373. }
  1374. if(SUCCEEDED(hr = ResolveMachineName(m_pszAddr)))
  1375. {
  1376. m_addrType = NM_ADDR_MACHINENAME;
  1377. }
  1378. break;
  1379. }
  1380. case NM_ADDR_H323_GATEWAY:
  1381. {
  1382. LPTSTR pch = (LPTSTR) _StrChr(m_pszAddr, _T('/'));
  1383. if (NULL != pch)
  1384. {
  1385. // Address is in the format: Gateway/address
  1386. // e.g. "157.59.0.40/65000" or "efusion/65000"
  1387. *pch = _T('\0');
  1388. pch++;
  1389. hr = ResolveIpName(m_pszAddr);
  1390. if (FAILED(hr))
  1391. {
  1392. hr = ResolveMachineName(m_pszAddr);
  1393. if (FAILED(hr))
  1394. {
  1395. break;
  1396. }
  1397. }
  1398. LPTSTR pszNumber = PszAlloc(pch);
  1399. delete m_pszAddr;
  1400. m_pszAddr = pszNumber;
  1401. }
  1402. else
  1403. {
  1404. TCHAR sz[MAX_PATH];
  1405. if (0 == GetDefaultGateway(sz, CCHMAX(sz)))
  1406. {
  1407. hr = E_FAIL;
  1408. break;
  1409. }
  1410. hr = ResolveIpName(sz);
  1411. if (FAILED(hr))
  1412. {
  1413. hr = ResolveMachineName(sz);
  1414. if (FAILED(hr))
  1415. {
  1416. break;
  1417. }
  1418. }
  1419. }
  1420. hr = FEmptySz(m_pszAddr) ? E_INVALIDARG : S_OK;
  1421. break;
  1422. }
  1423. case NM_ADDR_ULS:
  1424. // Make sure the address is prefixed with an ILS server
  1425. if (NULL == _StrChr(m_pszAddr, _T('/')))
  1426. {
  1427. TCHAR szAddr[CCHMAXSZ_ADDRESS];
  1428. if (!FCreateIlsName(szAddr, NULL, m_pszAddr, CCHMAX(szAddr)))
  1429. {
  1430. hr = E_FAIL;
  1431. break;
  1432. }
  1433. delete m_pszAddr;
  1434. m_pszAddr = PszAlloc(szAddr);
  1435. }
  1436. hr = ResolveUlsName(m_pszAddr);
  1437. break;
  1438. case NM_ADDR_IP:
  1439. hr = ResolveIpName(m_pszAddr);
  1440. if (FAILED(hr) && (hr != NM_CALLERR_LOOPBACK) )
  1441. {
  1442. hr = ResolveMachineName(m_pszAddr);
  1443. }
  1444. break;
  1445. case NM_ADDR_MACHINENAME:
  1446. hr = ResolveMachineName(m_pszAddr);
  1447. break;
  1448. case NM_ADDR_ALIAS_ID:
  1449. case NM_ADDR_ALIAS_E164:
  1450. case NM_ADDR_T120_TRANSPORT:
  1451. hr = FEmptySz(m_pszAddr) ? E_INVALIDARG : S_OK;
  1452. break;
  1453. default:
  1454. WARNING_OUT(("Resolve: Unsupported address type %d", m_addrType));
  1455. ASSERT(E_FAIL == hr);
  1456. break;
  1457. } /* switch (addrType) */
  1458. WARNING_OUT(("CCallResolver::Resolve(%d,%s) result=%08X", m_addrType, m_pszAddrIP ? m_pszAddrIP : m_pszAddr, hr));
  1459. DBGEXIT_HR(CCallResolver::Resolve, hr);
  1460. return hr;
  1461. }