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.

2225 lines
67 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* ERNCCONF.CPP */
  4. /* */
  5. /* Base Conference class for the Reference System Node Controller. */
  6. /* */
  7. /* Copyright Data Connection Ltd. 1995 */
  8. /* */
  9. /****************************************************************************/
  10. /* Changes: */
  11. /* */
  12. /* 12Jul95 NFC Created. */
  13. /* 05Oct95 NFC SFR 6206 Treat a "Join" as an incoming call. */
  14. /* 11Oct95 PM Relax checks on conference termination to */
  15. /* prevent "no win" situations */
  16. /* Support START_ALTERNATE from TPhys API */
  17. /* */
  18. /****************************************************************************/
  19. #include "precomp.h"
  20. DEBUG_FILEZONE(ZONE_GCC_NC);
  21. #include "ernccons.h"
  22. #include "nccglbl.hpp"
  23. #include "erncvrsn.hpp"
  24. #include <cuserdta.hpp>
  25. #include "connect.h"
  26. #include "erncconf.hpp"
  27. #include "ernctrc.h"
  28. #include "ernccm.hpp"
  29. #include <iappldr.h>
  30. #include "plgxprt.h"
  31. #include "nmremote.h"
  32. extern PController g_pMCSController;
  33. DCRNCConference::
  34. DCRNCConference
  35. (
  36. LPCWSTR pwcszConfName,
  37. GCCConfID nConfID,
  38. BOOL fSecure,
  39. HRESULT *pRetCode
  40. )
  41. :
  42. CRefCount(MAKE_STAMP_ID('N','C','C','F')),
  43. m_fNotifyToDo(FALSE),
  44. m_fActive(TRUE),
  45. #ifdef _DEBUG
  46. m_fAppendedToConfList(FALSE),
  47. #endif
  48. m_pInviteUI(NULL),
  49. m_pszFirstRemoteNodeAddress(NULL),
  50. m_nConfID(nConfID),
  51. m_eState(CONF_ST_UNINITIALIZED),
  52. m_fIncoming(FALSE),
  53. m_pbHashedPassword(NULL),
  54. m_cbHashedPassword(0),
  55. m_pwszPassword(NULL),
  56. m_pszNumericPassword(NULL),
  57. // T120 conference
  58. m_eT120State(T120C_ST_IDLE),
  59. m_nidMyself(0),
  60. m_fSecure(fSecure),
  61. m_nInvalidPasswords(0)
  62. {
  63. DebugEntry(DCRNCConference::DCRNCConference);
  64. // Save the conference name.
  65. DBG_SAVE_FILE_LINE
  66. m_pwszConfName = ::My_strdupW(pwcszConfName);
  67. if (! ::IsEmptyStringW(m_pwszConfName))
  68. {
  69. *pRetCode = NO_ERROR;
  70. }
  71. else
  72. {
  73. *pRetCode = (NULL == m_pwszConfName) ? UI_RC_OUT_OF_MEMORY :
  74. UI_RC_NO_CONFERENCE_NAME;
  75. }
  76. // T120 conference
  77. m_ConfName.numeric_string = NULL;
  78. m_ConfName.text_string = NULL;
  79. DebugExitVOID(DCRNCConference::DCRNCConference);
  80. }
  81. /****************************************************************************/
  82. /* Destructor - see erncconf.h */
  83. /****************************************************************************/
  84. DCRNCConference::
  85. ~DCRNCConference(void)
  86. {
  87. DebugEntry(DCRNCConference::~DCRNCConference);
  88. ASSERT(! m_fAppendedToConfList);
  89. // delete all the name strings
  90. LPSTR pszStr;
  91. while (NULL != (pszStr = m_NodeIdNameList.Get()))
  92. {
  93. delete [] pszStr;
  94. }
  95. // Delete all the usr data
  96. CNCUserDataList *pUserDataList;
  97. while (NULL != (pUserDataList = m_UserDataList.Get()))
  98. {
  99. delete pUserDataList;
  100. }
  101. delete m_pwszConfName;
  102. // If there is a password, delete it.
  103. delete []m_pbHashedPassword;
  104. delete m_pwszPassword;
  105. delete m_pszNumericPassword;
  106. delete m_pszFirstRemoteNodeAddress;
  107. // T120 conference
  108. delete m_ConfName.numeric_string;
  109. DebugExitVOID(DCRNCConference::~DCRNCConference);
  110. }
  111. void DCRNCConference::
  112. OnRemoved(BOOL fReleaseNow)
  113. {
  114. DebugEntry(DCRNCConference::OnRemoved);
  115. CLogicalConnection *pConEntry;
  116. #ifdef _DEBUG
  117. m_fAppendedToConfList = FALSE;
  118. #endif
  119. // Issue a request to leave the conference.
  120. // This request may fail, but may as well let leave validate
  121. // itself, rather than put an extra check in here.
  122. // See comments in RemoveConference() and Leave() for more details
  123. // if interested.
  124. if (T120C_ST_PENDING_DISCONNECT != m_eT120State &&
  125. T120C_ST_PENDING_TERMINATE != m_eT120State)
  126. {
  127. Leave();
  128. }
  129. // Take the conference out of the list of pending invites.
  130. g_pNCConfMgr->RemoveInviteIndWorkItem(m_pInviteUI);
  131. // End all physical connections in use by this conference,
  132. // and inform the user of the results of pending events.
  133. while (NULL != (pConEntry = m_ConnList.Get()))
  134. {
  135. pConEntry->Delete(UI_RC_CONFERENCE_GOING_DOWN);
  136. }
  137. //
  138. // LONCHANC: This destructor may be called inside
  139. // ConfMgr::ReleaseInterface(). As a result, the global pointer
  140. // to the callback interface may already be nulled out.
  141. // Check it before use it.
  142. //
  143. // ASSERT(2 == GetRefCount());
  144. // Tell UI its handle to conference is no longer valid.
  145. if (NULL != g_pCallbackInterface)
  146. {
  147. g_pCallbackInterface->OnConferenceEnded((CONF_HANDLE) this);
  148. }
  149. else
  150. {
  151. ERROR_OUT(("DCRNCConference::OnRemoved: g_pCallbackInterface is null"));
  152. }
  153. // ASSERT(1 == GetRefCount());
  154. if (fReleaseNow)
  155. {
  156. ReleaseNow();
  157. }
  158. else
  159. {
  160. Release();
  161. }
  162. DebugExitVOID(DCRNCConference::OnRemoved);
  163. }
  164. //
  165. // IDataConference Interface
  166. //
  167. STDMETHODIMP_(void) DCRNCConference::
  168. ReleaseInterface(void)
  169. {
  170. DebugEntry(DCRNCConference::ReleaseInterface);
  171. InterfaceEntry();
  172. Release();
  173. DebugExitVOID(DCRNCConference::ReleaseInterface);
  174. }
  175. STDMETHODIMP_(UINT_PTR) DCRNCConference::
  176. GetConferenceID(void)
  177. {
  178. DebugEntry(DCRNCConference::GetConferenceID);
  179. InterfaceEntry();
  180. DebugExitINT(DCRNCConference::GetConferenceID, (UINT) m_nConfID);
  181. return m_nConfID;
  182. }
  183. STDMETHODIMP DCRNCConference::
  184. Leave(void)
  185. {
  186. DebugEntry(DCRNCConference::Leave);
  187. InterfaceEntry();
  188. GCCError GCCrc;
  189. HRESULT hr;
  190. switch (m_eT120State)
  191. {
  192. // LONCHANC: Added the following two cases for cancellation.
  193. case T120C_ST_PENDING_START_CONFIRM:
  194. case T120C_ST_PENDING_JOIN_CONFIRM:
  195. case T120C_ST_PENDING_ROSTER_ENTRY:
  196. case T120C_ST_PENDING_ROSTER_MESSAGE:
  197. case T120C_ST_PENDING_ANNOUNCE_PERMISSION:
  198. // User has called leave on a conference when it is being brought up.
  199. // Drop through to issue a disconnect request to T120.
  200. case T120C_ST_CONF_STARTED:
  201. // Set the state of the conference to note that we are
  202. // disconnecting from T120.
  203. // LONCHANC: this is a must to avoid reentrance of this Leave()
  204. // when direct InviteConfirm hits Node Controller later.
  205. m_eT120State = T120C_ST_PENDING_DISCONNECT;
  206. // User has requested to leave the conference after it has been
  207. // started as a T120 conference, so ask T120 to end the conference
  208. // before removing internal data structures.
  209. GCCrc = g_pIT120ControlSap->ConfDisconnectRequest(m_nConfID);
  210. hr = ::GetGCCRCDetails(GCCrc);
  211. TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfDisconnectRequest, rc=%d", GCCrc));
  212. if (NO_ERROR == hr)
  213. {
  214. break;
  215. }
  216. // T120 won't let us leave a conference that we think we are in.
  217. // Take this to mean that T120 doesn't know about the conference
  218. // anymore and just destroy our own knowledge of the conference.
  219. WARNING_OUT(("DCRNCConference::Leave: Failed to leave conference, GCC error %d", GCCrc));
  220. // Drop through to destroy our references.
  221. case T120C_ST_IDLE:
  222. // User has requested to leave a conference that has not been
  223. // started.
  224. // This should only happen when told that a conference join
  225. // request supplied an invalid password and the user gives up
  226. // on attempting to join the conference (or shuts down conferencing).
  227. // Just do the same processing as would be done when a T120
  228. // disconnect confirmation fires.
  229. g_pNCConfMgr->RemoveConference(this);
  230. hr = NO_ERROR;
  231. break;
  232. case T120C_ST_PENDING_DISCONNECT:
  233. case T120C_ST_PENDING_TERMINATE:
  234. // User has requested to leave a conference that is already
  235. // going down (most likely because of a prior request to leave).
  236. hr = UI_RC_CONFERENCE_GOING_DOWN;
  237. WARNING_OUT(("DCRNCConference::Leave: conference already going down, state=%d", m_eT120State));
  238. break;
  239. default:
  240. // User has called leave on a conference when he shouldn't
  241. // (e.g. when it is being brought up).
  242. // This is very unlikely to happen as the user doesn't know
  243. // the conference handle at this point.
  244. hr = UI_RC_INVALID_REQUEST;
  245. ERROR_OUT(("DCRNCConference::Leave: invalid state=%d", m_eT120State));
  246. break;
  247. }
  248. DebugExitHRESULT(DCRNCConference::Leave, hr);
  249. return hr;
  250. }
  251. STDMETHODIMP DCRNCConference::
  252. EjectUser ( UINT nidEjected )
  253. {
  254. DebugEntry(DCRNCConference::EjectUser);
  255. InterfaceEntry();
  256. GCCError GCCrc = g_pIT120ControlSap->ConfEjectUserRequest(m_nConfID, (UserID) nidEjected, GCC_REASON_USER_INITIATED);
  257. HRESULT hr = ::GetGCCRCDetails(GCCrc);
  258. if (NO_ERROR != hr)
  259. {
  260. ERROR_OUT(("DCRNCConference::EjectUser: Failed to eject user conference, GCC error %d", GCCrc));
  261. }
  262. CLogicalConnection *pConEntry = GetConEntryByNodeID((GCCNodeID) nidEjected);
  263. if (NULL != pConEntry)
  264. {
  265. pConEntry->Delete(UI_RC_USER_DISCONNECTED);
  266. }
  267. DebugExitHRESULT(DCRNCConference::EjectUser, hr);
  268. return hr;
  269. }
  270. STDMETHODIMP DCRNCConference::
  271. Invite
  272. (
  273. LPCSTR pcszNodeAddress,
  274. USERDATAINFO aInfo[],
  275. UINT cInfo,
  276. REQUEST_HANDLE * phRequest
  277. )
  278. {
  279. DebugEntry(DCRNCConference::Invite);
  280. InterfaceEntry();
  281. HRESULT hr;
  282. #if defined(TEST_PLUGGABLE) && defined(_DEBUG)
  283. if (g_fWinsockDisabled)
  284. {
  285. pcszNodeAddress = ::FakeNodeAddress(pcszNodeAddress);
  286. }
  287. #endif
  288. if (NULL != pcszNodeAddress && NULL != phRequest)
  289. {
  290. // if winsock is disabled, block any IP address or machine name
  291. if (g_fWinsockDisabled)
  292. {
  293. if (! IsValidPluggableTransportName(pcszNodeAddress))
  294. {
  295. return UI_RC_NO_WINSOCK;
  296. }
  297. }
  298. // Check that person is not already in the conference.
  299. if (GetConEntry((LPSTR) pcszNodeAddress))
  300. {
  301. hr = UI_RC_ALREADY_IN_CONFERENCE;
  302. }
  303. else
  304. {
  305. hr = StartConnection((LPSTR) pcszNodeAddress,
  306. CONF_CON_PENDING_INVITE,
  307. aInfo,
  308. cInfo,
  309. m_fSecure,
  310. phRequest);
  311. }
  312. if (NO_ERROR != hr)
  313. {
  314. ERROR_OUT(("Error adding connection"));
  315. }
  316. }
  317. else
  318. {
  319. hr = (pcszNodeAddress == NULL) ? UI_RC_NO_ADDRESS : UI_RC_BAD_PARAMETER;
  320. ERROR_OUT(("DCRNCConference::Invite: invalid parameters, hr=0x%x", (UINT) hr));
  321. }
  322. // Sit and wait for the connection to complete before continuing.
  323. DebugExitHRESULT(DCRNCConference::Invite, hr);
  324. return hr;
  325. }
  326. STDMETHODIMP DCRNCConference::
  327. CancelInvite ( REQUEST_HANDLE hRequest )
  328. {
  329. DebugEntry(DCRNCConference::CancelInvite);
  330. InterfaceEntry();
  331. HRESULT hr;
  332. CLogicalConnection *pConEntry = (CLogicalConnection *) hRequest;
  333. if (NULL != pConEntry)
  334. {
  335. ConnectionHandle hConn = pConEntry->GetInviteReqConnHandle();
  336. ASSERT(NULL != hConn);
  337. g_pIT120ControlSap->CancelInviteRequest(m_nConfID, hConn);
  338. hr = NO_ERROR;
  339. }
  340. else
  341. {
  342. hr = UI_RC_BAD_PARAMETER;
  343. }
  344. DebugExitHRESULT(DCRNCConference::CancelInvite, hr);
  345. return hr;
  346. }
  347. STDMETHODIMP DCRNCConference::
  348. GetCred ( PBYTE *ppbCred, DWORD *pcbCred )
  349. {
  350. DebugEntry(DCRNCConference::GetCred);
  351. HRESULT hr = UI_RC_INTERNAL_ERROR;
  352. if (m_pbCred)
  353. {
  354. *ppbCred = m_pbCred;
  355. *pcbCred = m_cbCred;
  356. hr = NO_ERROR;
  357. }
  358. DebugExitHRESULT(DCRNCConference::GetCred, hr);
  359. return hr;
  360. }
  361. STDMETHODIMP DCRNCConference::
  362. InviteResponse ( BOOL fResponse )
  363. {
  364. DebugEntry(DCRNCConference::InviteResponse);
  365. InterfaceEntry();
  366. HRESULT hrResponse = fResponse ? NO_ERROR : UI_RC_USER_REJECTED;
  367. HRESULT hr = InviteResponse(hrResponse);
  368. DebugExitHRESULT(DCRNCConferenceManager::InviteResponse, hr);
  369. return hr;
  370. }
  371. HRESULT DCRNCConference::
  372. InviteResponse ( HRESULT hrResponse )
  373. {
  374. DebugEntry(DCRNCConference::InviteResponse);
  375. InterfaceEntry();
  376. GCCResult Result = ::MapRCToGCCResult(hrResponse);
  377. GCCError GCCrc = g_pIT120ControlSap->ConfInviteResponse(
  378. m_nConfID,
  379. NULL,
  380. m_fSecure,
  381. NULL, // domain parms
  382. 0, // number_of_network_addresses
  383. NULL, // local_network_address_list
  384. g_nVersionRecords, // number_of_user_data_members
  385. g_ppVersionUserData, // user_data_list
  386. Result);
  387. if ((GCCrc == GCC_RESULT_SUCCESSFUL) && (Result == GCC_RESULT_SUCCESSFUL))
  388. {
  389. // Have successfully posted an invite response acceptance.
  390. // Note that the conference is expecting permission to
  391. // announce its presence.
  392. m_eT120State = T120C_ST_PENDING_ANNOUNCE_PERMISSION;
  393. }
  394. else
  395. {
  396. // Have rejected/failed a request to be invited into a conference.
  397. // Remove the references that were created to track the potential
  398. // new conference.
  399. g_pNCConfMgr->RemoveConference(this);
  400. }
  401. HRESULT hr = ::GetGCCRCDetails(GCCrc);
  402. DebugExitHRESULT(DCRNCConferenceManager::InviteResponse, hr);
  403. return hr;
  404. }
  405. STDMETHODIMP DCRNCConference::
  406. JoinResponse ( BOOL fResponse )
  407. {
  408. DebugEntry(DCRNCConference::JoinResponse);
  409. InterfaceEntry();
  410. HRESULT hr;
  411. CJoinIndWork *pJoinUI = g_pNCConfMgr->PeekFirstJoinIndWorkItem();
  412. if (NULL != pJoinUI)
  413. {
  414. if (pJoinUI->GetConference() == this)
  415. {
  416. if (fResponse && pJoinUI->GetConEntry()->NewLocalAddress())
  417. {
  418. AnnouncePresence();
  419. }
  420. hr = pJoinUI->Respond(fResponse ? GCC_RESULT_SUCCESSFUL : GCC_RESULT_USER_REJECTED);
  421. // Done responding to event, so can now remove from list and process
  422. // another pending event.
  423. // Note: since the handling of the previous event is still
  424. // potentially on the stack, this can cause the stack to grow,
  425. // but this should not be a problem for Win32.
  426. g_pNCConfMgr->RemoveJoinIndWorkItem(pJoinUI);
  427. }
  428. else
  429. {
  430. hr = UI_RC_BAD_PARAMETER;
  431. }
  432. }
  433. else
  434. {
  435. ERROR_OUT(("DCRNCConference::JoinResponse: Empty m_JoinIndWorkList, fResponse=%u", fResponse));
  436. hr = UI_RC_INTERNAL_ERROR;
  437. }
  438. DebugExitHRESULT(DCRNCConference::JoinResponse, hr);
  439. return hr;
  440. }
  441. STDMETHODIMP DCRNCConference::
  442. LaunchGuid
  443. (
  444. const GUID *pcGUID,
  445. UINT auNodeIDs[],
  446. UINT cNodes
  447. )
  448. {
  449. DebugEntry(DCRNCConference::LaunchGuid);
  450. InterfaceEntry();
  451. HRESULT hr;
  452. if (NULL != pcGUID)
  453. {
  454. //
  455. // We probably should support conference-wide app invoke by
  456. // cNodes==0 and auNodeIDs==NULL.
  457. // Implement it later...
  458. //
  459. if ((0 != cNodes) || (NULL != auNodeIDs))
  460. {
  461. // UserID is a short. We have to translate these UserID to a new array.
  462. // Try not to allocate memory for small array.
  463. UserID *pNodeIDs;
  464. const UINT c_cRemote = 16;
  465. UserID auidRemote[c_cRemote];
  466. if (cNodes <= c_cRemote)
  467. {
  468. pNodeIDs = auidRemote;
  469. }
  470. else
  471. {
  472. pNodeIDs = new UserID[cNodes];
  473. if (NULL == pNodeIDs)
  474. {
  475. hr = UI_RC_OUT_OF_MEMORY;
  476. goto MyExit;
  477. }
  478. }
  479. // Copy all the node IDs.
  480. for (UINT i = 0; i < cNodes; i++)
  481. {
  482. pNodeIDs[i] = (UserID)auNodeIDs[i];
  483. }
  484. // Construct the key
  485. GCCError GCCrc;
  486. GCCObjectKey * pAppKey;
  487. GCCAppProtocolEntity AppEntity;
  488. GCCAppProtocolEntity * pAppEntity;
  489. BYTE h221Key[CB_H221_GUIDKEY];
  490. ::CreateH221AppKeyFromGuid(h221Key, (GUID *) pcGUID);
  491. ::ZeroMemory(&AppEntity, sizeof(AppEntity));
  492. pAppKey = &AppEntity.session_key.application_protocol_key;
  493. pAppKey->key_type = GCC_H221_NONSTANDARD_KEY;
  494. pAppKey->h221_non_standard_id.length = sizeof(h221Key);
  495. pAppKey->h221_non_standard_id.value = h221Key;
  496. // AppEntity.session_key.session_id = 0; // default session
  497. // AppEntity.number_of_expected_capabilities = 0; // no capabilities
  498. // AppEntity.expected_capabilities_list = NULL;
  499. AppEntity.startup_channel_type = MCS_NO_CHANNEL_TYPE_SPECIFIED;
  500. AppEntity.must_be_invoked = TRUE;
  501. pAppEntity = &AppEntity;
  502. GCCrc = g_pIT120ControlSap->AppletInvokeRequest(m_nConfID, 1, &pAppEntity, cNodes, pNodeIDs);
  503. hr = ::GetGCCRCDetails(GCCrc);
  504. if (NO_ERROR != hr)
  505. {
  506. ERROR_OUT(("DCRNCConference::LaunchGuid: AppletInvokeRequest failed, GCCrc=%u", GCCrc));
  507. }
  508. if (pNodeIDs != auidRemote)
  509. {
  510. delete [] pNodeIDs;
  511. }
  512. }
  513. else
  514. {
  515. hr = UI_RC_BAD_PARAMETER;
  516. ERROR_OUT(("DCRNCConference::LaunchGuid: invalid combination, cNodes=%u. auNodeIDs=0x%p", cNodes, auNodeIDs));
  517. }
  518. }
  519. else
  520. {
  521. hr = UI_RC_BAD_PARAMETER;
  522. ERROR_OUT(("DCRNCConference::LaunchGuid: null pcGUID"));
  523. }
  524. MyExit:
  525. DebugExitHRESULT(DCRNCConference::LaunchGuid, hr);
  526. return hr;
  527. }
  528. STDMETHODIMP DCRNCConference::
  529. SetUserData
  530. (
  531. const GUID *pcGUID,
  532. UINT cbData,
  533. LPVOID pData
  534. )
  535. {
  536. DebugEntry(DCRNCConference::SetUserData);
  537. InterfaceEntry();
  538. HRESULT hr;
  539. if (0 != cbData || NULL != pData)
  540. {
  541. hr = m_LocalUserData.AddUserData((GUID *) pcGUID, cbData, pData);
  542. }
  543. else
  544. {
  545. hr = UI_RC_BAD_PARAMETER;
  546. ERROR_OUT(("DCRNCConference::SetUserData: invalid combination, cbData=%u. pData=0x%p", cbData, pData));
  547. }
  548. DebugExitHRESULT(DCRNCConference::SetUserData, hr);
  549. return hr;
  550. }
  551. STDMETHODIMP_(BOOL) DCRNCConference::
  552. IsSecure ()
  553. {
  554. return m_fSecure;
  555. }
  556. STDMETHODIMP DCRNCConference::
  557. SetSecurity ( BOOL fSecure )
  558. {
  559. m_fSecure = fSecure;
  560. return S_OK;
  561. }
  562. STDMETHODIMP DCRNCConference::
  563. UpdateUserData(void)
  564. {
  565. DebugEntry(DCRNCConference::UpdateUserData);
  566. InterfaceEntry();
  567. HRESULT hr = AnnouncePresence();
  568. DebugExitHRESULT(DCRNCConference::UpdateUserData, hr);
  569. return hr;
  570. }
  571. STDMETHODIMP DCRNCConference::
  572. GetLocalAddressList
  573. (
  574. LPWSTR pwszBuffer,
  575. UINT cchBuffer
  576. )
  577. {
  578. DebugEntry(DCRNCConference::GetLocalAddressList);
  579. InterfaceEntry();
  580. HRESULT hr;
  581. UINT cAddrs;
  582. LPCSTR *pAddresses = NULL;
  583. ASSERT(cchBuffer > 1); // buffer should have enough room for a double NULL terminator
  584. hr = m_LocalAddressList.GetLocalAddressList(&cAddrs, &pAddresses);
  585. if (NO_ERROR == hr)
  586. {
  587. LPWSTR pwszPos = pwszBuffer;
  588. for (UINT i = 0; i < cAddrs; i++)
  589. {
  590. ASSERT(pAddresses[i]);
  591. LPWSTR pwszAddress = ::AnsiToUnicode(pAddresses[i]);
  592. UINT cchAddress = ::My_strlenW(pwszAddress);
  593. if ((cchBuffer - (pwszPos - pwszBuffer)) <
  594. (RNC_GCC_TRANSPORT_AND_SEPARATOR_LENGTH + cchAddress + 2))
  595. {
  596. // NOTE: +2 insures room for the two '\0' chars
  597. // If there isn't room, break out here:
  598. delete [] pwszAddress;
  599. break;
  600. }
  601. LStrCpyW(pwszPos, RNC_GCC_TRANSPORT_AND_SEPARATOR_UNICODE);
  602. pwszPos += RNC_GCC_TRANSPORT_AND_SEPARATOR_LENGTH;
  603. LStrCpyW(pwszPos, pwszAddress);
  604. pwszPos += cchAddress;
  605. *pwszPos = L'\0';
  606. pwszPos++;
  607. delete [] pwszAddress;
  608. }
  609. if ((UINT)(pwszPos - pwszBuffer) < cchBuffer)
  610. {
  611. *pwszPos = L'\0';
  612. }
  613. if (0 == cAddrs)
  614. {
  615. // No addresses in the string, so insure that the string returned is L"\0\0"
  616. pwszPos[1] = L'\0';
  617. }
  618. delete [] pAddresses;
  619. }
  620. else
  621. {
  622. ERROR_OUT(("DCRNCConference::GetLocalAddressList: GetLocalAddressList failed, hr=0x%x", (UINT) hr));
  623. }
  624. DebugExitHRESULT(DCRNCConference::GetLocalAddressList, hr);
  625. return hr;
  626. }
  627. STDMETHODIMP_(UINT) DCRNCConference::
  628. GetParentNodeID(void)
  629. {
  630. DebugEntry(DCRNCConference::GetConferenceID);
  631. InterfaceEntry();
  632. GCCNodeID nidParent = 0;
  633. g_pIT120ControlSap->GetParentNodeID(m_nConfID, &nidParent);
  634. DebugExitINT(DCRNCConference::GetConferenceID, (UINT) nidParent);
  635. return (UINT) nidParent;
  636. }
  637. CLogicalConnection * DCRNCConference::
  638. GetConEntry ( ConnectionHandle hInviteIndConn )
  639. {
  640. CLogicalConnection *pConEntry = NULL;
  641. m_ConnList.Reset();
  642. while (NULL != (pConEntry = m_ConnList.Iterate()))
  643. {
  644. if (pConEntry->GetInviteReqConnHandle() == hInviteIndConn)
  645. {
  646. break;
  647. }
  648. }
  649. return pConEntry;
  650. }
  651. CLogicalConnection * DCRNCConference::
  652. GetConEntry ( LPSTR pszNodeAddress )
  653. {
  654. CLogicalConnection *pConEntry = NULL;
  655. m_ConnList.Reset();
  656. while (NULL != (pConEntry = m_ConnList.Iterate()))
  657. {
  658. if (0 == ::lstrcmpA(pConEntry->GetNodeAddress(), pszNodeAddress))
  659. {
  660. break;
  661. }
  662. }
  663. return pConEntry;
  664. }
  665. CLogicalConnection * DCRNCConference::
  666. GetConEntryByNodeID ( GCCNodeID nid )
  667. {
  668. CLogicalConnection *pConEntry = NULL;
  669. m_ConnList.Reset();
  670. while (NULL != (pConEntry = m_ConnList.Iterate()))
  671. {
  672. if (nid == pConEntry->GetConnectionNodeID())
  673. {
  674. break;
  675. }
  676. }
  677. return pConEntry;
  678. }
  679. void DCRNCConference::
  680. FirstRoster(void)
  681. {
  682. DebugEntry(DCRNCConference::FirstRoster);
  683. // Great! We are now in a conference and outside of any
  684. // T120 callback, so that calling back into T120 will not
  685. // deadlock applications.
  686. // Let the applications know about the conference,
  687. // and then ask for a roster update.
  688. if (m_eT120State == T120C_ST_PENDING_ROSTER_MESSAGE)
  689. {
  690. m_eT120State = T120C_ST_CONF_STARTED;
  691. NotifyConferenceComplete(NO_ERROR);
  692. RefreshRoster();
  693. }
  694. DebugExitVOID(DCRNCConference::FirstRoster);
  695. }
  696. /****************************************************************************/
  697. /* HandleGCCCallback() - see erncconf.h */
  698. /****************************************************************************/
  699. // LONCHANC: Merged to T120 Conference.
  700. /****************************************************************************/
  701. /* ValidatePassword() - Validates a join request by checking the supplied */
  702. /* password with the one set when the conference was setup. */
  703. /****************************************************************************/
  704. BOOL DCRNCConference::
  705. ValidatePassword ( GCCChallengeRequestResponse *pPasswordChallenge )
  706. {
  707. PBYTE pbPasswordChallenge = NULL;
  708. DWORD cbPasswordChallenge = 0;
  709. CHash hashObj;
  710. OSVERSIONINFO osvi;
  711. BOOL bSuccess = FALSE;
  712. HANDLE hToken = 0;
  713. osvi.dwOSVersionInfoSize = sizeof(osvi);
  714. if (FALSE == ::GetVersionEx (&osvi))
  715. {
  716. ERROR_OUT(("GetVersionEx() failed!"));
  717. }
  718. if (!(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId && g_bRDS) &&
  719. (NULL == m_pbHashedPassword) && (NULL == m_pszNumericPassword) && (NULL == m_pwszPassword))
  720. {
  721. bSuccess = TRUE;
  722. goto Cleanup;
  723. }
  724. if ((pPasswordChallenge == NULL) ||
  725. (pPasswordChallenge->password_challenge_type != GCC_PASSWORD_IN_THE_CLEAR))
  726. {
  727. bSuccess = FALSE;
  728. goto Cleanup;
  729. }
  730. //
  731. // We are going to verify the password as a logon
  732. //
  733. if ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId && g_bRDS)
  734. {
  735. BYTE InfoBuffer[1024];
  736. PTOKEN_GROUPS ptgGroups = (PTOKEN_GROUPS)InfoBuffer;
  737. DWORD dwInfoBufferSize;
  738. PSID psidAdministrators;
  739. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  740. CHAR lpszBuf[1024];
  741. ASSERT(NULL != pPasswordChallenge->u.password_in_the_clear.text_string);
  742. WideCharToMultiByte( CP_ACP, 0,
  743. pPasswordChallenge->u.password_in_the_clear.text_string,
  744. -1,lpszBuf,256,NULL,NULL);
  745. CHAR* lp = (CHAR *)_StrChr(lpszBuf, ':');
  746. if (NULL == lp)
  747. {
  748. ERROR_OUT(("Expected separator in logon pwd"));
  749. bSuccess = FALSE;
  750. goto Cleanup;
  751. }
  752. *lp++ = '\0';
  753. CHAR* lpPw = (CHAR *)_StrChr(lp, ':');
  754. if (NULL == lpPw)
  755. {
  756. ERROR_OUT(("Expected 2nd separator in logon pwd"));
  757. bSuccess = FALSE;
  758. goto Cleanup;
  759. }
  760. *lpPw++ = '\0';
  761. if (0 == strlen(lpPw))
  762. {
  763. WARNING_OUT(("Short password in logon pwd"));
  764. bSuccess = FALSE;
  765. goto Cleanup;
  766. }
  767. bSuccess = LogonUser(lpszBuf, lp, lpPw, LOGON32_LOGON_NETWORK,
  768. LOGON32_PROVIDER_DEFAULT, &hToken);
  769. if (!bSuccess)
  770. {
  771. WARNING_OUT(("LogonUser failed %d", GetLastError()));
  772. goto Cleanup;
  773. }
  774. if( !AllocateAndInitializeSid(&siaNtAuthority, 2,
  775. SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS,
  776. 0,0,0,0,0,0, &psidAdministrators ))
  777. {
  778. ERROR_OUT(("Error getting admin group sid: %d", GetLastError()));
  779. bSuccess = FALSE;
  780. goto Cleanup;
  781. }
  782. // assume that we don't find the admin SID.
  783. bSuccess = FALSE;
  784. if (!CheckTokenMembership(hToken, psidAdministrators, &bSuccess))
  785. {
  786. ERROR_OUT(("Error checking token membership: %d", GetLastError()));
  787. bSuccess = FALSE;
  788. }
  789. FreeSid(psidAdministrators);
  790. //
  791. // If this worked there is no need to go on
  792. //
  793. if ( bSuccess )
  794. {
  795. bSuccess = TRUE;
  796. goto Cleanup;
  797. }
  798. //
  799. // Check for group membership in the RDS users group on
  800. // the local machine.
  801. //
  802. ASSERT(FALSE == bSuccess);
  803. DWORD cbSid = 0;
  804. DWORD cbDomain = 0;
  805. SID_NAME_USE SidNameUse = SidTypeGroup;
  806. if ( LookupAccountName ( NULL, SZRDSGROUP, NULL, &cbSid,
  807. NULL, &cbDomain, &SidNameUse )
  808. || ERROR_INSUFFICIENT_BUFFER == GetLastError() )
  809. {
  810. PSID pSid = new BYTE[cbSid];
  811. LPTSTR lpszDomain = new TCHAR[cbDomain];
  812. if ( pSid && lpszDomain )
  813. {
  814. if ( LookupAccountName ( NULL, SZRDSGROUP, pSid,
  815. &cbSid, lpszDomain, &cbDomain, &SidNameUse ))
  816. {
  817. //
  818. // Make sure what we found is a group
  819. //
  820. if ( SidTypeGroup == SidNameUse ||
  821. SidTypeAlias == SidNameUse )
  822. {
  823. if (!CheckTokenMembership(hToken, pSid, &bSuccess))
  824. {
  825. ERROR_OUT(("Error checking token membership: %d", GetLastError()));
  826. bSuccess = FALSE;
  827. }
  828. }
  829. else
  830. {
  831. WARNING_OUT(("SZRDSGROUP was not a group or alias? its a %d",
  832. SidNameUse ));
  833. }
  834. }
  835. else
  836. {
  837. ERROR_OUT(("LookupAccountName (2) failed: %d",
  838. GetLastError()));
  839. }
  840. }
  841. else
  842. {
  843. ERROR_OUT(("Alloc of sid or domain failed"));
  844. }
  845. delete [] pSid;
  846. delete [] lpszDomain;
  847. }
  848. else
  849. {
  850. WARNING_OUT(("LookupAccountName (1) failed: %d", GetLastError()));
  851. }
  852. return bSuccess;
  853. }
  854. //
  855. // We are going to hash the password and compare it to the
  856. // stored hash
  857. //
  858. if (m_pbHashedPassword != NULL)
  859. {
  860. if (NULL != pPasswordChallenge->u.password_in_the_clear.text_string)
  861. {
  862. cbPasswordChallenge = hashObj.GetHashedData((LPBYTE)pPasswordChallenge->u.password_in_the_clear.text_string,
  863. sizeof(WCHAR)*lstrlenW(pPasswordChallenge->u.password_in_the_clear.text_string),
  864. (void **) &pbPasswordChallenge);
  865. }
  866. else if (NULL != pPasswordChallenge->u.password_in_the_clear.numeric_string)
  867. {
  868. int cch = lstrlenA((PSTR)pPasswordChallenge->u.password_in_the_clear.numeric_string);
  869. LPWSTR lpwszNumPassword = new WCHAR[cch+1];
  870. MultiByteToWideChar(CP_ACP, 0, (PSTR)pPasswordChallenge->u.password_in_the_clear.numeric_string,
  871. -1, lpwszNumPassword, cch+1);
  872. int cwch = lstrlenW(lpwszNumPassword);
  873. cbPasswordChallenge = hashObj.GetHashedData((LPBYTE)lpwszNumPassword, sizeof(WCHAR)*lstrlenW(lpwszNumPassword), (void **) &pbPasswordChallenge);
  874. delete []lpwszNumPassword;
  875. }
  876. else
  877. {
  878. bSuccess = FALSE;
  879. goto Cleanup;
  880. }
  881. if (m_cbHashedPassword != cbPasswordChallenge)
  882. {
  883. bSuccess = FALSE;
  884. goto Cleanup;
  885. }
  886. if (0 == memcmp(m_pbHashedPassword, pbPasswordChallenge, cbPasswordChallenge))
  887. {
  888. bSuccess = TRUE;
  889. goto Cleanup;
  890. }
  891. else
  892. {
  893. bSuccess = FALSE;
  894. goto Cleanup;
  895. }
  896. }
  897. else if (m_pwszPassword != NULL)
  898. {
  899. // We have a text password
  900. if ((pPasswordChallenge->u.password_in_the_clear.text_string == NULL) ||
  901. (0 != ::My_strcmpW(m_pwszPassword,
  902. pPasswordChallenge->u.password_in_the_clear.text_string)))
  903. {
  904. bSuccess = FALSE;
  905. goto Cleanup;
  906. }
  907. else
  908. {
  909. bSuccess = TRUE;
  910. goto Cleanup;
  911. }
  912. }
  913. else
  914. {
  915. // We have a numeric password
  916. if ((pPasswordChallenge->u.password_in_the_clear.numeric_string == NULL) ||
  917. (::lstrcmpA(m_pszNumericPassword,
  918. (PSTR) pPasswordChallenge->u.password_in_the_clear.numeric_string)))
  919. {
  920. bSuccess = FALSE;
  921. goto Cleanup;
  922. }
  923. else
  924. {
  925. bSuccess = TRUE;
  926. goto Cleanup;
  927. }
  928. }
  929. Cleanup:
  930. if(hToken)
  931. {
  932. CloseHandle(hToken);
  933. }
  934. return bSuccess;
  935. }
  936. /****************************************************************************/
  937. /* Join() - see erncconf.h */
  938. /****************************************************************************/
  939. HRESULT DCRNCConference::
  940. Join
  941. (
  942. LPSTR pszNodeAddress,
  943. PUSERDATAINFO pInfo,
  944. UINT nInfo,
  945. LPCWSTR _wszPassword
  946. )
  947. {
  948. HRESULT hr = NO_ERROR;
  949. DebugEntry(DCRNCConference::Join);
  950. /*
  951. * Set the password that will be used by the JoinWrapper() method.
  952. * The password will be deleted after the Join is complete.
  953. * The m_pwszPassword member is only set for the top providers
  954. * protecting conferences.
  955. */
  956. if (! ::IsEmptyStringW (_wszPassword))
  957. {
  958. // Store the password; we will need it later
  959. m_pwszPassword = ::My_strdupW(_wszPassword);
  960. if (NULL == m_pwszPassword)
  961. {
  962. hr = UI_RC_OUT_OF_MEMORY;
  963. }
  964. }
  965. /************************************************************************/
  966. /* SFR 6206. The apps treat joining a conference at a remote site as */
  967. /* an "incoming" call. (i.e they discard any local data and accept the */
  968. /* msgs/WB contents from the conference we are joining). */
  969. /************************************************************************/
  970. if (NO_ERROR == hr)
  971. {
  972. m_fIncoming = TRUE;
  973. hr = StartConnection(pszNodeAddress,
  974. CONF_CON_PENDING_JOIN,
  975. pInfo,
  976. nInfo,
  977. m_fSecure);
  978. }
  979. if (NO_ERROR != hr)
  980. {
  981. ERROR_OUT(("Error starting connection"));
  982. }
  983. /************************************************************************/
  984. /* We now sit and wait for the connection to complete before */
  985. /* continuing. */
  986. /************************************************************************/
  987. DebugExitHRESULT(DCRNCConference::Join, hr);
  988. return hr;
  989. }
  990. /****************************************************************************/
  991. /* NotifyConferenceComplete() - the generic conference has finished its */
  992. /* attempt to start. */
  993. /****************************************************************************/
  994. void DCRNCConference::
  995. NotifyConferenceComplete ( HRESULT hr )
  996. {
  997. DebugEntry(DCRNCConference::NotifyConferenceComplete);
  998. /************************************************************************/
  999. /* If the attempt fails, action depends on whether this is the first or */
  1000. /* second attempt. */
  1001. /************************************************************************/
  1002. if (NO_ERROR != hr)
  1003. {
  1004. TRACE_OUT(("Attempt to start failed"));
  1005. // LONCHANC: please do not remove this chunk of code.
  1006. #ifdef ENABLE_START_REMOTE
  1007. if (m_eState == CONF_ST_PENDING_START_REMOTE_FIRST)
  1008. {
  1009. TRACE_OUT(("Try second conference type"));
  1010. StartSecondConference(hr);
  1011. return;
  1012. }
  1013. #endif // ENABLE_START_REMOTE
  1014. }
  1015. else
  1016. {
  1017. TRACE_OUT(("Conference started OK."));
  1018. m_eState = CONF_ST_STARTED;
  1019. }
  1020. g_pNCConfMgr->NotifyConferenceComplete(this, m_fIncoming, hr);
  1021. DebugExitVOID(DCRNCConference::NotifyConferenceComplete);
  1022. }
  1023. /****************************************************************************/
  1024. /* NotifyConnectionComplete() - see erncconf.h */
  1025. /****************************************************************************/
  1026. HRESULT DCRNCConference::
  1027. NotifyConnectionComplete
  1028. (
  1029. CLogicalConnection *pConEntry,
  1030. HRESULT hr
  1031. )
  1032. {
  1033. DebugEntry(DCRNCConference::NotifyConnectionComplete);
  1034. // This function is the state machine
  1035. // for bringing up a conferencing protocol.
  1036. // It manages getting the physical connection and trying
  1037. // T120 and R1.1.
  1038. // A connection has started.
  1039. // Subsequent action depends on the pending state for the connection.
  1040. // First filter out internal (success) return codes.
  1041. if (NO_ERROR != hr)
  1042. {
  1043. // Failed to get a physical connection.
  1044. WARNING_OUT(("Failed to start connection"));
  1045. if (pConEntry->GetState() != CONF_CON_PENDING_INVITE)
  1046. {
  1047. // Put the connection in a failed state before notifying the user.
  1048. // This is because notifying the user can cause GCC events to fire,
  1049. // and, in particular, a JoinRequest failure which must be ignored.
  1050. pConEntry->SetState(CONF_CON_ERROR);
  1051. g_pNCConfMgr->NotifyConferenceComplete(this, m_fIncoming, hr);
  1052. goto MyExit;
  1053. }
  1054. // Drop through for invite failures.
  1055. }
  1056. switch (pConEntry->GetState())
  1057. {
  1058. // LONCHANC: please do not remove this chunk of code.
  1059. #ifdef ENABLE_START_REMOTE
  1060. case CONF_CON_PENDING_START:
  1061. /****************************************************************/
  1062. /* Check we are in the correct state. */
  1063. /****************************************************************/
  1064. if ( (m_eState != CONF_ST_PENDING_CONNECTION) &&
  1065. (m_eState != CONF_ST_LOCAL_PENDING_RECREATE))
  1066. {
  1067. ERROR_OUT(("Bad state to start in..."));
  1068. goto MyExit;
  1069. }
  1070. pConEntry->SetState(CONF_CON_CONNECTED);
  1071. /****************************************************************/
  1072. /* The connection has started OK. we now try to establish */
  1073. /* either a T120 or a backlevel conference, depending on the */
  1074. /* starting order. */
  1075. /****************************************************************/
  1076. if (NO_ERROR == hr)
  1077. {
  1078. hr = StartFirstConference();
  1079. }
  1080. else
  1081. {
  1082. ERROR_OUT(("Invalid response in notify connection complete"));
  1083. }
  1084. break;
  1085. #endif // ENABLE_START_REMOTE
  1086. case CONF_CON_PENDING_JOIN:
  1087. // pConEntry->m_eState = CONF_CON_CONNECTED;
  1088. // Joining a new conference.
  1089. // Create a new generic conference and
  1090. // call its Join() entry point.
  1091. hr = NewT120Conference();
  1092. if (NO_ERROR == hr)
  1093. {
  1094. hr = JoinWrapper(pConEntry, m_pwszPassword);
  1095. // Delete the set password
  1096. if (m_pwszPassword != NULL)
  1097. {
  1098. delete m_pwszPassword;
  1099. m_pwszPassword = NULL;
  1100. }
  1101. }
  1102. else
  1103. {
  1104. ERROR_OUT(("Error %d joining conference", hr));
  1105. goto MyExit;
  1106. }
  1107. break;
  1108. case CONF_CON_PENDING_INVITE:
  1109. hr = pConEntry->InviteConnectResult(hr);
  1110. break;
  1111. default :
  1112. ERROR_OUT(("Unknown action %d", pConEntry->GetState()));
  1113. break;
  1114. }
  1115. MyExit:
  1116. DebugExitVOID(DCRNCConference::NotifyConnectionComplete);
  1117. return hr;
  1118. }
  1119. HRESULT DCRNCConference::
  1120. JoinWrapper
  1121. (
  1122. CLogicalConnection *pConEntry,
  1123. LPCWSTR _wszPassword
  1124. )
  1125. {
  1126. DebugEntry(DCRNCConference::JoinWrapper);
  1127. // Going asynchronous, so allow events to fire.
  1128. pConEntry->ReArm();
  1129. HRESULT hr = T120Join(pConEntry->GetNodeAddress(),
  1130. pConEntry->IsConnectionSecure(),
  1131. m_pwszConfName,
  1132. pConEntry->GetUserDataList(),
  1133. _wszPassword);
  1134. if (NO_ERROR == hr)
  1135. {
  1136. m_eState = CONF_ST_STARTED;
  1137. }
  1138. else
  1139. {
  1140. pConEntry->Grab();
  1141. ERROR_OUT(("Error %d joining conference", hr));
  1142. g_pNCConfMgr->NotifyConferenceComplete(this, m_fIncoming, hr);
  1143. }
  1144. DebugExitHRESULT(DCRNCConference::JoinWrapper, hr);
  1145. return hr;
  1146. }
  1147. /****************************************************************************/
  1148. /* NotifyRosterChanged() - see erncconf.hpp. */
  1149. /****************************************************************************/
  1150. void DCRNCConference::
  1151. NotifyRosterChanged ( PNC_ROSTER pRoster )
  1152. {
  1153. DebugEntry(DCRNCConference::NotifyRosterChanged);
  1154. // Add the conference name and ID to the roster.
  1155. pRoster->pwszConferenceName = m_pwszConfName;
  1156. pRoster->uConferenceID = m_nConfID;
  1157. /************************************************************************/
  1158. /* Pass the new roster up to the CM */
  1159. /************************************************************************/
  1160. g_pCallbackInterface->OnRosterChanged((CONF_HANDLE) this, pRoster);
  1161. DebugExitVOID(DCRNCConference::NotifyRosterChanged);
  1162. }
  1163. /****************************************************************************/
  1164. /* StartConnection - add a new connection to our connection list. */
  1165. /****************************************************************************/
  1166. HRESULT DCRNCConference::
  1167. StartConnection
  1168. (
  1169. LPSTR pszNodeAddress,
  1170. LOGICAL_CONN_STATE eAction,
  1171. PUSERDATAINFO pInfo,
  1172. UINT nInfo,
  1173. BOOL fSecure,
  1174. REQUEST_HANDLE * phRequest
  1175. )
  1176. {
  1177. HRESULT hr = NO_ERROR;
  1178. CLogicalConnection *pConEntry = NULL;
  1179. DebugEntry(DCRNCConference::StartConnection);
  1180. DBG_SAVE_FILE_LINE
  1181. pConEntry = NewLogicalConnection(eAction, NULL, pInfo, nInfo, fSecure);
  1182. if (NULL != pConEntry)
  1183. {
  1184. // Set node address
  1185. pConEntry->SetNodeAddress(::My_strdupA(pszNodeAddress));
  1186. //
  1187. // LONCHANC: Fire the conn-entry event.
  1188. //
  1189. hr = NotifyConnectionComplete(pConEntry, NO_ERROR);
  1190. if( NO_ERROR != hr )
  1191. {
  1192. pConEntry->Delete( hr );
  1193. pConEntry = NULL;
  1194. }
  1195. }
  1196. else
  1197. {
  1198. hr = UI_RC_OUT_OF_MEMORY;
  1199. }
  1200. if (phRequest)
  1201. {
  1202. // Return context as the connection entry, if required.
  1203. *phRequest = (REQUEST_HANDLE *)pConEntry;
  1204. }
  1205. DebugExitHRESULT(DCRNCConference::StartConnection, hr);
  1206. return hr;
  1207. }
  1208. // LONCHANC: please do not remove this chunk of code.
  1209. #ifdef ENABLE_START_REMOTE
  1210. /****************************************************************************/
  1211. /* StartFirstConference() - start the first attempt to create a conference. */
  1212. /****************************************************************************/
  1213. void DCRNCConference::
  1214. StartFirstConference(void)
  1215. {
  1216. BOOL result = FALSE;
  1217. HRESULT hr;
  1218. DebugEntry(DCRNCConference::StartFirstConference);
  1219. hr = NewT120Conference();
  1220. if (NO_ERROR != hr)
  1221. {
  1222. ERROR_OUT(("Failed to create new conference"));
  1223. m_eState = CONF_ST_UNINITIALIZED;
  1224. goto MyExit;
  1225. }
  1226. /************************************************************************/
  1227. /* Call the StartRemote() entry point. */
  1228. /************************************************************************/
  1229. hr = T120StartRemote(m_pszFirstRemoteNodeAddress);
  1230. if (hr)
  1231. {
  1232. WARNING_OUT(("Failed to start remote, rc %d", hr));
  1233. goto MyExit;
  1234. }
  1235. m_eState = CONF_ST_PENDING_START_REMOTE_FIRST;
  1236. result = TRUE;
  1237. MyExit:
  1238. /************************************************************************/
  1239. /* If we failed to start the first conference, try to start the second */
  1240. /* type of conference in the starting order. */
  1241. /************************************************************************/
  1242. if (!result)
  1243. {
  1244. TRACE_OUT(("Failed to start first conference."));
  1245. StartSecondConference(hr);
  1246. }
  1247. DebugExitVOID(DCRNCConference::StartFirstConference);
  1248. }
  1249. #endif // ENABLE_START_REMOTE
  1250. // LONCHANC: please do not remove this chunk of code.
  1251. #ifdef ENABLE_START_REMOTE
  1252. /****************************************************************************/
  1253. /* StartSecondConference() - start the second attempt to create a */
  1254. /* conference. */
  1255. /****************************************************************************/
  1256. void DCRNCConference::
  1257. StartSecondConference ( HRESULT FirstConferenceStatus )
  1258. {
  1259. BOOL result = FALSE;
  1260. HRESULT hr = NO_ERROR;
  1261. DebugEntry(DCRNCConference::StartSecondConference);
  1262. hr = FirstConferenceStatus;
  1263. #if 0 // LONCHANC: very weird code
  1264. goto MyExit;
  1265. /************************************************************************/
  1266. /* Call the StartRemote() entry point. */
  1267. /************************************************************************/
  1268. hr = T120StartRemote(m_pszFirstRemoteNodeAddress);
  1269. if (NO_ERROR != hr)
  1270. {
  1271. WARNING_OUT(("Failed to start remote, rc %d", hr));
  1272. goto MyExit;
  1273. }
  1274. m_eState = CONF_ST_PENDING_START_REMOTE_SECOND;
  1275. result = TRUE;
  1276. MyExit:
  1277. #endif // 0
  1278. /************************************************************************/
  1279. /* If we have failed to start any type of conference, tell CM about it. */
  1280. /************************************************************************/
  1281. if (!result)
  1282. {
  1283. TRACE_OUT(("Failed to start Second conference."));
  1284. g_pNCConfMgr->NotifyConferenceComplete(this, m_fIncoming, hr);
  1285. }
  1286. DebugExitVOID(DCRNCConference::StartSecondConference);
  1287. }
  1288. #endif // ENABLE_START_REMOTE
  1289. /****************************************************************************/
  1290. /* StartLocal() - see erncconf.h */
  1291. /****************************************************************************/
  1292. HRESULT DCRNCConference::
  1293. StartLocal ( LPCWSTR _wszPassword, PBYTE pbHashedPassword, DWORD cbHashedPassword)
  1294. {
  1295. HRESULT hr = NO_ERROR;
  1296. DebugEntry(DCRNCConference::StartLocal);
  1297. /*
  1298. * Set the password that will be used to protect the conference.
  1299. * against unauthorized Join requests.
  1300. * The password is only set for the top providers
  1301. * protecting conferences.
  1302. * If the password is a number it will be stored in m_pszNumericPassword.
  1303. * Otherwise, it will be stored in m_pwszPassword.
  1304. */
  1305. if (NULL != pbHashedPassword)
  1306. {
  1307. m_pbHashedPassword = new BYTE[cbHashedPassword];
  1308. if (NULL == m_pbHashedPassword)
  1309. {
  1310. hr = UI_RC_OUT_OF_MEMORY;
  1311. }
  1312. else
  1313. {
  1314. memcpy(m_pbHashedPassword, pbHashedPassword, cbHashedPassword);
  1315. m_cbHashedPassword = cbHashedPassword;
  1316. }
  1317. }
  1318. else if (! ::IsEmptyStringW(_wszPassword))
  1319. {
  1320. if (::UnicodeIsNumber(_wszPassword))
  1321. {
  1322. m_pszNumericPassword = ::UnicodeToAnsi(_wszPassword);
  1323. if (m_pszNumericPassword == NULL)
  1324. {
  1325. hr = UI_RC_OUT_OF_MEMORY;
  1326. }
  1327. }
  1328. else
  1329. {
  1330. m_pwszPassword = ::My_strdupW(_wszPassword);
  1331. if (NULL == m_pwszPassword)
  1332. {
  1333. hr = UI_RC_OUT_OF_MEMORY;
  1334. }
  1335. }
  1336. }
  1337. /************************************************************************/
  1338. /* Dont need to bother getting a physical connection. Just create a */
  1339. /* new T120 conference and call its StartLocal() entry point */
  1340. /************************************************************************/
  1341. if (NO_ERROR == hr)
  1342. {
  1343. hr = NewT120Conference();
  1344. if (NO_ERROR == hr)
  1345. {
  1346. hr = T120StartLocal(m_fSecure);
  1347. if (NO_ERROR == hr)
  1348. {
  1349. m_eState = CONF_ST_PENDING_T120_START_LOCAL;
  1350. }
  1351. }
  1352. }
  1353. DebugExitHRESULT(DCRNCConference::StartLocal, hr);
  1354. return hr;
  1355. }
  1356. // LONCHANC: please do not remove this chunk of code.
  1357. #ifdef ENABLE_START_REMOTE
  1358. /****************************************************************************/
  1359. /* StartRemote() - see erncconf.h */
  1360. /****************************************************************************/
  1361. HRESULT DCRNCConference::
  1362. StartRemote ( LPSTR pszNodeAddress )
  1363. {
  1364. HRESULT hr;
  1365. DebugEntry(DCRNCConference::StartRemote);
  1366. /************************************************************************/
  1367. /* Store the node details */
  1368. /************************************************************************/
  1369. m_pszFirstRemoteNodeAddress = ::My_strdupA(pszNodeAddress);
  1370. if (NULL != m_pszFirstRemoteNodeAddress)
  1371. {
  1372. /************************************************************************/
  1373. /* We need to set the conference state before trying to start a new */
  1374. /* connection - the connection may synchronously call us back and we */
  1375. /* want to be able to handle the callback correctly. */
  1376. /************************************************************************/
  1377. m_eState = CONF_ST_PENDING_CONNECTION;
  1378. /************************************************************************/
  1379. /* Start a new physical connection. */
  1380. /************************************************************************/
  1381. hr = StartConnection(m_pszFirstRemoteNodeAddress, CONF_CON_PENDING_START, NULL, NULL);
  1382. if (NO_ERROR != hr)
  1383. {
  1384. ERROR_OUT(("Error adding connection"));
  1385. m_eState = CONF_ST_UNINITIALIZED;
  1386. }
  1387. /************************************************************************/
  1388. /* We now sit and wait for the connection to complete before */
  1389. /* continuing. */
  1390. /************************************************************************/
  1391. }
  1392. else
  1393. {
  1394. ERROR_OUT(("DCRNCConference::StartRemote: can't duplicate node address"));
  1395. hr = UI_RC_OUT_OF_MEMORY;
  1396. m_eState = CONF_ST_UNINITIALIZED;
  1397. }
  1398. DebugExitHRESULT(DCRNCConference::StartRemote, hr);
  1399. return hr;
  1400. }
  1401. #endif // ENABLE_START_REMOTE
  1402. /****************************************************************************/
  1403. /* StartIncoming() - see erncconf.h */
  1404. /****************************************************************************/
  1405. HRESULT DCRNCConference::
  1406. StartIncoming(void)
  1407. {
  1408. DebugEntry(DCRNCConference::StartIncoming);
  1409. /************************************************************************/
  1410. /* Set the incoming flag. */
  1411. /************************************************************************/
  1412. m_fIncoming = TRUE;
  1413. /************************************************************************/
  1414. /* Create a new T120 conference and call its StartIncoming entry point. */
  1415. /************************************************************************/
  1416. HRESULT hr = NewT120Conference();
  1417. if (NO_ERROR == hr)
  1418. {
  1419. m_eState = CONF_ST_STARTED;
  1420. }
  1421. else
  1422. {
  1423. WARNING_OUT(("Failed to create new local conference"));
  1424. }
  1425. DebugExitHRESULT(DCRNCConference::StartIncoming, hr);
  1426. return hr;
  1427. }
  1428. CLogicalConnection::
  1429. CLogicalConnection
  1430. (
  1431. PCONFERENCE pConf,
  1432. LOGICAL_CONN_STATE eAction,
  1433. ConnectionHandle hConnection,
  1434. PUSERDATAINFO pInfo,
  1435. UINT nInfo,
  1436. BOOL fSecure
  1437. )
  1438. :
  1439. CRefCount(MAKE_STAMP_ID('C','L','N','E')),
  1440. m_pszNodeAddress(NULL),
  1441. m_eState(eAction),
  1442. m_pConf(pConf),
  1443. m_nidConnection(0),
  1444. m_hInviteReqConn(hConnection),
  1445. m_hConnection(hConnection),
  1446. m_pLocalAddress(NULL),
  1447. m_fEventGrabbed(FALSE),
  1448. m_fSecure(fSecure)
  1449. {
  1450. DebugEntry(CLogicalConnection::CLogicalConnection);
  1451. if(nInfo)
  1452. {
  1453. for (UINT i = 0 ; i < nInfo; i++, pInfo++)
  1454. {
  1455. m_UserDataInfoList.AddUserData(pInfo->pGUID, pInfo->cbData, pInfo->pData);
  1456. }
  1457. }
  1458. if ((eAction == CONF_CON_INVITED) ||
  1459. (eAction == CONF_CON_JOINED))
  1460. {
  1461. Grab(); // No events to fire.
  1462. }
  1463. DebugExitVOID(CLogicalConnection::CLogicalConnection);
  1464. }
  1465. CLogicalConnection::
  1466. ~CLogicalConnection(void)
  1467. {
  1468. DebugEntry(CLogicalConnection::~CLogicalConnection);
  1469. ASSERT((m_eState == CONF_CON_CONNECTED) ||
  1470. (m_eState == CONF_CON_ERROR));
  1471. delete m_pszNodeAddress;
  1472. DebugExitVOID(CLogicalConnection::~CLogicalConnection);
  1473. }
  1474. BOOL CLogicalConnection::
  1475. NewLocalAddress(void)
  1476. {
  1477. BOOL bNewAddress;
  1478. m_pConf->AddLocalAddress(m_hConnection, &bNewAddress, &m_pLocalAddress);
  1479. return bNewAddress;
  1480. }
  1481. HRESULT CLogicalConnection::
  1482. InviteConnectResult ( HRESULT hr )
  1483. {
  1484. DebugEntry(CLogicalConnection::InviteConnectResult);
  1485. if (NO_ERROR == hr)
  1486. {
  1487. /****************************************************************/
  1488. /* Check the state - we should be fully initialized and have a */
  1489. /* generic conference by this stage. */
  1490. /****************************************************************/
  1491. if (m_pConf->m_eState != CONF_ST_STARTED)
  1492. {
  1493. ERROR_OUT(("Bad state %d", m_pConf->m_eState));
  1494. hr = UI_NO_SUCH_CONFERENCE;
  1495. }
  1496. else
  1497. {
  1498. // Now have a connection to the conference, so go do invite.
  1499. // Note that this may not be the only invite if the user invites
  1500. // several people into the conference before the connection is up.
  1501. ReArm(); // So that connection going down fires off event handling
  1502. hr = m_pConf->T120Invite(m_pszNodeAddress,
  1503. m_fSecure,
  1504. &m_UserDataInfoList,
  1505. &m_hInviteReqConn);
  1506. if (NO_ERROR != hr)
  1507. {
  1508. Grab();
  1509. }
  1510. }
  1511. }
  1512. if (NO_ERROR != hr)
  1513. {
  1514. InviteComplete(hr);
  1515. }
  1516. DebugExitHRESULT(CLogicalConnection::InviteConnectResult, hr);
  1517. return hr;
  1518. }
  1519. void DCRNCConference::
  1520. InviteComplete
  1521. (
  1522. ConnectionHandle hInviteReqConn,
  1523. HRESULT result,
  1524. PT120PRODUCTVERSION pVersion
  1525. )
  1526. {
  1527. CLogicalConnection * pConEntry;
  1528. DebugEntry(DCRNCConference::InviteComplete);
  1529. pConEntry = GetConEntry(hInviteReqConn);
  1530. if (pConEntry == NULL)
  1531. {
  1532. ERROR_OUT(("Unable to match invite response with request"));
  1533. return;
  1534. }
  1535. pConEntry->SetConnectionHandle(hInviteReqConn);
  1536. pConEntry->InviteComplete(result, pVersion);
  1537. DebugExitVOID(DCRNCConference::InviteComplete);
  1538. }
  1539. HRESULT CLocalAddressList::
  1540. AddLocalAddress
  1541. (
  1542. ConnectionHandle connection_handle,
  1543. BOOL *pbNewAddress,
  1544. CLocalAddress **ppLocalAddrToRet
  1545. )
  1546. {
  1547. HRESULT hr = UI_RC_OUT_OF_MEMORY;
  1548. CLocalAddress * pLocalAddress = NULL;
  1549. char szLocalAddress[64];
  1550. int nLocalAddress = sizeof(szLocalAddress);
  1551. DebugEntry(CLocalAddressList::AddLocalAddress);
  1552. *pbNewAddress = FALSE;
  1553. ASSERT (g_pMCSController != NULL);
  1554. if (g_pMCSController->GetLocalAddress (connection_handle, szLocalAddress,
  1555. &nLocalAddress)) {
  1556. DBG_SAVE_FILE_LINE
  1557. pLocalAddress = new CLocalAddress(szLocalAddress);
  1558. if (pLocalAddress) {
  1559. if (!IS_EMPTY_STRING(pLocalAddress->m_pszLocalAddress)) {
  1560. BOOL fFound = FALSE;
  1561. CLocalAddress *p;
  1562. Reset();
  1563. while (NULL != (p = Iterate()))
  1564. {
  1565. if (0 == ::lstrcmpA(p->m_pszLocalAddress, szLocalAddress))
  1566. {
  1567. fFound = TRUE;
  1568. break;
  1569. }
  1570. }
  1571. if (! fFound)
  1572. {
  1573. ASSERT(NULL == p);
  1574. Append(pLocalAddress);
  1575. }
  1576. else
  1577. {
  1578. ASSERT(NULL != p);
  1579. pLocalAddress->Release();
  1580. (pLocalAddress = p)->AddRef();
  1581. }
  1582. hr = NO_ERROR;
  1583. }
  1584. else
  1585. {
  1586. pLocalAddress->Release(); // Remove when no longer referenced
  1587. pLocalAddress = NULL;
  1588. }
  1589. }
  1590. }
  1591. *ppLocalAddrToRet = pLocalAddress;
  1592. DebugExitHRESULT(CLocalAddressList::AddLocalAddress, hr);
  1593. return hr;
  1594. }
  1595. HRESULT CLocalAddressList::
  1596. GetLocalAddressList
  1597. (
  1598. UINT *pnAddresses,
  1599. LPCSTR **ppaAddresses
  1600. )
  1601. {
  1602. CLocalAddress * pAddress;
  1603. LPCSTR * pConnection;
  1604. LPCSTR * apConn = NULL;
  1605. HRESULT hr = NO_ERROR;
  1606. DebugEntry(CLocalAddressList::GetLocalAddressList);
  1607. if (! IsEmpty())
  1608. {
  1609. DBG_SAVE_FILE_LINE
  1610. if (NULL == (apConn = new LPCSTR[GetCount()]))
  1611. {
  1612. hr = UI_RC_OUT_OF_MEMORY;
  1613. }
  1614. }
  1615. if (NULL == apConn)
  1616. {
  1617. *pnAddresses = 0;
  1618. }
  1619. else
  1620. {
  1621. hr = NO_ERROR;
  1622. *pnAddresses = GetCount();
  1623. pConnection = apConn;
  1624. Reset();
  1625. while (NULL != (pAddress = Iterate()))
  1626. {
  1627. *pConnection++ = pAddress->m_pszLocalAddress;
  1628. }
  1629. }
  1630. *ppaAddresses = apConn;
  1631. DebugExitHRESULT(CLocalAddressList::GetLocalAddressList, hr);
  1632. return hr;
  1633. }
  1634. void CLocalAddressList::
  1635. EndReference ( CLocalAddress *pLocalAddress )
  1636. {
  1637. DebugEntry(CLocalAddressList::EndReference);
  1638. if (pLocalAddress->Release() == 0)
  1639. {
  1640. Remove(pLocalAddress);
  1641. }
  1642. DebugExitVOID(CLocalAddressList::EndReference);
  1643. }
  1644. CLocalAddress::CLocalAddress(PCSTR szLocalAddress)
  1645. :
  1646. CRefCount(MAKE_STAMP_ID('L','A','D','R'))
  1647. {
  1648. m_pszLocalAddress = ::My_strdupA(szLocalAddress);
  1649. }
  1650. void CLogicalConnection::
  1651. InviteComplete
  1652. (
  1653. HRESULT hrStatus,
  1654. PT120PRODUCTVERSION pVersion
  1655. )
  1656. {
  1657. DebugEntry(CLogicalConnection::InviteComplete);
  1658. // Don't want user calling us back in
  1659. // InviteConferenceResult to delete the conference
  1660. // causing this object to be deleted whilst
  1661. // in it.
  1662. AddRef();
  1663. // Should only handle an invite complete if there is one pending.
  1664. // Otherwise, this is most likely the result of entering this function
  1665. // after telling the user that the invite has failed for some other
  1666. // reason (e.g. a physical connection going down).
  1667. // In these cases, just ignore the invite complete event.
  1668. if (m_eState == CONF_CON_PENDING_INVITE)
  1669. {
  1670. // Invite complete will generate an event, so grab it.
  1671. Grab();
  1672. if (hrStatus != NO_ERROR)
  1673. {
  1674. m_eState = CONF_CON_ERROR;
  1675. }
  1676. else
  1677. {
  1678. m_eState = CONF_CON_CONNECTED;
  1679. if (NewLocalAddress())
  1680. {
  1681. m_pConf->AnnouncePresence();
  1682. }
  1683. }
  1684. g_pCallbackInterface->OnInviteResult(
  1685. (CONF_HANDLE) m_pConf,
  1686. (REQUEST_HANDLE) this,
  1687. m_nidConnection,
  1688. hrStatus,
  1689. pVersion);
  1690. if (hrStatus != NO_ERROR)
  1691. {
  1692. // Remove conentry from conference if invite fails.
  1693. Delete(hrStatus);
  1694. }
  1695. }
  1696. Release();
  1697. DebugExitVOID(CLogicalConnection::InviteComplete);
  1698. }
  1699. void CLogicalConnection::
  1700. Delete ( HRESULT hrReason )
  1701. {
  1702. DebugEntry(CLogicalConnection::Delete);
  1703. // WARNING, WARNING, WARNING:
  1704. // This method gets re-entered on the stack.
  1705. // Note guards in code below.
  1706. if (NULL != m_pConf)
  1707. {
  1708. PCONFERENCE pThisConf = m_pConf;
  1709. PCONFERENCE pConfToFree = NULL;
  1710. m_pConf = NULL;
  1711. // The connection is going away, so remove the reference to the
  1712. // associated local connection (if any).
  1713. if (NULL != m_pLocalAddress)
  1714. {
  1715. pThisConf->EndReference(m_pLocalAddress);
  1716. m_pLocalAddress = NULL;
  1717. }
  1718. if (m_eState == CONF_CON_INVITED)
  1719. {
  1720. // The conference associated with the entry was invited into the conference,
  1721. // so remove the conference and all of its connections.
  1722. m_eState = CONF_CON_ERROR; // Only do this once
  1723. pConfToFree = pThisConf;
  1724. }
  1725. // If there is a pending event on the connection,
  1726. // then try to grab it and notify the requestor
  1727. // that the request has failed.
  1728. // Note that the event handler may itself end up
  1729. // recalling this function, so it refcounts the
  1730. // CLogicalConnection to prevent it from being destructed
  1731. // too soon.
  1732. if (Grab())
  1733. {
  1734. pThisConf->NotifyConnectionComplete(this, hrReason);
  1735. }
  1736. // Set the connection state to be in error.
  1737. // Note that this is done after firing the event because
  1738. // otherwise a failed connection attempt to a disabled transport
  1739. // would cause the local conference to be destroyed by
  1740. // NotifyConnectionComplete().
  1741. m_eState = CONF_CON_ERROR;
  1742. // Sever the connection entry with the conference record.
  1743. pThisConf->m_ConnList.Remove(this);
  1744. // Now destroy the conentry once any pending event has fired -
  1745. // there is only a pending connection request or a pending
  1746. // request to join/invite/create a conference, and never both.
  1747. Release();
  1748. if (NULL != pConfToFree)
  1749. {
  1750. g_pNCConfMgr->RemoveConference(pConfToFree);
  1751. }
  1752. }
  1753. DebugExitVOID(CLogicalConnection::Delete);
  1754. }
  1755. BOOL FindSocketNumber(DWORD nid, SOCKET * socket_number)
  1756. {
  1757. (*socket_number) = 0;
  1758. ASSERT(g_pNCConfMgr != NULL);
  1759. return g_pNCConfMgr->FindSocketNumber((GCCNodeID) nid, socket_number);
  1760. }
  1761. // DCRNCConference::FindSocketNumber
  1762. // Given a GCCNodeID, finds a socket number associated with that id.
  1763. // Returns TRUE if we are directly connected topology-wise to the node, FALSE if not.
  1764. BOOL DCRNCConference::
  1765. FindSocketNumber
  1766. (
  1767. GCCNodeID nid,
  1768. SOCKET *socket_number
  1769. )
  1770. {
  1771. CLogicalConnection *pConEntry;
  1772. m_ConnList.Reset();
  1773. while (NULL != (pConEntry = m_ConnList.Iterate()))
  1774. {
  1775. if (pConEntry->GetConnectionNodeID() == nid)
  1776. {
  1777. // Found it!
  1778. g_pMCSController->FindSocketNumber(pConEntry->GetConnectionHandle(), socket_number);
  1779. return TRUE;
  1780. }
  1781. }
  1782. return FALSE;
  1783. }
  1784. ULONG DCRNCConference::
  1785. GetNodeName(GCCNodeID NodeId, LPSTR pszBuffer, ULONG cbBufSize)
  1786. {
  1787. LPSTR pszName = m_NodeIdNameList.Find(NodeId);
  1788. if (pszName)
  1789. {
  1790. ::lstrcpynA(pszBuffer, pszName, cbBufSize);
  1791. return lstrlenA(pszName);
  1792. }
  1793. return 0;
  1794. }
  1795. ULONG DCRNCConference::
  1796. GetUserGUIDData(GCCNodeID NodeId, GUID *pGuid,
  1797. LPBYTE pbBuffer, ULONG cbBufSize)
  1798. {
  1799. CNCUserDataList *pUserDataList = m_UserDataList.Find(NodeId);
  1800. GCCUserData *pUserData;
  1801. if (pUserDataList)
  1802. {
  1803. pUserData = pUserDataList->GetUserGUIDData(pGuid);
  1804. if (pUserData)
  1805. {
  1806. if (pbBuffer)
  1807. {
  1808. ::CopyMemory(pbBuffer, pUserData->octet_string->value + sizeof(GUID),
  1809. min(cbBufSize, pUserData->octet_string->length - sizeof(GUID)));
  1810. }
  1811. return pUserData->octet_string->length - sizeof(GUID);
  1812. }
  1813. // The GUID is not found
  1814. }
  1815. // The NodeId is not found
  1816. return 0;
  1817. }
  1818. void DCRNCConference::
  1819. UpdateNodeIdNameListAndUserData(PGCCMessage message)
  1820. {
  1821. GCCNodeID NodeId;
  1822. LPSTR pszName;
  1823. LPWSTR pwszNodeName;
  1824. GCCNodeRecord *pNodeRecord;
  1825. PGCCConferenceRoster pConfRost;
  1826. USHORT count;
  1827. PGCCUserData pGccUserData;
  1828. USHORT count2;
  1829. CNCUserDataList *pUserDataList;
  1830. ASSERT (message->message_type == GCC_ROSTER_REPORT_INDICATION);
  1831. pConfRost = message->u.conf_roster_report_indication.conference_roster;
  1832. for (count = 0; count < pConfRost->number_of_records; count++)
  1833. {
  1834. pNodeRecord = pConfRost->node_record_list[count];
  1835. NodeId = pNodeRecord->node_id;
  1836. pwszNodeName = pNodeRecord->node_name;
  1837. pszName = m_NodeIdNameList.Find(NodeId);
  1838. if (!pszName)
  1839. {
  1840. int ccnsize = (lstrlenW(pwszNodeName) + 1) * sizeof(WCHAR);
  1841. DBG_SAVE_FILE_LINE
  1842. pszName = new char[ccnsize];
  1843. if (pszName)
  1844. {
  1845. if (WideCharToMultiByte(CP_ACP, 0, pwszNodeName, -1, pszName, ccnsize, NULL, NULL))
  1846. {
  1847. m_NodeIdNameList.Append(NodeId, pszName);
  1848. }
  1849. else
  1850. {
  1851. ERROR_OUT(("ConfMgr::UpdateNodeIdNameList: cannot convert unicode node name"));
  1852. }
  1853. }
  1854. else
  1855. {
  1856. ERROR_OUT(("ConfMgr::UpdateNodeIdNameList: cannot duplicate unicode node name"));
  1857. }
  1858. }
  1859. for (count2 = 0; count2 < pNodeRecord->number_of_user_data_members; count2++)
  1860. {
  1861. pGccUserData = pNodeRecord->user_data_list[count2];
  1862. if (pGccUserData->octet_string->length <= sizeof(GUID))
  1863. continue; // not real user data
  1864. pUserDataList = m_UserDataList.Find(NodeId);
  1865. if (!pUserDataList)
  1866. {
  1867. DBG_SAVE_FILE_LINE
  1868. pUserDataList = new CNCUserDataList;
  1869. m_UserDataList.Append(NodeId, pUserDataList);
  1870. }
  1871. pUserDataList->AddUserData((GUID *)pGccUserData->octet_string->value,
  1872. pGccUserData->octet_string->length - sizeof(GUID),
  1873. pGccUserData->octet_string->value + sizeof(GUID));
  1874. }
  1875. }
  1876. }