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.

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