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.

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