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.

660 lines
14 KiB

  1. // File: imanager.cpp
  2. #include "precomp.h"
  3. extern "C"
  4. {
  5. #include "t120.h"
  6. }
  7. #include <version.h>
  8. #include "icall.h"
  9. #include "icall_in.h"
  10. #include "imanager.h"
  11. #include <objbase.h>
  12. #include <initguid.h>
  13. static HRESULT OnNotifyConferenceCreated(IUnknown *pManagerNotify, PVOID pv, REFIID riid);
  14. static HRESULT OnNotifyCallCreated(IUnknown *pManagerNotify, PVOID pv, REFIID riid);
  15. INodeController* g_pNodeController = NULL;
  16. COprahNCUI *COprahNCUI::m_pOprahNCUI = NULL;
  17. static const IID * g_apiidCP_Manager[] =
  18. {
  19. {&IID_INmManagerNotify}
  20. };
  21. COprahNCUI::COprahNCUI(void) :
  22. m_cRef(1),
  23. CConnectionPointContainer(g_apiidCP_Manager, ARRAY_ELEMENTS(g_apiidCP_Manager)),
  24. m_pOutgoingCallManager(NULL),
  25. m_pIncomingCallManager(NULL),
  26. m_pConfObject(NULL),
  27. m_bstrUserName(NULL)
  28. {
  29. DebugEntry(COprahNCUI::COprahNCUI);
  30. m_pOprahNCUI = this;
  31. DebugExitVOID(COprahNCUI::COprahNCUI);
  32. }
  33. COprahNCUI::~COprahNCUI()
  34. {
  35. DebugEntry(COprahNCUI::COprahNCUI);
  36. if (m_pIncomingCallManager)
  37. {
  38. delete m_pIncomingCallManager;
  39. m_pIncomingCallManager = NULL;
  40. }
  41. if (m_pOutgoingCallManager)
  42. {
  43. delete m_pOutgoingCallManager;
  44. m_pOutgoingCallManager = NULL;
  45. }
  46. if (m_pConfObject)
  47. {
  48. m_pConfObject->Release();
  49. m_pConfObject = NULL;
  50. }
  51. // cleanup the node controller:
  52. if (g_pNodeController)
  53. {
  54. g_pNodeController->ReleaseInterface();
  55. g_pNodeController = NULL;
  56. }
  57. if (m_bstrUserName)
  58. {
  59. SysFreeString(m_bstrUserName);
  60. m_bstrUserName = NULL;
  61. }
  62. m_pOprahNCUI = NULL;
  63. DebugExitVOID(COprahNCUI::~COprahNCUI);
  64. }
  65. UINT COprahNCUI::GetOutgoingCallCount()
  66. {
  67. if (m_pOutgoingCallManager)
  68. {
  69. return m_pOutgoingCallManager->GetCallCount();
  70. }
  71. else
  72. {
  73. return 0;
  74. }
  75. }
  76. VOID COprahNCUI::OnOutgoingCallCreated(INmCall* pCall)
  77. {
  78. // notify the UI about this outgoing call
  79. NotifySink(pCall, OnNotifyCallCreated);
  80. if (m_pConfObject && !m_pConfObject->IsConferenceCreated())
  81. {
  82. m_pConfObject->OnConferenceCreated();
  83. NotifySink((INmConference*) m_pConfObject, OnNotifyConferenceCreated);
  84. }
  85. }
  86. VOID COprahNCUI::OnOutgoingCallCanceled(COutgoingCall* pCall)
  87. {
  88. if (m_pOutgoingCallManager)
  89. {
  90. m_pOutgoingCallManager->RemoveFromList(pCall);
  91. }
  92. }
  93. VOID COprahNCUI::OnIncomingCallAccepted()
  94. {
  95. if (m_pConfObject && !m_pConfObject->IsConferenceCreated())
  96. {
  97. m_pConfObject->OnConferenceCreated();
  98. NotifySink((INmConference*) m_pConfObject, OnNotifyConferenceCreated);
  99. }
  100. }
  101. VOID COprahNCUI::OnIncomingCallCreated(INmCall* pCall)
  102. {
  103. NotifySink(pCall, OnNotifyCallCreated);
  104. }
  105. VOID COprahNCUI::CancelCalls()
  106. {
  107. if (m_pOutgoingCallManager)
  108. {
  109. m_pOutgoingCallManager->CancelCalls();
  110. }
  111. if (m_pIncomingCallManager)
  112. {
  113. m_pIncomingCallManager->CancelCalls();
  114. }
  115. }
  116. ULONG COprahNCUI::GetAuthenticatedName(PBYTE * ppb)
  117. {
  118. // Buffer created here should be freed by caller.
  119. ULONG cb;
  120. if (::T120_GetSecurityInfoFromGCCID(0,NULL,&cb)) {
  121. (*ppb) = new BYTE[cb];
  122. if ((*ppb) != NULL) {
  123. ::T120_GetSecurityInfoFromGCCID(0,*ppb,&cb);
  124. return cb;
  125. }
  126. }
  127. (* ppb) = NULL;
  128. return 0;
  129. }
  130. HRESULT COprahNCUI::OnIncomingInviteRequest(CONF_HANDLE hConference,
  131. PCWSTR pcwszNodeName,
  132. BOOL fSecure)
  133. {
  134. DebugEntry(COprahNCUI::OnIncomingInviteRequest);
  135. if (!m_pConfObject)
  136. {
  137. ERROR_OUT(("No m_pConfObject"));
  138. return E_FAIL;
  139. }
  140. if (!m_pConfObject->OnT120Invite(hConference, fSecure))
  141. {
  142. // Respond negatively - already in a call
  143. TRACE_OUT(("Rejecting invite - already in a call"));
  144. ASSERT(g_pNodeController);
  145. ASSERT(hConference);
  146. hConference->InviteResponse(FALSE);
  147. }
  148. else if (m_pIncomingCallManager)
  149. {
  150. m_pIncomingCallManager->OnIncomingT120Call( this,
  151. TRUE,
  152. hConference,
  153. pcwszNodeName,
  154. fSecure);
  155. //
  156. // This will simply notify the UI about the call state.
  157. //
  158. m_pConfObject->SetConfSecurity(fSecure);
  159. }
  160. DebugExitHRESULT(COprahNCUI::OnIncomingInviteRequest, S_OK);
  161. return S_OK;
  162. }
  163. HRESULT COprahNCUI::OnIncomingJoinRequest( CONF_HANDLE hConference,
  164. PCWSTR pcwszNodeName)
  165. {
  166. DebugEntry(COprahNCUI::OnIncomingJoinRequest);
  167. if (m_pIncomingCallManager)
  168. {
  169. // shouldn't we be checking for an active conference before accepting a join
  170. // or will T120 not present this
  171. m_pIncomingCallManager->OnIncomingT120Call( this,
  172. FALSE,
  173. hConference,
  174. pcwszNodeName,
  175. m_pConfObject->IsConfObjSecure());
  176. }
  177. DebugExitHRESULT(COprahNCUI::OnIncomingJoinRequest, S_OK);
  178. return S_OK;
  179. }
  180. HRESULT COprahNCUI::OnConferenceStarted(CONF_HANDLE hConference, HRESULT hResult)
  181. {
  182. DebugEntry(COprahNCUI::OnConferenceStarted);
  183. if (!m_pConfObject)
  184. {
  185. ERROR_OUT(("OnConferenceStarted - no m_pConfObject"));
  186. return E_FAIL;
  187. }
  188. if (m_pConfObject->GetConfHandle() == hConference)
  189. {
  190. m_pConfObject->OnConferenceStarted(hConference, hResult);
  191. m_pOutgoingCallManager->OnConferenceStarted(hConference, hResult);
  192. }
  193. DebugExitHRESULT(COprahNCUI::OnConferenceStarted, S_OK);
  194. return S_OK;
  195. }
  196. HRESULT COprahNCUI::OnQueryRemoteResult(PVOID pvCallerContext,
  197. HRESULT hResult,
  198. BOOL fMCU,
  199. PWSTR* ppwszConferenceNames,
  200. PWSTR* ppwszConfDescriptors)
  201. {
  202. DebugEntry(COprahNCUI::OnQueryRemoteResult);
  203. if (NO_ERROR == hResult)
  204. {
  205. TRACE_OUT(("COprahNCUI: OnQueryRemoteResult Success!"));
  206. }
  207. else
  208. {
  209. TRACE_OUT(("COprahNCUI: OnQueryRemoteResult Failure!"));
  210. }
  211. if (m_pOutgoingCallManager)
  212. {
  213. m_pOutgoingCallManager->OnQueryRemoteResult(pvCallerContext,
  214. hResult,
  215. fMCU,
  216. ppwszConferenceNames,
  217. ppwszConfDescriptors);
  218. }
  219. DebugExitHRESULT(COprahNCUI::OnQueryRemoteResult, S_OK);
  220. return S_OK;
  221. }
  222. HRESULT COprahNCUI::OnInviteResult( CONF_HANDLE hConference,
  223. REQUEST_HANDLE hRequest,
  224. UINT uNodeID,
  225. HRESULT hResult)
  226. {
  227. DebugEntry(COprahNCUI::OnInviteResult);
  228. if (!m_pConfObject)
  229. {
  230. ERROR_OUT(("OnInviteResult - no m_pConfObject"));
  231. return E_FAIL;
  232. }
  233. if (hConference == m_pConfObject->GetConfHandle())
  234. {
  235. if (m_pOutgoingCallManager)
  236. {
  237. m_pOutgoingCallManager->OnInviteResult( hConference,
  238. hRequest,
  239. uNodeID,
  240. hResult);
  241. }
  242. }
  243. DebugExitHRESULT(COprahNCUI::OnInviteResult, S_OK);
  244. return S_OK;
  245. }
  246. HRESULT COprahNCUI::OnConferenceEnded(CONF_HANDLE hConference)
  247. {
  248. DebugEntry(COprahNCUI::OnConferenceEnded);
  249. if (m_pConfObject && (hConference == m_pConfObject->GetConfHandle()))
  250. {
  251. m_pConfObject->OnConferenceEnded();
  252. if (m_pOutgoingCallManager)
  253. {
  254. m_pOutgoingCallManager->OnConferenceEnded(hConference);
  255. }
  256. if (m_pIncomingCallManager)
  257. {
  258. m_pIncomingCallManager->OnT120ConferenceEnded(hConference);
  259. }
  260. }
  261. DebugExitHRESULT(COprahNCUI::OnConferenceEnded, S_OK);
  262. return S_OK;
  263. }
  264. HRESULT COprahNCUI::OnRosterChanged(CONF_HANDLE hConf, PNC_ROSTER pRoster)
  265. {
  266. TRACE_OUT(("COprahNCUI::OnRosterChanged"));
  267. if (!m_pConfObject)
  268. {
  269. ERROR_OUT(("OnRosterChanged - no m_pConfObject"));
  270. return E_FAIL;
  271. }
  272. if (hConf == m_pConfObject->GetConfHandle())
  273. {
  274. m_pConfObject->OnRosterChanged(pRoster);
  275. }
  276. return S_OK;
  277. }
  278. ULONG STDMETHODCALLTYPE COprahNCUI::AddRef(void)
  279. {
  280. ++m_cRef;
  281. return m_cRef;
  282. }
  283. ULONG STDMETHODCALLTYPE COprahNCUI::Release(void)
  284. {
  285. if (m_cRef > 0)
  286. {
  287. --m_cRef;
  288. }
  289. if (!m_cRef)
  290. {
  291. delete this;
  292. return 0;
  293. }
  294. else
  295. {
  296. return m_cRef;
  297. }
  298. }
  299. HRESULT STDMETHODCALLTYPE COprahNCUI::QueryInterface(REFIID riid, PVOID *ppv)
  300. {
  301. HRESULT hr = S_OK;
  302. if ((riid == IID_INmManager) || (riid == IID_IUnknown))
  303. {
  304. *ppv = (INmManager *)this;
  305. TRACE_OUT(("COprahNCUI::QueryInterface()"));
  306. }
  307. else if (riid == IID_IConnectionPointContainer)
  308. {
  309. *ppv = (IConnectionPointContainer *) this;
  310. TRACE_OUT(("COprahNCUI::QueryInterface(): Returning IConnectionPointContainer."));
  311. }
  312. else
  313. {
  314. hr = E_NOINTERFACE;
  315. *ppv = NULL;
  316. TRACE_OUT(("COprahNCUI::QueryInterface(): Called on unknown interface."));
  317. }
  318. if (S_OK == hr)
  319. {
  320. AddRef();
  321. }
  322. return hr;
  323. }
  324. /* I N I T I A L I Z E */
  325. /*-------------------------------------------------------------------------
  326. %%Function: Initialize
  327. REVIEW: What should the return value be if any of these parts fail
  328. to initialize or load?
  329. -------------------------------------------------------------------------*/
  330. HRESULT COprahNCUI::Initialize
  331. (
  332. BSTR szName,
  333. DWORD_PTR dwCredentials,
  334. DWORD port,
  335. DWORD flags
  336. )
  337. {
  338. HRESULT hr = S_OK;
  339. ASSERT(!m_bstrUserName);
  340. SysFreeString(m_bstrUserName);
  341. m_bstrUserName = SysAllocString(szName);
  342. m_pOutgoingCallManager = new COutgoingCallManager;
  343. if (!m_pOutgoingCallManager)
  344. {
  345. ERROR_OUT(("COprahNCUI::Initialize -- failed to create outgoing call mgr"));
  346. return(E_OUTOFMEMORY);
  347. }
  348. m_pIncomingCallManager = new CIncomingCallManager;
  349. if (!m_pIncomingCallManager)
  350. {
  351. ERROR_OUT(("COprahNCUI::Initialize -- failed to create incoming call mgr"));
  352. return(E_OUTOFMEMORY);
  353. }
  354. // The lifetime of this object is up to the reference counting crap
  355. m_pConfObject = new CConfObject;
  356. if (!m_pConfObject)
  357. {
  358. ERROR_OUT(("COprahNCUI::Initialize -- failed to create conf object"));
  359. return(E_OUTOFMEMORY);
  360. }
  361. m_pConfObject->Init();
  362. //
  363. // Create the node controller
  364. //
  365. ASSERT(port == DEFAULT_LISTEN_PORT);
  366. hr = ::T120_CreateNodeController(&g_pNodeController, this, szName,
  367. dwCredentials, flags);
  368. if (FAILED(hr))
  369. {
  370. ERROR_OUT(("T120_CreateNodeController() failed!"));
  371. }
  372. return hr;
  373. }
  374. HRESULT COprahNCUI::Call
  375. (
  376. INmCall **ppCall,
  377. DWORD dwFlags,
  378. NM_ADDR_TYPE addrType,
  379. BSTR bstrAddr,
  380. BSTR bstrConference,
  381. BSTR bstrPassword
  382. )
  383. {
  384. BSTR bstrRealAddr;
  385. DebugEntry(COprahNCUI::Call);
  386. if (addrType == NM_ADDR_MACHINENAME)
  387. {
  388. //
  389. // Convert to IP Address
  390. //
  391. int cch;
  392. TCHAR * pszOemName;
  393. ULONG ulIpAddress;
  394. HOSTENT * pHostEnt;
  395. WCHAR * pwszName;
  396. cch = SysStringLen(bstrAddr);
  397. pszOemName = new TCHAR[cch + 1];
  398. if (!pszOemName)
  399. {
  400. ERROR_OUT(("Couldn't get OEM Name"));
  401. return E_OUTOFMEMORY;
  402. }
  403. WideCharToMultiByte(CP_ACP, 0, bstrAddr, -1, pszOemName, cch+1, NULL,
  404. NULL);
  405. CharUpper(pszOemName);
  406. CharToOem(pszOemName, pszOemName);
  407. pHostEnt = gethostbyname(pszOemName);
  408. if (!pHostEnt ||
  409. (pHostEnt->h_addrtype != AF_INET) ||
  410. (pHostEnt->h_length != sizeof(ULONG)) ||
  411. (pHostEnt->h_addr_list[0] == NULL))
  412. {
  413. ulIpAddress = 0;
  414. WARNING_OUT(("gethostbyname failed"));
  415. }
  416. else
  417. {
  418. ulIpAddress = *reinterpret_cast<ULONG *>(pHostEnt->h_addr_list[0]);
  419. }
  420. delete pszOemName;
  421. if (!ulIpAddress)
  422. {
  423. ERROR_OUT(("gethostbyname failed, returning"));
  424. return E_FAIL;
  425. }
  426. pszOemName = inet_ntoa(*reinterpret_cast<in_addr *>(&ulIpAddress));
  427. cch = lstrlen(pszOemName);
  428. pwszName = new WCHAR[cch + 1];
  429. if (!pwszName)
  430. {
  431. ERROR_OUT(("Can't alloc OLE string"));
  432. return E_OUTOFMEMORY;
  433. }
  434. MultiByteToWideChar(CP_ACP, 0, pszOemName, -1, pwszName, cch+1);
  435. bstrRealAddr = SysAllocString(pwszName);
  436. delete pwszName;
  437. }
  438. else if (addrType == NM_ADDR_IP)
  439. {
  440. bstrRealAddr = SysAllocString(bstrAddr);
  441. }
  442. else
  443. {
  444. ERROR_OUT(("INmManager::Call - bogus addrType %d", addrType));
  445. return E_FAIL;
  446. }
  447. HRESULT hr = m_pOutgoingCallManager->Call( ppCall,
  448. this,
  449. dwFlags,
  450. addrType,
  451. bstrRealAddr,
  452. bstrConference,
  453. bstrPassword);
  454. SysFreeString(bstrRealAddr);
  455. DebugExitHRESULT(COprahNCUI::Call, hr);
  456. return hr;
  457. }
  458. HRESULT COprahNCUI::CreateConference
  459. (
  460. INmConference **ppConference,
  461. BSTR bstrName,
  462. BSTR bstrPassword,
  463. BOOL fSecure
  464. )
  465. {
  466. if (NULL == ppConference)
  467. {
  468. ERROR_OUT(("CreateConferenceEx: null ppConference passed in"));
  469. return E_POINTER;
  470. }
  471. if (m_pConfObject->IsConferenceActive())
  472. {
  473. WARNING_OUT(("CreateConference is failing because IsConferenceActive return TRUE"));
  474. return NM_CALLERR_IN_CONFERENCE;
  475. }
  476. m_pConfObject->SetConfName(bstrName);
  477. m_pConfObject->SetConfSecurity(fSecure);
  478. if (!m_pConfObject->IsConferenceCreated())
  479. {
  480. m_pConfObject->OnConferenceCreated();
  481. }
  482. NotifySink((INmConference*) m_pConfObject, OnNotifyConferenceCreated);
  483. *ppConference = m_pConfObject;
  484. if(*ppConference)
  485. {
  486. (*ppConference)->AddRef();
  487. }
  488. return S_OK;
  489. }
  490. /* O N N O T I F Y C O N F E R E N C E C R E A T E D */
  491. /*-------------------------------------------------------------------------
  492. %%Function: OnNotifyConferenceCreated
  493. -------------------------------------------------------------------------*/
  494. HRESULT OnNotifyConferenceCreated(IUnknown *pManagerNotify, PVOID pv, REFIID riid)
  495. {
  496. ASSERT(NULL != pManagerNotify);
  497. ((INmManagerNotify*)pManagerNotify)->ConferenceCreated((INmConference *) pv);
  498. return S_OK;
  499. }
  500. /* O N N O T I F Y C A L L C R E A T E D */
  501. /*-------------------------------------------------------------------------
  502. %%Function: OnNotifyCallCreated
  503. -------------------------------------------------------------------------*/
  504. HRESULT OnNotifyCallCreated(IUnknown *pManagerNotify, PVOID pv, REFIID riid)
  505. {
  506. ASSERT(NULL != pManagerNotify);
  507. ((INmManagerNotify*)pManagerNotify)->CallCreated((INmCall *) pv);
  508. return S_OK;
  509. }
  510. /* O N N O T I F Y C A L L S T A T E C H A N G E D */
  511. /*-------------------------------------------------------------------------
  512. %%Function: OnNotifyCallStateChanged
  513. -------------------------------------------------------------------------*/
  514. HRESULT OnNotifyCallStateChanged(IUnknown *pCallNotify, PVOID pv, REFIID riid)
  515. {
  516. ASSERT(NULL != pCallNotify);
  517. ((INmCallNotify*)pCallNotify)->StateChanged((NM_CALL_STATE)(DWORD_PTR)pv);
  518. return S_OK;
  519. }
  520. HRESULT WINAPI CreateNmManager(INmManager ** ppMan)
  521. {
  522. if (!ppMan)
  523. return E_POINTER;
  524. COprahNCUI *pManager = new COprahNCUI();
  525. if (!pManager)
  526. return E_OUTOFMEMORY;
  527. *ppMan = (INmManager *)pManager;
  528. return S_OK;
  529. }