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.

2094 lines
70 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* ERNCCM.CPP */
  4. /* */
  5. /* Conference Manager class for the Reference System Node Controller. */
  6. /* */
  7. /* Copyright Data Connection Ltd. 1995 */
  8. /* */
  9. /****************************************************************************/
  10. /* Changes: */
  11. /* */
  12. /* 07Jul95 NFC Created. */
  13. /* 23Aug95 NFC Bad trace in StartConference(). */
  14. /* 05Sep95 NFC Integration with CMP_Notify* API. */
  15. /* 13Sep95 NFC Added handler for GCC_EJECT_USER_INDICATION */
  16. /* 19Sep95 NFC Missing break in GetConfIDFromMessage(). */
  17. /****************************************************************************/
  18. #include "precomp.h"
  19. DEBUG_FILEZONE(ZONE_GCC_NC);
  20. #include "ernccons.h"
  21. #include "nccglbl.hpp"
  22. #include "erncvrsn.hpp"
  23. #include "t120app.h"
  24. #include <cuserdta.hpp>
  25. #include <confreg.h>
  26. #include "erncconf.hpp"
  27. #include "ernccm.hpp"
  28. #include "ernctrc.h"
  29. #include <time.h>
  30. #include <string.h>
  31. #include "plgxprt.h"
  32. #include <service.h>
  33. #ifdef _DEBUG
  34. BOOL g_fInterfaceBreak = FALSE;
  35. #endif
  36. #define MAX_INVALID_PASSWORDS 5
  37. // Global data structures.
  38. DCRNCConferenceManager *g_pNCConfMgr = NULL;
  39. CQueryRemoteWorkList *g_pQueryRemoteList = NULL;
  40. INodeControllerEvents *g_pCallbackInterface = NULL;
  41. HINSTANCE g_hDllInst = NULL;
  42. IT120ControlSAP *g_pIT120ControlSap = NULL;
  43. BOOL g_bRDS = FALSE;
  44. extern PController g_pMCSController;
  45. extern PTransportInterface g_Transport;
  46. // Private function prototypes.
  47. void HandleAddInd(AddIndicationMessage * pAddInd);
  48. void HandleQueryConfirmation(QueryConfirmMessage * pQueryMessage);
  49. void HandleQueryIndication(QueryIndicationMessage * pQueryMessage);
  50. void HandleConductGiveInd(ConductGiveIndicationMessage * pConductGiveInd);
  51. void HandleLockIndication(LockIndicationMessage * pLockInd);
  52. void HandleUnlockIndication(UnlockIndicationMessage * pUnlockInd);
  53. void HandleSubInitializedInd(SubInitializedIndicationMessage * pSubInitInd);
  54. void HandleTimeInquireIndication(TimeInquireIndicationMessage * pTimeInquireInd);
  55. void HandleApplicationInvokeIndication(ApplicationInvokeIndicationMessage * pInvokeMessage);
  56. BOOL InitializePluggableTransport(void);
  57. void CleanupPluggableTransport(void);
  58. BOOL WINAPI DllMain(HINSTANCE hDllInst, DWORD fdwReason, LPVOID)
  59. {
  60. switch (fdwReason)
  61. {
  62. case DLL_PROCESS_ATTACH:
  63. {
  64. g_hDllInst = hDllInst;
  65. ASSERT (g_hDllInst != NULL);
  66. DisableThreadLibraryCalls (hDllInst);
  67. DBG_INIT_MEMORY_TRACKING(hDllInst);
  68. ::InitializeCriticalSection(&g_csTransport);
  69. T120DiagnosticCreate();
  70. break;
  71. }
  72. case DLL_PROCESS_DETACH:
  73. {
  74. g_hDllInst = NULL;
  75. /*
  76. * Go cleanup all resources on behalf of the process that is
  77. * detaching from this DLL.
  78. */
  79. T120DiagnosticDestroy ();
  80. ::DeleteCriticalSection(&g_csTransport);
  81. DBG_CHECK_MEMORY_TRACKING(hDllInst);
  82. break;
  83. }
  84. }
  85. return (TRUE);
  86. }
  87. HRESULT WINAPI
  88. T120_CreateNodeController
  89. (
  90. INodeController **ppNodeCtrlIntf,
  91. INodeControllerEvents *pEventsCallback,
  92. BSTR szName,
  93. DWORD_PTR dwCredentials,
  94. DWORD flags
  95. )
  96. {
  97. DebugEntry(T120_CreateNodeController);
  98. HRESULT hr;
  99. ASSERT(ppNodeCtrlIntf);
  100. ASSERT(pEventsCallback);
  101. if (NULL == g_pNCConfMgr)
  102. {
  103. *ppNodeCtrlIntf = NULL;
  104. g_bRDS = ((flags & NMMANAGER_SERVICE) != 0);
  105. DBG_SAVE_FILE_LINE
  106. if (NULL != (g_pNCConfMgr = new DCRNCConferenceManager(pEventsCallback, szName, &hr)))
  107. {
  108. if (S_OK == hr)
  109. {
  110. *ppNodeCtrlIntf = (INodeController*) g_pNCConfMgr;
  111. ASSERT(g_Transport);
  112. //
  113. // Security. Create transport interface if we don't have one.
  114. // Update credentials if we do.
  115. //
  116. if (!g_Transport->pSecurityInterface)
  117. {
  118. g_Transport->pSecurityInterface = new SecurityInterface();
  119. if ( TPRTSEC_NOERROR !=
  120. g_Transport->pSecurityInterface->Initialize())
  121. {
  122. delete g_Transport->pSecurityInterface;
  123. g_Transport->pSecurityInterface = NULL;
  124. }
  125. }
  126. else
  127. {
  128. g_Transport->pSecurityInterface->
  129. InitializeCreds((PCCERT_CONTEXT)dwCredentials);
  130. }
  131. }
  132. else
  133. {
  134. g_pNCConfMgr->Release();
  135. }
  136. }
  137. else
  138. {
  139. hr = E_OUTOFMEMORY;
  140. }
  141. }
  142. else
  143. {
  144. hr = UI_RC_T120_ALREADY_INITIALIZED;
  145. }
  146. DebugExitHRESULT(T120_CreateNodeController, hr);
  147. return hr;
  148. }
  149. /****************************************************************************/
  150. /* Constructor - see ernccm.hpp */
  151. /****************************************************************************/
  152. DCRNCConferenceManager::
  153. DCRNCConferenceManager
  154. (
  155. INodeControllerEvents *pCallback,
  156. BSTR szUserName,
  157. HRESULT *pRetCode
  158. )
  159. :
  160. CRefCount(MAKE_STAMP_ID('N', 'C', 'C', 'M')),
  161. m_eState(CM_ST_UNINITIALIZED),
  162. m_bstrUserName(NULL)
  163. {
  164. GCCError GCCrc;
  165. HRESULT hr = NO_ERROR;
  166. DebugEntry(DCRNCConferenceManager::DCRNCConferenceManager);
  167. ::InitializePluggableTransport();
  168. //
  169. // There should be only one NC conference manager in the system.
  170. //
  171. ASSERT(NULL == g_pNCConfMgr);
  172. ASSERT(pRetCode);
  173. m_bstrUserName = SysAllocString(szUserName);
  174. //
  175. // Save the callback interface
  176. //
  177. g_pCallbackInterface = pCallback;
  178. //
  179. // Create the query-remote list.
  180. //
  181. ASSERT(NULL == g_pQueryRemoteList);
  182. DBG_SAVE_FILE_LINE
  183. g_pQueryRemoteList = new CQueryRemoteWorkList();
  184. if (g_pQueryRemoteList == NULL)
  185. {
  186. ERROR_OUT(("Failed to create Query Remote List"));
  187. hr = UI_RC_OUT_OF_MEMORY;
  188. goto MyExit;
  189. }
  190. /************************************************************************/
  191. /* For GCCInitialize: */
  192. /* */
  193. /* - pass in a pointer to CM as the user defined data, allowing */
  194. /* GCCCallBackHandler to call back into CM to handle GCC callbacks. */
  195. /************************************************************************/
  196. GCCrc = ::T120_CreateControlSAP(&g_pIT120ControlSap, this, GCCCallBackHandler);
  197. if (GCCrc == GCC_NO_ERROR)
  198. {
  199. m_eState = CM_ST_GCC_INITIALIZED;
  200. hr = NO_ERROR;
  201. }
  202. else
  203. {
  204. ERROR_OUT(("Failed to initializeGCC, GCC error %d", GCCrc));
  205. hr = ::GetGCCRCDetails(GCCrc);
  206. }
  207. MyExit:
  208. *pRetCode = hr;
  209. DebugExitHRESULT(DCRNCConferenceManager::DCRNCConferenceManager, hr);
  210. }
  211. /****************************************************************************/
  212. /* Destructor - see ernccm.hpp */
  213. /****************************************************************************/
  214. DCRNCConferenceManager::
  215. ~DCRNCConferenceManager(void)
  216. {
  217. DebugEntry(DCRNCConferenceManager::~DCRNCConferenceManager);
  218. //
  219. // Make sure no one can use this global pointer any more since
  220. // we are deleting this object.
  221. //
  222. g_pNCConfMgr = NULL;
  223. g_pCallbackInterface = NULL;
  224. //
  225. // Clean up the query-remote list
  226. //
  227. delete g_pQueryRemoteList;
  228. g_pQueryRemoteList = NULL;
  229. //
  230. // If we have initialized GCC, uninitialize it.
  231. //
  232. if (NULL != g_pIT120ControlSap)
  233. {
  234. ASSERT(CM_ST_GCC_INITIALIZED == m_eState);
  235. g_pIT120ControlSap->ReleaseInterface();
  236. g_pIT120ControlSap = NULL;
  237. }
  238. m_eState = CM_ST_UNINITIALIZED;
  239. if (m_bstrUserName)
  240. {
  241. SysFreeString(m_bstrUserName);
  242. m_bstrUserName = NULL;
  243. }
  244. ::CleanupPluggableTransport();
  245. DebugExitVOID(DCRNCConferenceManager::~DCRNCConferenceManager);
  246. }
  247. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  248. //
  249. // Implementation of INodeController interface
  250. //
  251. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  252. STDMETHODIMP_(void) DCRNCConferenceManager::
  253. ReleaseInterface ( void )
  254. {
  255. DebugEntry(DCRNCConferenceManager::ReleaseInterface);
  256. InterfaceEntry();
  257. //
  258. // End and delete all the conferences.
  259. //
  260. PCONFERENCE pConf;
  261. while (NULL != (pConf = m_ConfList.Get()))
  262. {
  263. RemoveConference(pConf, TRUE, TRUE);
  264. }
  265. //
  266. // Free the query remote list
  267. //
  268. g_pQueryRemoteList->DeleteList();
  269. //
  270. // Empty our sequential lists of entries without owners.
  271. //
  272. m_InviteIndWorkList.DeleteList();
  273. m_JoinIndWorkList.DeleteList();
  274. //
  275. // Reset the NC related data
  276. //
  277. g_pCallbackInterface = NULL;
  278. //
  279. // Release this object now.
  280. //
  281. Release();
  282. DebugExitVOID(DCRNCConferenceManager::ReleaseInterface);
  283. }
  284. STDMETHODIMP DCRNCConferenceManager::
  285. QueryRemote
  286. (
  287. LPVOID pCallerContext,
  288. LPCSTR pcszNodeAddress,
  289. BOOL fSecure,
  290. BOOL bIsConferenceActive
  291. )
  292. {
  293. DebugEntry(DCRNCConferenceManager::QueryRemote);
  294. InterfaceEntry();
  295. HRESULT hr;
  296. #if defined(TEST_PLUGGABLE) && defined(_DEBUG)
  297. if (g_fWinsockDisabled)
  298. {
  299. pcszNodeAddress = ::FakeNodeAddress(pcszNodeAddress);
  300. }
  301. #endif
  302. if (NULL != pcszNodeAddress)
  303. {
  304. // if winsock is disabled, block any IP address or machine name
  305. if (g_fWinsockDisabled)
  306. {
  307. if (! IsValidPluggableTransportName(pcszNodeAddress))
  308. {
  309. return UI_RC_NO_WINSOCK;
  310. }
  311. }
  312. // Construct context for the life of the request.
  313. DBG_SAVE_FILE_LINE
  314. CQueryRemoteWork *pQueryRemote;
  315. DBG_SAVE_FILE_LINE
  316. pQueryRemote = new CQueryRemoteWork(pCallerContext,
  317. bIsConferenceActive ? GCC_ASYMMETRY_CALLER : GCC_ASYMMETRY_UNKNOWN,
  318. // GCC_ASYMMETRY_CALLER, // lonchanc: always want to be the caller
  319. pcszNodeAddress,
  320. fSecure,
  321. &hr);
  322. if (NULL != pQueryRemote && NO_ERROR == hr)
  323. {
  324. //
  325. // LONCHANC: The following call is to put this query remote work item
  326. // to the global list, and do the work. We have to do this because
  327. // we removed the physical connection.
  328. //
  329. pQueryRemote->SetHr(NO_ERROR);
  330. // Put entry in list of pending query requests to
  331. // issue GCCConferenceQuery on connection.
  332. g_pQueryRemoteList->AddWorkItem(pQueryRemote);
  333. hr = NO_ERROR;
  334. }
  335. else
  336. {
  337. ERROR_OUT(("DCRNCConferenceManager::QueryRemote:: can't allocate query remote work item"));
  338. delete pQueryRemote;
  339. hr = UI_RC_OUT_OF_MEMORY;
  340. }
  341. }
  342. else
  343. {
  344. ERROR_OUT(("DCRNCConferenceManager::QueryRemote:: null pcszAddress"));
  345. hr = UI_RC_NO_ADDRESS;
  346. }
  347. DebugExitHRESULT(DCRNCConferenceManager::QueryRemote, hr);
  348. return hr;
  349. }
  350. STDMETHODIMP DCRNCConferenceManager::
  351. CancelQueryRemote ( LPVOID pCallerContext )
  352. {
  353. DebugEntry(DCRNCConferenceManager::CancelQueryRemote);
  354. InterfaceEntry();
  355. HRESULT hr = g_pQueryRemoteList->Cancel(pCallerContext);
  356. DebugExitHRESULT(DCRNCConferenceManager::CancelQueryRemote, hr);
  357. return hr;
  358. }
  359. STDMETHODIMP DCRNCConferenceManager::
  360. CreateConference
  361. (
  362. LPCWSTR pcwszConfName,
  363. LPCWSTR pcwszPassword,
  364. PBYTE pbHashedPassword,
  365. DWORD cbHashedPassword,
  366. BOOL fSecure,
  367. CONF_HANDLE *phConf
  368. )
  369. {
  370. DebugEntry(DCRNCConferenceManager::CreateConference);
  371. InterfaceEntry();
  372. HRESULT hr;
  373. if (NULL != phConf)
  374. {
  375. *phConf = NULL;
  376. if (! ::IsEmptyStringW(pcwszConfName))
  377. {
  378. PCONFERENCE pNewConf;
  379. /************************************************************************/
  380. /* Create a new conference. */
  381. /************************************************************************/
  382. hr = CreateNewConference(pcwszConfName, NULL, &pNewConf, FALSE, fSecure);
  383. if (NO_ERROR == hr)
  384. {
  385. ASSERT(NULL != pNewConf);
  386. /****************************************************************/
  387. /* Only need the name for a new local conference. */
  388. /****************************************************************/
  389. hr = pNewConf->StartLocal(pcwszPassword, pbHashedPassword, cbHashedPassword);
  390. if (NO_ERROR == hr)
  391. {
  392. pNewConf->SetNotifyToDo(TRUE);
  393. *phConf = (CONF_HANDLE) pNewConf;
  394. }
  395. else
  396. {
  397. ERROR_OUT(("DCRNCConferenceManager::CreateConference: can't start local conference, hr=0x%x", (UINT) hr));
  398. if (hr != UI_RC_CONFERENCE_ALREADY_EXISTS)
  399. {
  400. RemoveConference(pNewConf);
  401. }
  402. }
  403. }
  404. else
  405. {
  406. ERROR_OUT(("DCRNCConferenceManager::CreateConference: failed to create new conference, hr=0x%x", (UINT) hr));
  407. }
  408. }
  409. else
  410. {
  411. ERROR_OUT(("DCRNCConferenceManager::CreateConference: invalid conference name"));
  412. hr = UI_RC_NO_CONFERENCE_NAME;
  413. }
  414. }
  415. else
  416. {
  417. ERROR_OUT(("DCRNCConferenceManager::CreateConference: null phConf"));
  418. hr = UI_RC_BAD_PARAMETER;
  419. }
  420. DebugExitHRESULT(DCRNCConferenceManager::CreateConference, hr);
  421. return hr;
  422. }
  423. STDMETHODIMP DCRNCConferenceManager::
  424. JoinConference
  425. (
  426. LPCWSTR pcwszConfName,
  427. LPCWSTR pcwszPassword,
  428. LPCSTR pcszNodeAddress,
  429. BOOL fSecure,
  430. CONF_HANDLE *phConf
  431. )
  432. {
  433. DebugEntry(DCRNCConferenceManager::JoinConference);
  434. InterfaceEntry();
  435. HRESULT hr;
  436. #if defined(TEST_PLUGGABLE) && defined(_DEBUG)
  437. if (g_fWinsockDisabled)
  438. {
  439. pcszNodeAddress = ::FakeNodeAddress(pcszNodeAddress);
  440. }
  441. #endif
  442. if (NULL != phConf)
  443. {
  444. *phConf = NULL;
  445. if (! ::IsEmptyStringW(pcwszConfName) && NULL != pcszNodeAddress)
  446. {
  447. // if winsock is disabled, block any IP address or machine name
  448. if (g_fWinsockDisabled)
  449. {
  450. if (! IsValidPluggableTransportName(pcszNodeAddress))
  451. {
  452. return UI_RC_NO_WINSOCK;
  453. }
  454. }
  455. PCONFERENCE pNewConf;
  456. // Create a new conference, or find a new conference that
  457. // has just rejected a join because of an invalid password,
  458. // and call its Join() entry point.
  459. hr = CreateNewConference(pcwszConfName, NULL, &pNewConf, TRUE, fSecure);
  460. if (NO_ERROR == hr)
  461. {
  462. // First join attempt. Do all of the start connection.
  463. hr = pNewConf->Join((LPSTR) pcszNodeAddress,
  464. pcwszPassword);
  465. }
  466. else
  467. if (hr == UI_RC_CONFERENCE_ALREADY_EXISTS)
  468. {
  469. // Conference already exists.
  470. // Look to see if it is awaiting a join with a password.
  471. // If so, then retry the join.
  472. // Otherwise drop through to return an error.
  473. // Note that we walk the list here again to find the existing
  474. // conference rather than pass back from CreateNewConference(),
  475. // because that would be a side effect behavior that can (and has!)
  476. // introduce obscure bugs in unrelated code.
  477. hr = NO_ERROR;
  478. pNewConf = GetConferenceFromName(pcwszConfName);
  479. ASSERT(NULL != pNewConf);
  480. if (! pNewConf->IsConnListEmpty())
  481. {
  482. CLogicalConnection *pConEntry = pNewConf->PeekConnListHead();
  483. if (pConEntry->GetState() == CONF_CON_PENDING_PASSWORD)
  484. {
  485. hr = pNewConf->JoinWrapper(pConEntry, pcwszPassword);
  486. }
  487. }
  488. }
  489. // Delete the conference if the join fails
  490. // for any reason other than trying to join
  491. // a local conference.
  492. if (NO_ERROR == hr)
  493. {
  494. pNewConf->SetNotifyToDo(TRUE);
  495. *phConf = (CONF_HANDLE) pNewConf;
  496. }
  497. else
  498. {
  499. if (hr != UI_RC_CONFERENCE_ALREADY_EXISTS)
  500. {
  501. ERROR_OUT(("DCRNCConferenceManager::JoinConference: Failed to create new conference, hr=0x%x", (UINT) hr));
  502. }
  503. RemoveConference(pNewConf);
  504. }
  505. }
  506. else
  507. {
  508. hr = (pcszNodeAddress == NULL) ? UI_RC_NO_ADDRESS : UI_RC_NO_CONFERENCE_NAME;
  509. ERROR_OUT(("DCRNCConferenceManager::JoinConference: invalid parameters, hr=0x%x", (UINT) hr));
  510. }
  511. }
  512. else
  513. {
  514. ERROR_OUT(("DCRNCConferenceManager::JoinConference: null phConf"));
  515. hr = UI_RC_BAD_PARAMETER;
  516. }
  517. DebugExitHRESULT(DCRNCConferenceManager::JoinConference, hr);
  518. return hr;
  519. }
  520. STDMETHODIMP_(UINT) DCRNCConferenceManager::
  521. GetPluggableConnID
  522. (
  523. LPCSTR pcszNodeAddress
  524. )
  525. {
  526. return ::GetPluggableTransportConnID(pcszNodeAddress);
  527. }
  528. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  529. //
  530. // Implementation of Methods for DCRNCConferenceManager
  531. //
  532. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  533. void DCRNCConferenceManager::
  534. WndMsgHandler(UINT uMsg, LPARAM lParam)
  535. {
  536. DebugEntry(DCRNCConferenceManager::WndMsgHandler);
  537. TRACE_OUT(("DCRNCConferenceManager::WndMsgHandler: uMsg=%u, lParam=0x%x", (UINT) uMsg, (UINT) lParam));
  538. switch (uMsg)
  539. {
  540. case NCMSG_FIRST_ROSTER_RECVD:
  541. {
  542. PCONFERENCE pConf = (PCONFERENCE) lParam;
  543. if (NULL != pConf)
  544. {
  545. pConf->FirstRoster();
  546. }
  547. }
  548. break;
  549. case NCMSG_QUERY_REMOTE_FAILURE:
  550. {
  551. CQueryRemoteWork *pWork = (CQueryRemoteWork *) lParam;
  552. if (NULL != pWork)
  553. {
  554. pWork->SyncQueryRemoteResult();
  555. }
  556. }
  557. break;
  558. default:
  559. ERROR_OUT(("DCRNCConferenceManager::WndMsgHandler: unknown msg=%u, lParam=0x%x", uMsg, (UINT) lParam));
  560. break;
  561. }
  562. DebugExitVOID(DCRNCConferenceManager::WndMsgHandler);
  563. }
  564. /****************************************************************************/
  565. /* CreateNewConference - create a new instance of DCRNCConference and add */
  566. /* it to the conference list. */
  567. /****************************************************************************/
  568. HRESULT DCRNCConferenceManager::
  569. CreateNewConference
  570. (
  571. LPCWSTR pcwszConfName,
  572. GCCConfID nConfID,
  573. PCONFERENCE *ppConf,
  574. BOOL fFindExistingConf,
  575. BOOL fSecure
  576. )
  577. {
  578. HRESULT hr;
  579. DebugEntry(DCRNCConferenceManager::CreateNewConference);
  580. ASSERT(ppConf);
  581. // Make sure there is not already an active conference of the same name.
  582. PCONFERENCE pConf = GetConferenceFromName(pcwszConfName);
  583. if (NULL == pConf)
  584. {
  585. // Add new conference
  586. DBG_SAVE_FILE_LINE
  587. pConf = new DCRNCConference(pcwszConfName, nConfID, fSecure, &hr);
  588. if (NULL != pConf && NO_ERROR == hr)
  589. {
  590. // Conference added, so include in list.
  591. m_ConfList.Append(pConf);
  592. #ifdef _DEBUG
  593. pConf->OnAppended();
  594. #endif
  595. // This reference is for nmcom.dll so that ReleaseInterface will do
  596. // the right thing.
  597. pConf->AddRef();
  598. }
  599. else
  600. {
  601. ERROR_OUT(("DCRNCConferenceManager::CreateNewConference: can't create conf, hr=0x%x, pConf=0x%p", (UINT) hr, pConf));
  602. if (pConf == NULL)
  603. {
  604. hr = UI_RC_OUT_OF_MEMORY;
  605. }
  606. else
  607. {
  608. pConf->Release();
  609. pConf = NULL;
  610. }
  611. }
  612. *ppConf = pConf;
  613. }
  614. else
  615. {
  616. WARNING_OUT(("DCRNCConferenceManager::CreateNewConference: conf already exists"));
  617. hr = UI_RC_CONFERENCE_ALREADY_EXISTS;
  618. *ppConf = fFindExistingConf ? pConf : NULL;
  619. }
  620. DebugExitHRESULT(DCRNCConferenceManager::CreateNewConference, hr);
  621. return hr;
  622. }
  623. /***************************************************************************/
  624. /* GetConfIDFromMessage() - Get the conference ID from the message. */
  625. /***************************************************************************/
  626. GCCConfID GetConfIDFromMessage ( GCCMessage * pGCCMessage )
  627. {
  628. GCCConfID nConfID = pGCCMessage->nConfID;
  629. #ifdef _DEBUG
  630. /************************************************************************/
  631. /* Dig the conference ID out of the message. */
  632. /************************************************************************/
  633. switch (pGCCMessage->message_type)
  634. {
  635. case GCC_CREATE_INDICATION:
  636. // nConfID = pGCCMessage->u.create_indication.conference_id;
  637. break;
  638. case GCC_CREATE_CONFIRM:
  639. // nConfID = pGCCMessage->u.create_confirm.conference_id;
  640. break;
  641. case GCC_JOIN_CONFIRM:
  642. // nConfID = pGCCMessage->u.join_confirm.conference_id;
  643. break;
  644. case GCC_INVITE_CONFIRM:
  645. // nConfID = pGCCMessage->u.invite_confirm.conference_id;
  646. break;
  647. case GCC_ADD_CONFIRM:
  648. // nConfID = pGCCMessage->u.add_confirm.conference_id;
  649. break;
  650. case GCC_DISCONNECT_INDICATION:
  651. // nConfID = pGCCMessage->u.disconnect_indication.conference_id;
  652. break;
  653. case GCC_DISCONNECT_CONFIRM:
  654. // nConfID = pGCCMessage->u.disconnect_confirm.conference_id;
  655. break;
  656. case GCC_TERMINATE_INDICATION:
  657. // nConfID = pGCCMessage->u.terminate_indication.conference_id;
  658. break;
  659. case GCC_TERMINATE_CONFIRM:
  660. // nConfID = pGCCMessage->u.terminate_confirm.conference_id;
  661. break;
  662. case GCC_ANNOUNCE_PRESENCE_CONFIRM:
  663. // nConfID = pGCCMessage->u.announce_presence_confirm.conference_id;
  664. break;
  665. case GCC_ROSTER_REPORT_INDICATION:
  666. // nConfID = pGCCMessage->u.conf_roster_report_indication.conference_id;
  667. break;
  668. case GCC_ROSTER_INQUIRE_CONFIRM:
  669. // nConfID = pGCCMessage->u.conf_roster_inquire_confirm.conference_id;
  670. break;
  671. case GCC_PERMIT_TO_ANNOUNCE_PRESENCE:
  672. // nConfID = pGCCMessage->u.permit_to_announce_presence.conference_id;
  673. break;
  674. case GCC_EJECT_USER_INDICATION:
  675. // nConfID = pGCCMessage->u.eject_user_indication.conference_id;
  676. break;
  677. default :
  678. // nConfID = 0;
  679. ERROR_OUT(("Unknown message"));
  680. break;
  681. }
  682. #endif // _DEBUG
  683. return nConfID;
  684. }
  685. PCONFERENCE DCRNCConferenceManager::
  686. GetConferenceFromID ( GCCConfID conferenceID )
  687. {
  688. PCONFERENCE pConf = NULL;
  689. m_ConfList.Reset();
  690. while (NULL != (pConf = m_ConfList.Iterate()))
  691. {
  692. if (pConf->GetID() == conferenceID)
  693. {
  694. break;
  695. }
  696. }
  697. return pConf;
  698. }
  699. PCONFERENCE DCRNCConferenceManager::
  700. GetConferenceFromName ( LPCWSTR pcwszConfName )
  701. {
  702. PCONFERENCE pConf = NULL;
  703. if (! ::IsEmptyStringW(pcwszConfName))
  704. {
  705. m_ConfList.Reset();
  706. while (NULL != (pConf = m_ConfList.Iterate()))
  707. {
  708. if ((0 == ::My_strcmpW(pConf->GetName(), pcwszConfName)) &&
  709. (pConf->IsActive()))
  710. {
  711. break;
  712. }
  713. }
  714. }
  715. return pConf;
  716. }
  717. // GetConferenceFromNumber - get the T120 conference with the specified number.
  718. PCONFERENCE DCRNCConferenceManager::
  719. GetConferenceFromNumber ( GCCNumericString NumericName )
  720. {
  721. PCONFERENCE pConf = NULL;
  722. if (! ::IsEmptyStringA(NumericName))
  723. {
  724. m_ConfList.Reset();
  725. while (NULL != (pConf = m_ConfList.Iterate()))
  726. {
  727. LPSTR pszConfNumericName = pConf->GetNumericName();
  728. if (NULL != pszConfNumericName &&
  729. 0 == ::lstrcmpA(pszConfNumericName, NumericName))
  730. {
  731. break;
  732. }
  733. }
  734. }
  735. return pConf;
  736. }
  737. /****************************************************************************/
  738. /* Handle a GCC callback. */
  739. /****************************************************************************/
  740. void DCRNCConferenceManager::
  741. HandleGCCCallback ( GCCMessage * pGCCMessage )
  742. {
  743. DebugEntry(DCRNCConferenceManager::HandleGCCCallback);
  744. TRACE_OUT(("DCRNCConferenceManager::HandleGCCCallback: msg_type=%u", (UINT) pGCCMessage->message_type));
  745. switch (pGCCMessage->message_type)
  746. {
  747. case GCC_CREATE_CONFIRM:
  748. {
  749. PCONFERENCE pConf;
  750. LPWSTR pwszConfName;
  751. // For create confirm, the conference won't
  752. // know its ID yet (it is contained in this message), so get
  753. // the conference by name.
  754. if (NO_ERROR == ::GetUnicodeFromGCC(
  755. pGCCMessage->u.create_confirm.conference_name.numeric_string,
  756. pGCCMessage->u.create_confirm.conference_name.text_string,
  757. &pwszConfName))
  758. {
  759. pConf = GetConferenceFromName(pwszConfName);
  760. if (NULL != pConf)
  761. {
  762. pConf->HandleGCCCallback(pGCCMessage);
  763. }
  764. delete pwszConfName;
  765. }
  766. }
  767. break;
  768. case GCC_JOIN_CONFIRM:
  769. HandleJoinConfirm(&(pGCCMessage->u.join_confirm));
  770. break;
  771. case GCC_CONDUCT_GIVE_INDICATION:
  772. HandleConductGiveInd(&(pGCCMessage->u.conduct_give_indication));
  773. break;
  774. case GCC_JOIN_INDICATION:
  775. HandleJoinInd(&(pGCCMessage->u.join_indication));
  776. break;
  777. case GCC_ADD_INDICATION:
  778. HandleAddInd(&(pGCCMessage->u.add_indication));
  779. break;
  780. case GCC_SUB_INITIALIZED_INDICATION:
  781. HandleSubInitializedInd(&(pGCCMessage->u.conf_sub_initialized_indication));
  782. break;
  783. case GCC_ROSTER_REPORT_INDICATION:
  784. // update the (node id, name) list and user data
  785. UpdateNodeIdNameListAndUserData(pGCCMessage);
  786. // fall through
  787. case GCC_INVITE_CONFIRM:
  788. case GCC_ADD_CONFIRM:
  789. case GCC_DISCONNECT_INDICATION:
  790. case GCC_DISCONNECT_CONFIRM:
  791. case GCC_TERMINATE_INDICATION:
  792. case GCC_TERMINATE_CONFIRM:
  793. case GCC_ANNOUNCE_PRESENCE_CONFIRM:
  794. case GCC_ROSTER_INQUIRE_CONFIRM:
  795. case GCC_PERMIT_TO_ANNOUNCE_PRESENCE:
  796. case GCC_EJECT_USER_INDICATION:
  797. {
  798. /****************************************************************/
  799. /* All these events are passed straight onto one of our */
  800. /* conferences. */
  801. /****************************************************************/
  802. /****************************************************************/
  803. /* Get the conference ID from the message */
  804. /****************************************************************/
  805. GCCConfID nConfID = ::GetConfIDFromMessage(pGCCMessage);
  806. /****************************************************************/
  807. /* See whether we have a conference with this ID; */
  808. /****************************************************************/
  809. PCONFERENCE pConf = GetConferenceFromID(nConfID);
  810. if (NULL != pConf)
  811. {
  812. /****************************************************************/
  813. /* Pass the event onto the conference. */
  814. /****************************************************************/
  815. pConf->HandleGCCCallback(pGCCMessage);
  816. }
  817. else
  818. {
  819. // bugbug: should still reply to indications that require a response.
  820. TRACE_OUT(("DCRNCConferenceManager::HandleGCCCallback: No conference found with ID %d", nConfID));
  821. }
  822. }
  823. break;
  824. #ifdef TSTATUS_INDICATION
  825. case GCC_TRANSPORT_STATUS_INDICATION:
  826. {
  827. WORD state = 0;
  828. TRACE_OUT(("DCRNCConferenceManager::HandleGCCCallback: GCC msg type GCC_TRANSPORT_STATUS_INDICATION"));
  829. TRACE_OUT(("Device identifier '%s'",
  830. pGCCMessage->u.transport_status.device_identifier));
  831. TRACE_OUT(("Remote address '%s'",
  832. pGCCMessage->u.transport_status.remote_address));
  833. TRACE_OUT(("Message '%s'",
  834. pGCCMessage->u.transport_status.message));
  835. state = pGCCMessage->u.transport_status.state;
  836. #ifdef DEBUG
  837. LPSTR stateString =
  838. (state == TSTATE_NOT_READY ? "TSTATE_NOT_READY" :
  839. (state == TSTATE_NOT_CONNECTED ? "TSTATE_NOT_CONNECTED" :
  840. (state == TSTATE_CONNECT_PENDING ? "TSTATE_CONNECT_PENDING" :
  841. (state == TSTATE_CONNECTED ? "TSTATE_CONNECTED" :
  842. (state == TSTATE_REMOVED ? "TSTATE_REMOVED" :
  843. ("UNKNOWN STATE"))))));
  844. TRACE_OUT(("DCRNCConferenceManager::HandleGCCCallback: Transport state %d (%s)",
  845. pGCCMessage->u.transport_status.state,
  846. (const char *)stateString));
  847. #endif // DEBUG
  848. }
  849. break;
  850. case GCC_STATUS_INDICATION:
  851. {
  852. WORD state = 0;
  853. #ifdef DEBUG
  854. LPSTR stateString =
  855. (state == GCC_STATUS_PACKET_RESOURCE_FAILURE ? "GCC_STATUS_PACKET_RESOURCE_FAILURE " :
  856. (state == GCC_STATUS_PACKET_LENGTH_EXCEEDED ? "GCC_STATUS_PACKET_LENGTH_EXCEEDED " :
  857. (state == GCC_STATUS_CTL_SAP_RESOURCE_ERROR ? "GCC_STATUS_CTL_SAP_RESOURCE_ERROR " :
  858. (state == GCC_STATUS_APP_SAP_RESOURCE_ERROR ? "GCC_STATUS_APP_SAP_RESOURCE_ERROR " :
  859. (state == GCC_STATUS_CONF_RESOURCE_ERROR ? "GCC_STATUS_CONF_RESOURCE_ERROR " :
  860. (state == GCC_STATUS_INCOMPATIBLE_PROTOCOL ? "GCC_STATUS_INCOMPATIBLE_PROTOCOL " :
  861. (state == GCC_STATUS_JOIN_FAILED_BAD_CONF_NAME ? "GCC_STATUS_JOIN_FAILED_BAD_CONF_NAME" :
  862. (state == GCC_STATUS_JOIN_FAILED_BAD_CONVENER ? "GCC_STATUS_JOIN_FAILED_BAD_CONVENER " :
  863. (state == GCC_STATUS_JOIN_FAILED_LOCKED ? "GCC_STATUS_JOIN_FAILED_LOCKED " :
  864. ("UNKNOWN STATUS"))))))))));
  865. TRACE_OUT(("DCRNCConferenceManager::HandleGCCCallback: GCC_STATUS_INDICATION, type %d (%s)",
  866. pGCCMessage->u.status_indication.status_message_type,
  867. (const char *)stateString));
  868. #endif // DEBUG
  869. }
  870. break;
  871. #endif // TSTATUS_INDICATION
  872. case GCC_INVITE_INDICATION:
  873. /****************************************************************/
  874. /* We have been invited into a conference: Create a new */
  875. /* (incoming) conference. */
  876. /****************************************************************/
  877. HandleInviteIndication(&(pGCCMessage->u.invite_indication));
  878. break;
  879. case GCC_CREATE_INDICATION:
  880. /****************************************************************/
  881. /* A new conference has been created. */
  882. /****************************************************************/
  883. HandleCreateIndication(&(pGCCMessage->u.create_indication));
  884. break;
  885. case GCC_QUERY_CONFIRM:
  886. HandleQueryConfirmation(&(pGCCMessage->u.query_confirm));
  887. break;
  888. case GCC_QUERY_INDICATION:
  889. HandleQueryIndication(&(pGCCMessage->u.query_indication));
  890. break;
  891. case GCC_CONNECTION_BROKEN_INDICATION:
  892. BroadcastGCCCallback(pGCCMessage);
  893. break;
  894. case GCC_LOCK_INDICATION:
  895. HandleLockIndication(&(pGCCMessage->u.lock_indication));
  896. break;
  897. // case GCC_APPLICATION_INVOKE_CONFIRM:
  898. // This just indicates the g_pIT120ControlSap->AppletInvokeRequest succeeded.
  899. // There is no official confirmation from the remote machine.
  900. // FUTURE: Add protocol + code to respond to the launch request.
  901. // break;
  902. case GCC_APPLICATION_INVOKE_INDICATION:
  903. HandleApplicationInvokeIndication(&(pGCCMessage->u.application_invoke_indication));
  904. break;
  905. case GCC_UNLOCK_INDICATION:
  906. HandleUnlockIndication(&(pGCCMessage->u.unlock_indication));
  907. break;
  908. case GCC_TIME_INQUIRE_INDICATION:
  909. HandleTimeInquireIndication(&(pGCCMessage->u.time_inquire_indication));
  910. break;
  911. #ifdef DEBUG
  912. case GCC_APP_ROSTER_REPORT_INDICATION:
  913. TRACE_OUT(("DCRNCConferenceManager::HandleGCCCallback: GCC msg type GCC_APP_ROSTER_REPORT_INDICATION"));
  914. break;
  915. #endif /* DEBUG */
  916. default :
  917. /****************************************************************/
  918. /* This should be an exhaustive list of all the events we dont */
  919. /* handle: */
  920. /* */
  921. /* GCC_TEXT_MESSAGE_INDICATION */
  922. /* GCC_TIME_REMAINING_INDICATION */
  923. /* */
  924. /* GCC_ALLOCATE_HANDLE_CONFIRM */
  925. /* GCC_APP_ROSTER_INQUIRE_CONFIRM */
  926. /* GCC_ASSIGN_TOKEN_CONFIRM */
  927. /* GCC_ASSISTANCE_CONFIRM */
  928. /* GCC_ASSISTANCE_INDICATION */
  929. /* GCC_CONDUCT_ASK_CONFIRM */
  930. /* GCC_CONDUCT_ASK_INDICATION */
  931. /* GCC_CONDUCT_ASSIGN_CONFIRM */
  932. /* GCC_CONDUCT_ASSIGN_INDICATION */
  933. /* GCC_CONDUCT_GIVE_CONFIRM */
  934. /* GCC_CONDUCT_GRANT_CONFIRM */
  935. /* GCC_CONDUCT_GRANT_INDICATION */
  936. /* GCC_CONDUCT_INQUIRE_CONFIRM */
  937. /* GCC_CONDUCT_PLEASE_CONFIRM */
  938. /* GCC_CONDUCT_PLEASE_INDICATION */
  939. /* GCC_CONDUCT_RELEASE_CONFIRM */
  940. /* GCC_CONDUCT_RELEASE_INDICATION */
  941. /* GCC_CONFERENCE_EXTEND_CONFIRM */
  942. /* GCC_CONFERENCE_EXTEND_INDICATION */
  943. /* GCC_DELETE_ENTRY_CONFIRM */
  944. /* GCC_EJECT_USER_CONFIRM */
  945. /* GCC_ENROLL_CONFIRM */
  946. /* GCC_LOCK_CONFIRM */
  947. /* GCC_LOCK_REPORT_INDICATION */
  948. /* GCC_MONITOR_CONFIRM */
  949. /* GCC_MONITOR_INDICATION */
  950. /* GCC_PERMIT_TO_ENROLL_INDICATION: */
  951. /* GCC_REGISTER_CHANNEL_CONFIRM */
  952. /* GCC_RETRIEVE_ENTRY_CONFIRM */
  953. /* GCC_SET_PARAMETER_CONFIRM */
  954. /* GCC_TEXT_MESSAGE_CONFIRM */
  955. /* GCC_TIME_INQUIRE_CONFIRM */
  956. /* GCC_TIME_REMAINING_CONFIRM */
  957. /* GCC_TRANSFER_CONFIRM */
  958. /* GCC_TRANSFER_INDICATION */
  959. /* GCC_UNLOCK_CONFIRM */
  960. /****************************************************************/
  961. TRACE_OUT(("DCRNCConferenceManager::HandleGCCCallback: Ignoring msg_type=%u", pGCCMessage->message_type));
  962. break;
  963. }
  964. DebugExitVOID(DCRNCConferenceManager::HandleGCCCallback);
  965. }
  966. void DCRNCConferenceManager::
  967. BroadcastGCCCallback ( GCCMessage *pGCCMessage )
  968. {
  969. DebugEntry(DCRNCConferenceManager::BroadcastGCCCallback);
  970. // An event has come in that is of potential interest to all
  971. // conferences, so pass it on to them.
  972. // Note that this is currently only used for broken logical
  973. // connections that are actually on a single conference because
  974. // T120 maps logical connections to conferences.
  975. PCONFERENCE pConf;
  976. m_ConfList.Reset();
  977. while (NULL != (pConf = m_ConfList.Iterate()))
  978. {
  979. pConf->HandleGCCCallback(pGCCMessage);
  980. }
  981. DebugExitVOID(DCRNCConferenceManager::BroadcastGCCCallback);
  982. }
  983. // HandleJoinConfirm - handle a GCC_JOIN_CONFIRM message.
  984. void DCRNCConferenceManager::
  985. HandleJoinConfirm ( JoinConfirmMessage * pJoinConfirm )
  986. {
  987. PCONFERENCE pConf = NULL;
  988. LPWSTR pwszConfName;
  989. DebugEntry(DCRNCConferenceManager::HandleJoinConfirm);
  990. // For join confirm, the conference won't know its ID yet
  991. // (it is contained in this message),
  992. // so get the conference by name.
  993. HRESULT hr = GetUnicodeFromGCC((PCSTR)pJoinConfirm->conference_name.numeric_string,
  994. pJoinConfirm->conference_name.text_string,
  995. &pwszConfName);
  996. if (NO_ERROR == hr)
  997. {
  998. pConf = GetConferenceFromName(pwszConfName);
  999. delete pwszConfName;
  1000. }
  1001. if (pConf == NULL)
  1002. {
  1003. pConf = GetConferenceFromNumber(pJoinConfirm->conference_name.numeric_string);
  1004. }
  1005. if (pConf != NULL)
  1006. {
  1007. pConf->HandleJoinConfirm(pJoinConfirm);
  1008. }
  1009. DebugExitVOID(DCRNCConferenceManager::HandleJoinConfirm);
  1010. }
  1011. #ifdef ENABLE_START_REMOTE
  1012. // HandleCreateIndication - handle a GCC_CREATE_INDICATION message.
  1013. void DCRNCConferenceManager::
  1014. HandleCreateIndication ( CreateIndicationMessage * pCreateMessage )
  1015. {
  1016. PCONFERENCE pNewConference = NULL;
  1017. HRESULT hr = UI_RC_USER_REJECTED;
  1018. LPWSTR name;
  1019. DebugEntry(DCRNCConferenceManager::HandleCreateIndication);
  1020. TRACE_OUT(("GCC event: GCC_CREATE_INDICATION"));
  1021. TRACE_OUT(("Conference ID %ld", pCreateMessage->conference_id));
  1022. if (pCreateMessage->conductor_privilege_list == NULL)
  1023. {
  1024. TRACE_OUT(("Conductor privilege list is NULL"));
  1025. }
  1026. else
  1027. {
  1028. TRACE_OUT(("Conductor priv, terminate allowed %d",
  1029. pCreateMessage->conductor_privilege_list->terminate_is_allowed));
  1030. }
  1031. if (pCreateMessage->conducted_mode_privilege_list == NULL)
  1032. {
  1033. TRACE_OUT(("Conducted mode privilege list is NULL"));
  1034. }
  1035. else
  1036. {
  1037. TRACE_OUT(("Conducted mode priv, terminate allowed %d",
  1038. pCreateMessage->conducted_mode_privilege_list->terminate_is_allowed));
  1039. }
  1040. if (pCreateMessage->non_conducted_privilege_list == NULL)
  1041. {
  1042. TRACE_OUT(("Non-conducted mode privilege list is NULL"));
  1043. }
  1044. else
  1045. {
  1046. TRACE_OUT(("non-conducted priv, terminate allowed %d",
  1047. pCreateMessage->non_conducted_privilege_list->terminate_is_allowed));
  1048. }
  1049. hr = ::GetUnicodeFromGCC((PCSTR)pCreateMessage->conference_name.numeric_string,
  1050. (PWSTR)pCreateMessage->conference_name.text_string,
  1051. &name);
  1052. if (NO_ERROR == hr)
  1053. {
  1054. hr = CreateNewConference(name,
  1055. pCreateMessage->conference_id,
  1056. &pNewConference);
  1057. delete name;
  1058. }
  1059. if (NO_ERROR == hr)
  1060. {
  1061. hr = pNewConference->StartIncoming();
  1062. if (NO_ERROR == hr)
  1063. {
  1064. g_pNCConfMgr->CreateConferenceRequest(pNewConference);
  1065. return;
  1066. }
  1067. }
  1068. ERROR_OUT(("Failed to create incoming conference"));
  1069. GCCCreateResponse(hr, pMsg->conference_id, &pMsg->conference_name);
  1070. DebugExitVOID(DCRNCConferenceManager::HandleCreateIndication);
  1071. }
  1072. #endif // ENABLE_START_REMOTE
  1073. void DCRNCConferenceManager::
  1074. GCCCreateResponse
  1075. (
  1076. HRESULT hr,
  1077. GCCConfID conference_id,
  1078. GCCConferenceName * pGCCName
  1079. )
  1080. {
  1081. DebugEntry(DCRNCConferenceManager::GCCCreateResponse);
  1082. GCCError GCCrc = g_pIT120ControlSap->ConfCreateResponse(
  1083. NULL,
  1084. conference_id,
  1085. 0,
  1086. NULL, /* domain_parameters */
  1087. 0, /* number_of_network_addresses */
  1088. NULL, /* local_network_address_list */
  1089. 0, /* number_of_user_data_members */
  1090. NULL, /* user_data_list */
  1091. ::MapRCToGCCResult(hr));
  1092. TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfCreateResponse, rc=%d", GCCrc));
  1093. DebugExitVOID(DCRNCConferenceManager::GCCCreateResponse);
  1094. }
  1095. /****************************************************************************/
  1096. /* HandleInviteIndication - handle a GCC_INVITE_INDICATION message. */
  1097. /****************************************************************************/
  1098. void DCRNCConferenceManager::
  1099. HandleInviteIndication ( InviteIndicationMessage * pInviteMessage )
  1100. {
  1101. LPWSTR pwszConfName;
  1102. PCONFERENCE pNewConference = NULL;
  1103. HRESULT hr;
  1104. CLogicalConnection *pConEntry;
  1105. CInviteIndWork *pInviteUI;
  1106. DebugEntry(DCRNCConferenceManager::HandleInviteIndication);
  1107. TRACE_OUT(("GCC event: GCC_INVITE_INDICATION"));
  1108. TRACE_OUT(("Invited into conference ID %ld", pInviteMessage->conference_id));
  1109. // Create a new conference, using the constructor for an incoming T120
  1110. // conference.
  1111. hr = GetUnicodeFromGCC((PCSTR)pInviteMessage->conference_name.numeric_string,
  1112. (PWSTR)pInviteMessage->conference_name.text_string,
  1113. &pwszConfName);
  1114. //
  1115. // Check to see if we're allowed to be invited. We may never get here
  1116. // if we properly signal callers that we won't accept a nonsecure
  1117. // Invite, but if they do it anyway or lead with T.120 we will enforce
  1118. // the registry setting here.
  1119. //
  1120. // REQUIRE SECURITY!
  1121. #if 0
  1122. {
  1123. if ( !pInviteMessage->fSecure )
  1124. {
  1125. WARNING_OUT(("HandleInviteIndication: CONNECTION is NOT SECURE"));
  1126. hr = UI_RC_T120_SECURITY_FAILED;
  1127. }
  1128. }
  1129. #endif
  1130. if (NO_ERROR == hr)
  1131. {
  1132. hr = CreateNewConference(pwszConfName,
  1133. pInviteMessage->conference_id,
  1134. &pNewConference,
  1135. FALSE,
  1136. pInviteMessage->fSecure);
  1137. delete pwszConfName;
  1138. if (NO_ERROR == hr)
  1139. {
  1140. // Make sure the conference object does not go away randomly.
  1141. pNewConference->AddRef();
  1142. pNewConference->SetActive(FALSE);
  1143. DBG_SAVE_FILE_LINE
  1144. pConEntry = pNewConference->NewLogicalConnection(CONF_CON_INVITED,
  1145. pInviteMessage->connection_handle,
  1146. pInviteMessage->fSecure);
  1147. if (NULL != pConEntry)
  1148. {
  1149. // Save the T120 connection handle in the connection record
  1150. // so that disconnect indications take down the conference.
  1151. pConEntry->SetInviteReqConnHandle(pInviteMessage->connection_handle);
  1152. hr = pNewConference->StartIncoming();
  1153. // Linearize the invite requests so that two invites don't fight each other
  1154. // for attention, and so that the second invite has a conference to see in
  1155. // rosters and join if the first invite gets accepted.
  1156. if (NO_ERROR == hr)
  1157. {
  1158. DBG_SAVE_FILE_LINE
  1159. pInviteUI = new CInviteIndWork(pNewConference,
  1160. (LPCWSTR)(pInviteMessage->caller_identifier),
  1161. pConEntry);
  1162. if (pInviteUI)
  1163. {
  1164. pNewConference->SetInviteIndWork(pInviteUI);
  1165. m_InviteIndWorkList.AddWorkItem(pInviteUI);
  1166. hr = NO_ERROR;
  1167. }
  1168. else
  1169. {
  1170. hr = UI_RC_OUT_OF_MEMORY;
  1171. }
  1172. }
  1173. }
  1174. else
  1175. {
  1176. hr = UI_RC_OUT_OF_MEMORY;
  1177. }
  1178. // This Release corresponds to the above AddRef.
  1179. if (0 == pNewConference->Release())
  1180. {
  1181. // Make sure no one will use it any more.
  1182. pNewConference = NULL;
  1183. }
  1184. }
  1185. }
  1186. if (NO_ERROR != hr)
  1187. {
  1188. if (NULL != pNewConference)
  1189. {
  1190. pNewConference->InviteResponse(hr);
  1191. }
  1192. else
  1193. {
  1194. // LONCHANC: we have to somehow send a response PDU out.
  1195. g_pIT120ControlSap->ConfInviteResponse(
  1196. pInviteMessage->conference_id,
  1197. NULL,
  1198. pInviteMessage->fSecure,
  1199. NULL, // domain parms
  1200. 0, // number_of_network_addresses
  1201. NULL, // local_network_address_list
  1202. 0,
  1203. NULL,
  1204. GCC_RESULT_ENTRY_ALREADY_EXISTS);
  1205. }
  1206. }
  1207. DebugExitHRESULT(DCRNCConferenceManager::HandleInviteIndication, hr);
  1208. }
  1209. /****************************************************************************/
  1210. /* HandleJoinInd - handle a GCC_JOIN_INDICATION message. */
  1211. /****************************************************************************/
  1212. void DCRNCConferenceManager::
  1213. HandleJoinInd ( JoinIndicationMessage * pJoinInd )
  1214. {
  1215. DebugEntry(DCRNCConferenceManager::HandleJoinInd);
  1216. GCCResult Result = GCC_RESULT_SUCCESSFUL;
  1217. // Look up conference ID, and if not found, dismiss request.
  1218. CJoinIndWork *pJoinUI;
  1219. CLogicalConnection *pConEntry;
  1220. PCONFERENCE pConf = GetConferenceFromID(pJoinInd->conference_id);
  1221. if (NULL != pConf)
  1222. {
  1223. //
  1224. // Under RDS, if this conference has been hit with bad passwords
  1225. // too many times, everyone is out of luck and we will not accept
  1226. // anyone into this conference anymore.
  1227. //
  1228. if (g_bRDS && ( pConf->InvalidPwdCount() >= MAX_INVALID_PASSWORDS ))
  1229. {
  1230. WARNING_OUT(("RDS: locked out by too many bad pwd attempts"));
  1231. Result = GCC_RESULT_USER_REJECTED;
  1232. }
  1233. // Validate conference password, if required.
  1234. else if (!pConf->ValidatePassword(pJoinInd->password_challenge))
  1235. {
  1236. //
  1237. // Only increment the wrong password count if one was
  1238. // supplied
  1239. //
  1240. if ( pJoinInd->password_challenge )
  1241. pConf->IncInvalidPwdCount();
  1242. if ( g_bRDS &&
  1243. ( pConf->InvalidPwdCount() >= MAX_INVALID_PASSWORDS ))
  1244. {
  1245. Result = GCC_RESULT_USER_REJECTED;
  1246. }
  1247. else
  1248. {
  1249. Result = GCC_RESULT_INVALID_PASSWORD;
  1250. }
  1251. }
  1252. else
  1253. pConf->ResetInvalidPwdCount();
  1254. }
  1255. else
  1256. {
  1257. Result = GCC_RESULT_INVALID_CONFERENCE;
  1258. }
  1259. if (Result == GCC_RESULT_SUCCESSFUL)
  1260. {
  1261. DBG_SAVE_FILE_LINE
  1262. pConEntry = pConf->NewLogicalConnection(
  1263. CONF_CON_JOINED,
  1264. pJoinInd->connection_handle,
  1265. pConf->IsSecure());
  1266. if (NULL != pConEntry)
  1267. {
  1268. HRESULT hr;
  1269. DBG_SAVE_FILE_LINE
  1270. pJoinUI = new CJoinIndWork(pJoinInd->join_response_tag,
  1271. pConf,
  1272. pJoinInd->caller_identifier,
  1273. pConEntry,
  1274. &hr);
  1275. if (NULL != pJoinUI && NO_ERROR == hr)
  1276. {
  1277. m_JoinIndWorkList.AddWorkItem(pJoinUI);
  1278. return;
  1279. }
  1280. // Handle failure
  1281. delete pJoinUI;
  1282. pConEntry->Delete(UI_RC_OUT_OF_MEMORY);
  1283. }
  1284. Result = GCC_RESULT_RESOURCES_UNAVAILABLE;
  1285. }
  1286. ::GCCJoinResponseWrapper(pJoinInd->join_response_tag,
  1287. NULL,
  1288. Result,
  1289. pJoinInd->conference_id);
  1290. DebugExitVOID(DCRNCConferenceManager::HandleJoinInd);
  1291. }
  1292. void HandleQueryConfirmation ( QueryConfirmMessage * pQueryMessage )
  1293. {
  1294. DebugEntry(HandleQueryConfirmation);
  1295. ASSERT(g_pQueryRemoteList);
  1296. CQueryRemoteWork *pQueryRemote;
  1297. // Must have a pending query and it must be first in
  1298. // sequential work list.
  1299. g_pQueryRemoteList->Reset();
  1300. while (NULL != (pQueryRemote = g_pQueryRemoteList->Iterate()))
  1301. {
  1302. if (pQueryRemote->GetConnectionHandle() == pQueryMessage->connection_handle)
  1303. {
  1304. // GCC has given us a valid query response, so handle it.
  1305. pQueryRemote->HandleQueryConfirmation(pQueryMessage);
  1306. break;
  1307. }
  1308. }
  1309. if (NULL == pQueryRemote)
  1310. {
  1311. // Unexpected GCC Query Confirmation.
  1312. WARNING_OUT(("HandleQueryConfirmation: Unmatched GCCQueryConfirm"));
  1313. }
  1314. DebugExitVOID(HandleQueryConfirmation);
  1315. }
  1316. /****************************************************************************/
  1317. /* NotifyConferenceComplete() - see ernccm.hpp */
  1318. /****************************************************************************/
  1319. void DCRNCConferenceManager::
  1320. NotifyConferenceComplete
  1321. (
  1322. PCONFERENCE pConf,
  1323. BOOL bIncoming,
  1324. HRESULT result
  1325. )
  1326. {
  1327. DebugEntry(DCRNCConferenceManager::NotifyConferenceComplete);
  1328. ASSERT(NULL != pConf);
  1329. // If the new conference was successfully added, then ensure that it
  1330. // is marked as active. This is for the invite case, and is done before
  1331. // telling the UI about the conference.
  1332. HRESULT hr = result;
  1333. if (NO_ERROR == hr)
  1334. {
  1335. pConf->SetActive(TRUE);
  1336. }
  1337. // If the conference failed to start, tell the UI so that
  1338. // it can display a pop-up.
  1339. // Note this this allows message pre-emption which can cause GCC to give back a GCC event.
  1340. // In particular, a JoinRequest completion event, which must be ignored.
  1341. // The following is a guard because NotifyConferenceComplete is called all
  1342. // over the place and we do not want the user notified through callbacks
  1343. // for inline errors. All inline errors are meant to trickle back through the
  1344. // originating API, so these callbacks are only enabled once the user is returned
  1345. // success.
  1346. if (pConf->GetNotifyToDo())
  1347. {
  1348. pConf->SetNotifyToDo(FALSE);
  1349. //
  1350. // LONCHANC: This function may be called inside
  1351. // ConfMgr::ReleaseInterface(). As a result, the global pointer
  1352. // to the callback interface may already be nulled out.
  1353. // Check it before use it.
  1354. //
  1355. if (NULL != g_pCallbackInterface)
  1356. {
  1357. g_pCallbackInterface->OnConferenceStarted(pConf, hr);
  1358. }
  1359. }
  1360. if (NO_ERROR == hr)
  1361. {
  1362. // If the conference is new as the result of an invite, then it has an entry
  1363. // at the start of the sequential work item list. Now that the conference is up
  1364. // and the UI has been told, this entry is removed to allow other invite
  1365. // requests to be processed.
  1366. m_InviteIndWorkList.RemoveWorkItem(pConf->GetInviteIndWork());
  1367. pConf->SetInviteIndWork(NULL);
  1368. }
  1369. else
  1370. {
  1371. RemoveConference(pConf);
  1372. }
  1373. DebugExitVOID(DCRNCConferenceManager::NotifyConferenceComplete);
  1374. }
  1375. /****************************************************************************/
  1376. /* NotifyRosterChanged() - see ernccm.hpp */
  1377. /****************************************************************************/
  1378. // RemoveConference() - remove the conference from the conference list,
  1379. // and destroy the conference.
  1380. void DCRNCConferenceManager::
  1381. RemoveConference ( PCONFERENCE pConf, BOOL fDontCheckList, BOOL fReleaseNow )
  1382. {
  1383. DebugEntry(DCRNCConferenceManager::RemoveConference);
  1384. if (pConf != NULL)
  1385. {
  1386. if (m_ConfList.Remove(pConf) || fDontCheckList)
  1387. {
  1388. pConf->OnRemoved(fReleaseNow);
  1389. m_InviteIndWorkList.PurgeListEntriesByOwner(pConf);
  1390. m_JoinIndWorkList.PurgeListEntriesByOwner(pConf);
  1391. }
  1392. else
  1393. {
  1394. // If we get here, we haven't found the conference.
  1395. // This actually happens because when a conference is being
  1396. // terminated, its destructor calls DCRNCConference::Leave()
  1397. // to ensure a speedy exit, if required. However, if the
  1398. // conference is currently not yet active (e.g. waiting for
  1399. // the user to supply a password), calling Leave() causes
  1400. // RemoveConference() to be called back. In this case,
  1401. // because the conference has already been removed from the
  1402. // list, this function does nothing.
  1403. }
  1404. }
  1405. DebugExitVOID(DCRNCConferenceManager::RemoveConference);
  1406. }
  1407. /****************************************************************************/
  1408. /* EjectUserFromConference() - see ernccm.hpp */
  1409. /****************************************************************************/
  1410. /****************************************************************************/
  1411. /* SendUserTextMessage() - see ernccm.hpp */
  1412. /****************************************************************************/
  1413. /****************************************************************************/
  1414. /* TimeRemainingInConference() - see ernccm.hpp */
  1415. /****************************************************************************/
  1416. /****************************************************************************/
  1417. /* GCC callback function. */
  1418. /****************************************************************************/
  1419. void CALLBACK DCRNCConferenceManager::
  1420. GCCCallBackHandler ( GCCMessage * pGCCMessage )
  1421. {
  1422. DCRNCConferenceManager *pConfManager;
  1423. /************************************************************************/
  1424. /* The message has a user defined field which we use to store a pointer */
  1425. /* to the CM class. Use it to pass the message onto CM. */
  1426. /************************************************************************/
  1427. pConfManager = (DCRNCConferenceManager *) pGCCMessage->user_defined;
  1428. //
  1429. // Check the pointer isnt completely daft,
  1430. // and guard against getting events after shutting down
  1431. // (a current bug in GCC/MCS).
  1432. if (pConfManager == g_pNCConfMgr)
  1433. {
  1434. /************************************************************************/
  1435. /* Pass the message onto CM and return the returned code. */
  1436. /************************************************************************/
  1437. g_pNCConfMgr->HandleGCCCallback(pGCCMessage);
  1438. }
  1439. else
  1440. {
  1441. WARNING_OUT(("Dud user_defined field, pConfMgr=%p, g_pNCConfMgr=%p",
  1442. pConfManager, g_pNCConfMgr));
  1443. }
  1444. }
  1445. HRESULT GCCJoinResponseWrapper
  1446. (
  1447. GCCResponseTag join_response_tag,
  1448. GCCChallengeRequestResponse *password_challenge,
  1449. GCCResult result,
  1450. GCCConferenceID conferenceID,
  1451. UINT nUserData,
  1452. GCCUserData **ppUserData
  1453. )
  1454. {
  1455. HRESULT hr;
  1456. GCCError GCCrc;
  1457. DebugEntry(GCCJoinResponseWrapper);
  1458. TRACE_OUT(("GCC event: GCC_JOIN_INDICATION"));
  1459. TRACE_OUT(("Response tag %d", join_response_tag));
  1460. if (g_pControlSap->IsThisNodeTopProvider(conferenceID) == FALSE)
  1461. {
  1462. GCCrc = g_pIT120ControlSap->ConfJoinResponse(join_response_tag,
  1463. password_challenge,
  1464. nUserData,
  1465. ppUserData,
  1466. result);
  1467. }
  1468. else
  1469. {
  1470. GCCrc = g_pIT120ControlSap->ConfJoinResponse(join_response_tag,
  1471. password_challenge,
  1472. 0,
  1473. NULL,
  1474. result);
  1475. }
  1476. hr = ::GetGCCRCDetails(GCCrc);
  1477. TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfJoinResponse, rc=%d", GCCrc));
  1478. if ((GCCrc != GCC_NO_ERROR) &&
  1479. (result != GCC_RESULT_USER_REJECTED))
  1480. {
  1481. /********************************************************************/
  1482. /* If the call to join response fails, we must try again to reject */
  1483. /* the join request. */
  1484. /********************************************************************/
  1485. ERROR_OUT(("GCCJoinResponseWrapper: GCC error %d responding to join ind", GCCrc));
  1486. GCCrc = g_pIT120ControlSap->ConfJoinResponse(join_response_tag,
  1487. password_challenge,
  1488. 0,
  1489. NULL,
  1490. GCC_RESULT_USER_REJECTED);
  1491. TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfJoinResponse (again), rc=%d", GCCrc));
  1492. if (GCCrc != GCC_NO_ERROR)
  1493. {
  1494. /****************************************************************/
  1495. /* If it fails a second time we really are in deep doggy-do. */
  1496. /****************************************************************/
  1497. ERROR_OUT(("GCCJoinResponseWrapper: g_pIT120ControlSap->ConfJoinResponse failed again..."));
  1498. }
  1499. }
  1500. DebugExitHRESULT(GCCJoinResponseWrapper, hr);
  1501. return hr;
  1502. }
  1503. void HandleQueryIndication ( QueryIndicationMessage * pQueryMessage )
  1504. {
  1505. DebugEntry(HandleQueryIndication);
  1506. GCCAsymmetryIndicator ai, ai2;
  1507. GCCNodeType node_type;
  1508. GCCError GCCrc;
  1509. CQueryRemoteWork *pQueryRemote = NULL;
  1510. GCCResult result = GCC_RESULT_SUCCESSFUL;
  1511. OSVERSIONINFO osvi;
  1512. osvi.dwOSVersionInfoSize = sizeof(osvi);
  1513. if (FALSE == ::GetVersionEx (&osvi))
  1514. {
  1515. ERROR_OUT(("GetVersionEx() failed!"));
  1516. }
  1517. if ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId && g_bRDS )
  1518. {
  1519. SOCKET socket_number;
  1520. if (g_pMCSController->FindSocketNumber(pQueryMessage->connection_handle, &socket_number))
  1521. {
  1522. TransportConnection XprtConn;
  1523. SET_SOCKET_CONNECTION(XprtConn, socket_number);
  1524. PSocket pSocket = g_pSocketList->FindByTransportConnection(XprtConn);
  1525. ASSERT(NULL != pSocket);
  1526. if (NULL != pSocket)
  1527. {
  1528. pSocket->Release();
  1529. }
  1530. }
  1531. }
  1532. // If the caller did not pass in the protocol for deciding who is caller
  1533. // then fabricate something for him and make him the caller.
  1534. if (pQueryMessage->asymmetry_indicator)
  1535. {
  1536. ai = *pQueryMessage->asymmetry_indicator;
  1537. }
  1538. else
  1539. {
  1540. ai.asymmetry_type = GCC_ASYMMETRY_CALLER;
  1541. ai.random_number = 0;
  1542. }
  1543. // let's set default random number, which will be read only in the "unknown" case.
  1544. ai2.random_number = ai.random_number;
  1545. // prepare the query respone
  1546. switch (ai.asymmetry_type)
  1547. {
  1548. case GCC_ASYMMETRY_CALLED:
  1549. ai2.asymmetry_type = GCC_ASYMMETRY_CALLER;
  1550. break;
  1551. case GCC_ASYMMETRY_CALLER:
  1552. ai2.asymmetry_type = GCC_ASYMMETRY_CALLED;
  1553. break;
  1554. case GCC_ASYMMETRY_UNKNOWN:
  1555. // Check if we are not in a pending query
  1556. ASSERT(g_pQueryRemoteList);
  1557. if (! g_pQueryRemoteList->IsEmpty())
  1558. {
  1559. pQueryRemote = g_pQueryRemoteList->PeekHead();
  1560. }
  1561. // If we queryed as unknown
  1562. if (pQueryRemote && pQueryRemote->IsInUnknownQueryRequest())
  1563. {
  1564. pQueryRemote->GetAsymIndicator(&ai2);
  1565. if (ai2.asymmetry_type == GCC_ASYMMETRY_UNKNOWN &&
  1566. ai2.random_number > ai.random_number)
  1567. {
  1568. result = GCC_RESULT_USER_REJECTED;
  1569. }
  1570. }
  1571. else
  1572. {
  1573. ai2.asymmetry_type = GCC_ASYMMETRY_UNKNOWN;
  1574. // ai2.random_number = ~ ai.random_number;
  1575. ai2.random_number--; // lonchanc: we should always be the callee in this case.
  1576. }
  1577. break;
  1578. default:
  1579. result = GCC_RESULT_USER_REJECTED;
  1580. break;
  1581. }
  1582. // Figure out my node type.
  1583. LoadAnnouncePresenceParameters(&node_type, NULL, NULL, NULL);
  1584. // Issue reply.
  1585. GCCrc = g_pIT120ControlSap->ConfQueryResponse(
  1586. pQueryMessage->query_response_tag,
  1587. node_type,
  1588. &ai2,
  1589. 0,
  1590. NULL,
  1591. result);
  1592. if (GCCrc)
  1593. {
  1594. TRACE_OUT(("HandleQueryIndication: g_pIT120ControlSap->ConfQueryResponse failed, rc=%d", GCCrc));
  1595. }
  1596. DebugExitVOID(HandleQueryIndication);
  1597. }
  1598. void HandleConductGiveInd ( ConductGiveIndicationMessage * pConductGiveInd )
  1599. {
  1600. DebugEntry(HandleConductGiveInd);
  1601. // Node controller does not accept conductorship being handed over
  1602. // from another node, so reject request.
  1603. GCCError GCCrc = g_pIT120ControlSap->ConductorGiveResponse(pConductGiveInd->conference_id,
  1604. GCC_RESULT_USER_REJECTED);
  1605. TRACE_OUT(("HandleConductGiveInd: Failed to reject ConductGiveIndication, gcc_rc=%u", (UINT) GCCrc));
  1606. DebugExitVOID(HandleConductGiveInd);
  1607. }
  1608. void HandleAddInd ( AddIndicationMessage * pAddInd )
  1609. {
  1610. DebugEntry(HandleAddInd);
  1611. // Just reject the request because we don't do adds on behalf of someone else.
  1612. GCCError GCCrc = g_pIT120ControlSap->ConfAddResponse(
  1613. pAddInd->add_response_tag, // add_response_tag
  1614. pAddInd->conference_id, // conference_id
  1615. pAddInd->requesting_node_id, // requesting_node
  1616. 0, // number_of_user_data_members
  1617. NULL, // user_data_list
  1618. GCC_RESULT_USER_REJECTED); // result
  1619. TRACE_OUT(("HandleAddInd: Failed to reject AddIndication, gcc_rc=%u", (UINT) GCCrc));
  1620. DebugExitVOID(HandleAddInd);
  1621. }
  1622. void HandleLockIndication ( LockIndicationMessage * pLockInd )
  1623. {
  1624. DebugEntry(HandleLockIndication);
  1625. // Just reject the request because we don't do locked conferences.
  1626. GCCError GCCrc = g_pIT120ControlSap->ConfLockResponse(
  1627. pLockInd->conference_id, // conference_id
  1628. pLockInd->requesting_node_id, // requesting_node
  1629. GCC_RESULT_USER_REJECTED); // result
  1630. TRACE_OUT(("HandleLockIndication: Failed to reject LockIndication, gcc_rc=%u", (UINT) GCCrc));
  1631. DebugExitVOID(HandleLockIndication);
  1632. }
  1633. void HandleUnlockIndication ( UnlockIndicationMessage * pUnlockInd )
  1634. {
  1635. DebugEntry(HandleUnlockIndication);
  1636. // Reject the request because we don't manage
  1637. // locking/unlocking of conferences.
  1638. GCCError GCCrc = g_pIT120ControlSap->ConfLockResponse(
  1639. pUnlockInd->conference_id, // conference_id
  1640. pUnlockInd->requesting_node_id, // requesting_node
  1641. GCC_RESULT_USER_REJECTED); // result
  1642. TRACE_OUT(("HandleUnlockIndication: Failed to reject UnlockIndication, gcc_rc=%u", (UINT) GCCrc));
  1643. DebugExitVOID(HandleUnlockIndication);
  1644. }
  1645. void HandleSubInitializedInd ( SubInitializedIndicationMessage * pSubInitInd )
  1646. {
  1647. DebugEntry(HandleSubInitializedInd);
  1648. CLogicalConnection *pConEntry = g_pNCConfMgr->GetConEntryFromConnectionHandle(
  1649. pSubInitInd->connection_handle);
  1650. if (NULL != pConEntry)
  1651. {
  1652. pConEntry->SetConnectionNodeID(pSubInitInd->subordinate_node_id);
  1653. }
  1654. DebugExitVOID(HandleSubInitializedInd);
  1655. }
  1656. // This function is used by the GCC_SUB_INITIALIZED_INDICATION handler.
  1657. // This handler was added to bind the request to enter someone into
  1658. // a conference to the resulting conference roster, so that you could
  1659. // tell which new entry in the roster was the one you requested in.
  1660. // Since the above handler only gets a connection handle (recast here to a
  1661. // request handle) and a userID, this means that the local GCC implementation
  1662. // is guarunteeing that connection handles are unique to a local machine
  1663. // and not duplicated in different conferences (this fact is also being used
  1664. // by the node controller to know when someone invited into a conference leaves).
  1665. CLogicalConnection * DCRNCConferenceManager::
  1666. GetConEntryFromConnectionHandle ( ConnectionHandle hInviteIndConn )
  1667. {
  1668. PCONFERENCE pConf;
  1669. CLogicalConnection *pConEntry;
  1670. m_ConfList.Reset();
  1671. while (NULL != (pConf = m_ConfList.Iterate()))
  1672. {
  1673. pConEntry = pConf->GetConEntry(hInviteIndConn);
  1674. if (NULL != pConEntry)
  1675. {
  1676. return(pConEntry);
  1677. }
  1678. }
  1679. return(NULL);
  1680. }
  1681. void HandleTimeInquireIndication ( TimeInquireIndicationMessage * pTimeInquireInd )
  1682. {
  1683. DebugEntry(HandleTimeInquireIndication);
  1684. // Since we don't currently time messages, and there is no mechanism to say this,
  1685. // or to even say that there is no such conference that we know about, just
  1686. // say that the conference has one hour remaining, with the same scope as the request.
  1687. UserID node_id = pTimeInquireInd->time_is_conference_wide ?
  1688. 0 : pTimeInquireInd->requesting_node_id;
  1689. GCCError GCCrc = g_pIT120ControlSap->ConfTimeRemainingRequest(
  1690. pTimeInquireInd->conference_id,
  1691. 60*60,
  1692. node_id);
  1693. TRACE_OUT(("HandleTimeInquireIndication: Failed to return Time Remaining, gcc_rc=%u", (UINT) GCCrc));
  1694. DebugExitVOID(HandleTimeInquireIndication);
  1695. }
  1696. BOOL DCRNCConferenceManager::
  1697. FindSocketNumber
  1698. (
  1699. GCCNodeID nid,
  1700. SOCKET *socket_number
  1701. )
  1702. {
  1703. // Currently we are relying on the fact there is only one conference at a time.
  1704. PCONFERENCE pConf = m_ConfList.PeekHead();
  1705. if (NULL != pConf)
  1706. {
  1707. return pConf->FindSocketNumber(nid, socket_number);
  1708. }
  1709. return FALSE;
  1710. }
  1711. /* H A N D L E A P P L I C A T I O N I N V O K E I N D I C A T I O N */
  1712. /*----------------------------------------------------------------------------
  1713. %%Function: HandleApplicationInvokeIndication
  1714. TODO: use GCC_OBJECT_KEY instead of GCC_H221_NONSTANDARD_KEY
  1715. ----------------------------------------------------------------------------*/
  1716. void HandleApplicationInvokeIndication ( ApplicationInvokeIndicationMessage * pInvokeMessage )
  1717. {
  1718. DebugEntry(HandleApplicationInvokeIndication);
  1719. DebugExitVOID(HandleApplicationInvokeIndication);
  1720. }
  1721. // Update <NodeId,Name> pair
  1722. void DCRNCConferenceManager::
  1723. UpdateNodeIdNameListAndUserData(GCCMessage * pGCCMessage)
  1724. {
  1725. GCCConfID ConfId = pGCCMessage->nConfID;
  1726. PCONFERENCE pConf = GetConferenceFromID(ConfId);
  1727. if (pConf)
  1728. pConf->UpdateNodeIdNameListAndUserData(pGCCMessage);
  1729. }
  1730. void WINAPI T120_GetNodeName(LPSTR szName, UINT cchMax)
  1731. {
  1732. BSTR bstrName;
  1733. bstrName = ::GetNodeName();
  1734. if (!bstrName)
  1735. {
  1736. *szName = 0;
  1737. }
  1738. else
  1739. {
  1740. CSTRING str(bstrName);
  1741. lstrcpyn(szName, str, cchMax);
  1742. SysFreeString(bstrName);
  1743. }
  1744. }
  1745. BSTR GetNodeName(void)
  1746. {
  1747. if (g_pNCConfMgr)
  1748. {
  1749. return g_pNCConfMgr->GetNodeName();
  1750. }
  1751. else
  1752. return NULL;
  1753. }
  1754. BSTR DCRNCConferenceManager::GetNodeName(void)
  1755. {
  1756. return(SysAllocString(m_bstrUserName));
  1757. }
  1758. // Query node name
  1759. ULONG DCRNCConferenceManager::
  1760. GetNodeName(GCCConfID ConfId, GCCNodeID NodeId,
  1761. LPSTR pszBuffer, ULONG cbBufSize)
  1762. {
  1763. PCONFERENCE pConf = GetConferenceFromID(ConfId);
  1764. if (pConf)
  1765. return pConf->GetNodeName(NodeId, pszBuffer, cbBufSize);
  1766. return 0;
  1767. }
  1768. // Query user data
  1769. ULONG DCRNCConferenceManager::
  1770. GetUserGUIDData(GCCConfID ConfId, GCCNodeID NodeId,
  1771. GUID *pGuid, LPBYTE pbBuffer, ULONG cbBufSize)
  1772. {
  1773. PCONFERENCE pConf = GetConferenceFromID(ConfId);
  1774. if (pConf)
  1775. return pConf->GetUserGUIDData(NodeId, pGuid, pbBuffer, cbBufSize);
  1776. return 0;
  1777. }