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.

802 lines
27 KiB

  1. #include "precomp.h"
  2. #include "events.hpp"
  3. #include "ernccm.hpp"
  4. #include "erncconf.hpp"
  5. #include "erncvrsn.hpp"
  6. #include "nccglbl.hpp"
  7. extern PController g_pMCSController;
  8. GUID g_csguidSecurity = GUID_SECURITY;
  9. CWorkItem::~CWorkItem(void) { } // pure virtual
  10. BOOL GetSecurityInfo(ConnectionHandle connection_handle, PBYTE pInfo, PDWORD pcbInfo);
  11. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  12. //
  13. // Implementation of Methods for CInviteIndWork
  14. //
  15. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  16. CInviteIndWork::
  17. CInviteIndWork
  18. (
  19. PCONFERENCE _pConference,
  20. LPCWSTR _wszCallerID,
  21. PT120PRODUCTVERSION _pRequestorVersion,
  22. GCCUserData **_ppUserData,
  23. UINT _nUserData,
  24. CLogicalConnection * _pConEntry
  25. )
  26. :
  27. CWorkItem(_pConference),
  28. m_pConf(_pConference),
  29. m_pRequestorVersion(_pRequestorVersion),
  30. m_nUserData(_nUserData),
  31. m_fSecure(_pConEntry->IsConnectionSecure())
  32. {
  33. DebugEntry(CInviteIndWork::CInviteIndWork);
  34. // If there is version information, then take a copy of it
  35. // as this is going asynchronous.
  36. if (m_pRequestorVersion)
  37. {
  38. m_RequestorVersion = *m_pRequestorVersion;
  39. }
  40. // Take copy of caller ID.
  41. // Note memory allocation failure proceeds with NULL ID.
  42. m_pwszCallerID = ::My_strdupW(_wszCallerID);
  43. // Create the user data list for the ui
  44. if(_nUserData)
  45. {
  46. DBG_SAVE_FILE_LINE
  47. m_pUserDataList = new USERDATAINFO[_nUserData];
  48. if (NULL != m_pUserDataList)
  49. {
  50. for (UINT i = 0; i < m_nUserData; i++)
  51. {
  52. if ((*_ppUserData)->octet_string->length < sizeof(GUID))
  53. {
  54. // skip this user data
  55. i--;
  56. m_nUserData--;
  57. _ppUserData++;
  58. continue;
  59. }
  60. m_pUserDataList[i].pGUID = (GUID*)(*_ppUserData)->octet_string->value;
  61. m_pUserDataList[i].pData = (*_ppUserData)->octet_string->value + sizeof(GUID);
  62. m_pUserDataList[i].cbData = (*_ppUserData)->octet_string->length - sizeof(GUID);
  63. // Verify security data
  64. if (0 == CompareGuid(m_pUserDataList[i].pGUID, &g_csguidSecurity)) {
  65. // Check data against transport level
  66. PBYTE pbData = NULL;
  67. DWORD cbData = 0;
  68. BOOL fTrust = FALSE;
  69. if (m_pUserDataList[i].cbData != 0 && GetSecurityInfo(_pConEntry->GetConnectionHandle(),NULL,&cbData)) {
  70. if (cbData) {
  71. // We are directly connected, so verify the information
  72. pbData = new BYTE[cbData];
  73. if (NULL != pbData) {
  74. GetSecurityInfo(_pConEntry->GetConnectionHandle(),pbData,&cbData);
  75. if ( m_pUserDataList[i].cbData != cbData ||
  76. memcmp(pbData, m_pUserDataList[i].pData,
  77. cbData)) {
  78. WARNING_OUT(("SECURITY MISMATCH: (%s) vs (%s)", pbData, m_pUserDataList[i].pData));
  79. }
  80. else {
  81. // Verification OK
  82. fTrust = TRUE;
  83. }
  84. delete [] pbData;
  85. }
  86. else {
  87. ERROR_OUT(("Failed to alloc %d bytes for security data verification", cbData));
  88. }
  89. }
  90. }
  91. if (FALSE == fTrust) {
  92. // Leave the security GUID in place, but NULL out the data to signal distrust.
  93. WARNING_OUT(("CInviteIndWork: Nulling out security"));
  94. m_pUserDataList[i].pData = NULL;
  95. m_pUserDataList[i].cbData = 0;
  96. }
  97. }
  98. _ppUserData++;
  99. }
  100. }
  101. else
  102. {
  103. ERROR_OUT(("CInviteIndWork::CInviteIndWork: Out of memory"));
  104. m_nUserData = 0;
  105. }
  106. }
  107. else
  108. {
  109. m_pUserDataList = NULL;
  110. }
  111. DebugExitVOID(CInviteIndWork::CInviteIndWork);
  112. }
  113. CInviteIndWork::
  114. ~CInviteIndWork(void)
  115. {
  116. DebugEntry(CInviteIndWork::~CInviteIndWork);
  117. //
  118. // If we substituted transport security data for roster data,
  119. // free that buffer now
  120. //
  121. delete m_pwszCallerID;
  122. delete [] m_pUserDataList;
  123. DebugExitVOID(CInviteIndWork::~CInviteIndWork);
  124. }
  125. void CInviteIndWork::
  126. DoWork(void)
  127. {
  128. DebugEntry(CInviteIndWork::DoWork);
  129. // Now we are actually processing the invite, validate that there
  130. // are no other conferences of the same name, and, if not, block
  131. // a conference of the same name by setting the conference to be active,
  132. // and give invite request up to the UI.
  133. PCONFERENCE pOtherConf = g_pNCConfMgr->GetConferenceFromName(m_pConf->GetName());
  134. if (NULL == pOtherConf)
  135. {
  136. m_pConf->SetNotifyToDo(TRUE);
  137. g_pCallbackInterface->OnIncomingInviteRequest((CONF_HANDLE) m_pConf,
  138. GetCallerID(),
  139. m_pRequestorVersion,
  140. m_pUserDataList,
  141. m_nUserData,
  142. m_fSecure);
  143. }
  144. else
  145. {
  146. m_pConf->InviteResponse(UI_RC_CONFERENCE_ALREADY_EXISTS);
  147. }
  148. DebugExitVOID(CInviteIndWork::DoWork);
  149. }
  150. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  151. //
  152. // Implementation of Methods for CJoinIndWork
  153. //
  154. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  155. CJoinIndWork::
  156. CJoinIndWork
  157. (
  158. GCCResponseTag Tag,
  159. PCONFERENCE _pConference,
  160. LPCWSTR _wszCallerID,
  161. CLogicalConnection *_pConEntry,
  162. PT120PRODUCTVERSION _pRequestorVersion,
  163. UINT _nUserData,
  164. GCCUserData **_ppUserData,
  165. HRESULT *pRetCode
  166. )
  167. :
  168. CWorkItem(_pConference),
  169. m_nResponseTag(Tag),
  170. m_pConf(_pConference),
  171. m_pConEntry(_pConEntry),
  172. m_pRequestorVersion(_pRequestorVersion),
  173. m_nUserData(_nUserData),
  174. m_pUserDataList(NULL),
  175. m_ppUserData(NULL)
  176. {
  177. DebugEntry(CJoinIndWork::CJoinIndWork);
  178. *pRetCode = NO_ERROR;
  179. #ifdef DEBUG
  180. SOCKET socket_number;
  181. g_pMCSController->FindSocketNumber(m_pConEntry->GetConnectionHandle(),&socket_number);
  182. #endif
  183. // If there is version information, then take a copy of it
  184. // as this is going asynchronous.
  185. if (m_pRequestorVersion)
  186. {
  187. m_RequestorVersion = *m_pRequestorVersion;
  188. }
  189. // Take copy of caller ID because T120
  190. // implementation is not keeping its copy valid
  191. // until the join response.
  192. // Note that memory allocation failure proceeds with
  193. // NULL caller ID.
  194. m_pwszCallerID = ::My_strdupW(_wszCallerID);
  195. // Add the user data list for forwarded join requests and the UI.
  196. if (m_nUserData && NULL != _ppUserData)
  197. {
  198. DBG_SAVE_FILE_LINE
  199. m_pUserDataList = new USERDATAINFO[m_nUserData];
  200. if (NULL != m_pUserDataList)
  201. {
  202. ::ZeroMemory(m_pUserDataList, sizeof(USERDATAINFO) * m_nUserData);
  203. DBG_SAVE_FILE_LINE
  204. m_ppUserData = new GCCUserData * [m_nUserData];
  205. if (NULL != m_ppUserData)
  206. {
  207. ::ZeroMemory(m_ppUserData, sizeof(GCCUserData *) * m_nUserData);
  208. for (UINT i = 0; i < m_nUserData; i++)
  209. {
  210. // Calculate the total size to allocate for this entry.
  211. UINT cbUserDataStructSize = ROUNDTOBOUNDARY(sizeof(GCCUserData));
  212. UINT cbNonStdIDSize = ROUNDTOBOUNDARY((* _ppUserData)->key.h221_non_standard_id.length);
  213. UINT cbOctetStringSize = ROUNDTOBOUNDARY((* _ppUserData)->octet_string->length);
  214. UINT cbTotalSize = cbUserDataStructSize + cbNonStdIDSize + sizeof(OSTR) + cbOctetStringSize;
  215. // Allocate a single memory buffer
  216. DBG_SAVE_FILE_LINE
  217. LPBYTE pData = new BYTE[cbTotalSize];
  218. if (NULL != pData)
  219. {
  220. // Set up pointers
  221. GCCUserData *pUserData = (GCCUserData *) pData;
  222. ::ZeroMemory(pUserData, sizeof(GCCUserData));
  223. pUserData->key.h221_non_standard_id.value = (LPBYTE) (pData + cbUserDataStructSize);
  224. pUserData->octet_string = (LPOSTR) (pData + cbUserDataStructSize + cbNonStdIDSize);
  225. pUserData->octet_string->value = ((LPBYTE) pUserData->octet_string) + sizeof(OSTR);
  226. // Copy user data to prevent it from being lost when callback message is freed.
  227. m_ppUserData[i] = pUserData;
  228. // Copy key
  229. pUserData->key.key_type = (* _ppUserData)->key.key_type;
  230. ASSERT(pUserData->key.key_type == GCC_H221_NONSTANDARD_KEY);
  231. pUserData->key.h221_non_standard_id.length = (* _ppUserData)->key.h221_non_standard_id.length;
  232. ::CopyMemory(pUserData->key.h221_non_standard_id.value,
  233. (* _ppUserData)->key.h221_non_standard_id.value,
  234. pUserData->key.h221_non_standard_id.length);
  235. // Copy data
  236. pUserData->octet_string->length = (* _ppUserData)->octet_string->length;
  237. ::CopyMemory(pUserData->octet_string->value,
  238. (* _ppUserData)->octet_string->value,
  239. pUserData->octet_string->length);
  240. m_pUserDataList[i].pGUID = (GUID *)pUserData->octet_string->value;
  241. m_pUserDataList[i].cbData = pUserData->octet_string->length - sizeof(GUID);
  242. m_pUserDataList[i].pData = pUserData->octet_string->value + sizeof(GUID);
  243. if (0 == CompareGuid(m_pUserDataList[i].pGUID, &g_csguidSecurity)) {
  244. // Check data against transport level
  245. PBYTE pbData = NULL;
  246. DWORD cbData = 0;
  247. BOOL fTrust = FALSE;
  248. if (m_pUserDataList[i].cbData != 0 &&
  249. GetSecurityInfo(m_pConEntry->GetConnectionHandle(),NULL,&cbData)) {
  250. if (cbData == NOT_DIRECTLY_CONNECTED) {
  251. // This means we are not directly connected,
  252. // transitivity. so trust by
  253. fTrust = TRUE;
  254. }
  255. else {
  256. pbData = new BYTE[cbData];
  257. if (NULL != pbData) {
  258. GetSecurityInfo(m_pConEntry->GetConnectionHandle(),pbData,&cbData);
  259. // Does the data match?
  260. if (cbData != m_pUserDataList[i].cbData ||
  261. memcmp(pbData,
  262. m_pUserDataList[i].pData,
  263. cbData)) {
  264. WARNING_OUT(("SECURITY MISMATCH: (%s) vs (%s)", pbData, m_pUserDataList[i].pData));
  265. }
  266. else {
  267. fTrust = TRUE;
  268. }
  269. delete [] pbData;
  270. }
  271. else {
  272. ERROR_OUT(("Failed to alloc %d bytes for security data verification", cbData));
  273. }
  274. }
  275. }
  276. if (FALSE == fTrust) {
  277. // Leave the security GUID in place, but NULL out the data to signal distrust.
  278. m_pUserDataList[i].pData = NULL;
  279. m_pUserDataList[i].cbData = 0;
  280. pUserData->octet_string->length = sizeof(GUID);
  281. }
  282. }
  283. _ppUserData++;
  284. }
  285. else
  286. {
  287. ERROR_OUT(("CJoinIndWork::CJoinIndWork: can't create pData, cbTotalSize=%u", cbTotalSize));
  288. *pRetCode = UI_RC_OUT_OF_MEMORY;
  289. }
  290. } // for
  291. }
  292. else
  293. {
  294. ERROR_OUT(("CJoinIndWork::CJoinIndWork: can't create m_ppUserData, m_nUserData=%u", m_nUserData));
  295. *pRetCode = UI_RC_OUT_OF_MEMORY;
  296. }
  297. }
  298. else
  299. {
  300. ERROR_OUT(("CJoinIndWork::CJoinIndWork: can't create m_pUserDataList, m_nUserData=%u", m_nUserData));
  301. *pRetCode = UI_RC_OUT_OF_MEMORY;
  302. }
  303. } // if
  304. DebugExitVOID(CJoinIndWork::CJoinIndWork);
  305. }
  306. CJoinIndWork::
  307. ~CJoinIndWork(void)
  308. {
  309. DebugEntry(CJoinIndWork::~CJoinIndWork);
  310. delete m_pwszCallerID;
  311. for (UINT i = 0; i < m_nUserData; i++)
  312. {
  313. delete (LPBYTE) m_ppUserData[i]; // pData in the constructor
  314. }
  315. delete m_ppUserData;
  316. delete m_pUserDataList;
  317. DebugExitVOID(CJoinIndWork::~CJoinIndWork);
  318. }
  319. void CJoinIndWork::
  320. DoWork(void)
  321. {
  322. DebugEntry(CJoinIndWork::DoWork);
  323. // Notify the core.
  324. g_pCallbackInterface->OnIncomingJoinRequest((CONF_HANDLE) m_pConf,
  325. m_pwszCallerID,
  326. m_pRequestorVersion,
  327. m_pUserDataList,
  328. m_nUserData);
  329. DebugExitVOID(CJoinIndWork::DoWork);
  330. }
  331. HRESULT CJoinIndWork::
  332. Respond ( GCCResult _Result )
  333. {
  334. DebugEntry(CJoinIndWork::Respond);
  335. // It is a response from the core.
  336. HRESULT hr = ::GCCJoinResponseWrapper(m_nResponseTag,
  337. NULL,
  338. _Result,
  339. m_pConf->GetID(),
  340. m_nUserData,
  341. m_ppUserData);
  342. DebugExitHRESULT(CJoinIndWork::Respond, hr);
  343. return hr;
  344. }
  345. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  346. //
  347. // Implementation of Methods for CSequentialWorkList
  348. //
  349. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  350. void CSequentialWorkList::
  351. AddWorkItem ( CWorkItem *pWorkItem )
  352. {
  353. DebugEntry(CSequentialWorkList::AddWorkItem);
  354. Append(pWorkItem);
  355. // If first entry in list, then kick off handler.
  356. if (1 == GetCount())
  357. {
  358. pWorkItem->DoWork();
  359. }
  360. DebugExitVOID(CSequentialWorkList::AddWorkItem);
  361. }
  362. void CSequentialWorkList::
  363. RemoveWorkItem ( CWorkItem *pWorkItem )
  364. {
  365. DebugEntry(CSequentialWorkList::RemoveWorkItem);
  366. if (pWorkItem)
  367. {
  368. // Make a note as to whether we are going to remove the head
  369. // work item in the list.
  370. BOOL bHeadItemRemoved = (pWorkItem == PeekHead());
  371. // Remove work item from list and destroy it.
  372. if (Remove(pWorkItem))
  373. {
  374. delete pWorkItem;
  375. // If there are more entries in the list, and we removed the
  376. // first one, then start the work of the next one in line.
  377. // Note that before doing this, the pointer to the workitem
  378. // was NULLed out (above) to prevent reentracy problems.
  379. if (bHeadItemRemoved && !IsEmpty())
  380. {
  381. PeekHead()->DoWork();
  382. }
  383. }
  384. else
  385. {
  386. ASSERT(! bHeadItemRemoved);
  387. }
  388. }
  389. DebugExitVOID(CSequentialWorkList::RemoveWorkItem);
  390. }
  391. void CSequentialWorkList::
  392. PurgeListEntriesByOwner ( DCRNCConference *pOwner )
  393. {
  394. CWorkItem *pWorkItem;
  395. DebugEntry(CSequentialWorkList::PurgeListEntriesByOwner);
  396. if (NULL != pOwner)
  397. {
  398. // Note that head entry is removed last to stop work being started
  399. // on other entries in the list that are owned by pOwner.
  400. // Check to ensure there is a head item in the list.
  401. if (NULL != (pWorkItem = PeekHead()))
  402. {
  403. // Remember we are going to remove the head.
  404. BOOL fHeadToRemove = pWorkItem->IsOwnedBy(pOwner);
  405. // Walk remaining entries in the list removing them.
  406. BOOL fMoreToRemove;
  407. do
  408. {
  409. fMoreToRemove = FALSE;
  410. Reset();
  411. while (NULL != (pWorkItem = Iterate()))
  412. {
  413. if (pWorkItem->IsOwnedBy(pOwner))
  414. {
  415. Remove(pWorkItem);
  416. delete pWorkItem;
  417. fMoreToRemove = TRUE;
  418. break;
  419. }
  420. }
  421. }
  422. while (fMoreToRemove);
  423. // Now done removing all entries, including the head if needed...
  424. if (fHeadToRemove && ! IsEmpty())
  425. {
  426. PeekHead()->DoWork();
  427. }
  428. }
  429. }
  430. DebugExitVOID(CSequentialWorkList::PurgeListEntriesByOwner);
  431. }
  432. void CSequentialWorkList::
  433. DeleteList(void)
  434. {
  435. CWorkItem *pWorkItem;
  436. while (NULL != (pWorkItem = Get()))
  437. {
  438. delete pWorkItem;
  439. }
  440. }
  441. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  442. //
  443. // Implementation of Methods for CQueryRemoteWork
  444. //
  445. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  446. CQueryRemoteWork::
  447. CQueryRemoteWork
  448. (
  449. LPVOID pCallerContext,
  450. GCCAsymmetryType eAsymType,
  451. LPCSTR pcszNodeAddress,
  452. BOOL fSecure,
  453. HRESULT *pRetCode
  454. )
  455. :
  456. CWorkItem(pCallerContext),
  457. m_hGCCConnHandle(NULL),
  458. m_apConfNames(NULL),
  459. m_fRemoteIsMCU(FALSE),
  460. m_eAsymType(eAsymType),
  461. m_pVersion(NULL),
  462. m_fSecure(fSecure),
  463. m_apConfDescriptors(NULL)
  464. {
  465. DebugEntry(CQueryRemoteWork::CQueryRemoteWork);
  466. char szAddress[RNC_MAX_NODE_STRING_LEN];
  467. ::BuildAddressFromNodeDetails((LPSTR) pcszNodeAddress, &szAddress[0]);
  468. m_pszAddress = ::My_strdupA(&szAddress[0]);
  469. m_hr = (NULL != m_pszAddress) ? NO_ERROR : UI_RC_OUT_OF_MEMORY;
  470. *pRetCode = m_hr;
  471. DebugExitVOID(CQueryRemoteWork::CQueryRemoteWork);
  472. }
  473. CQueryRemoteWork::
  474. ~CQueryRemoteWork(void)
  475. {
  476. LPWSTR *ppTempTargetName;
  477. LPWSTR *ppTempTargetDescriptor;
  478. DebugEntry(CQueryRemoteWork::~CQueryRemoteWork);
  479. // Clean up memory allocated.
  480. if (m_apConfNames)
  481. {
  482. ppTempTargetName = m_apConfNames;
  483. while (*ppTempTargetName)
  484. {
  485. delete *(ppTempTargetName++);
  486. }
  487. delete [] m_apConfNames;
  488. }
  489. if (m_apConfDescriptors)
  490. {
  491. ppTempTargetDescriptor = m_apConfDescriptors;
  492. while (*ppTempTargetDescriptor)
  493. {
  494. delete *(ppTempTargetDescriptor++);
  495. }
  496. delete [] m_apConfDescriptors;
  497. }
  498. delete m_pszAddress;
  499. DebugExitVOID(CQueryRemoteWork::~CQueryRemoteWork);
  500. }
  501. void CQueryRemoteWork::
  502. DoWork(void)
  503. {
  504. GCCError GCCrc;
  505. GCCNodeType nodeType;
  506. GCCAsymmetryIndicator asymmetry_indicator;
  507. DebugEntry(CQueryRemoteWork::DoWork);
  508. ::LoadAnnouncePresenceParameters(&nodeType, NULL, NULL, NULL);
  509. asymmetry_indicator.asymmetry_type = m_eAsymType;
  510. asymmetry_indicator.random_number = 0;
  511. if (asymmetry_indicator.asymmetry_type == GCC_ASYMMETRY_UNKNOWN)
  512. {
  513. m_nRandSeed = (int) ::GetTickCount();
  514. m_LocalAsymIndicator.random_number = ((GenerateRand() << 16) + GenerateRand());
  515. asymmetry_indicator.random_number = m_LocalAsymIndicator.random_number;
  516. m_LocalAsymIndicator.asymmetry_type = GCC_ASYMMETRY_UNKNOWN;
  517. m_fInUnknownQueryRequest = TRUE;
  518. }
  519. GCCrc = g_pIT120ControlSap->ConfQueryRequest(
  520. nodeType,
  521. &asymmetry_indicator,
  522. NULL,
  523. (TransportAddress) m_pszAddress,
  524. m_fSecure,
  525. g_nVersionRecords,
  526. g_ppVersionUserData,
  527. &m_hGCCConnHandle);
  528. TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfQueryRequest, rc=%d", GCCrc));
  529. if (NO_ERROR != (m_hr = ::GetGCCRCDetails(GCCrc)))
  530. {
  531. AsyncQueryRemoteResult();
  532. }
  533. DebugExitHRESULT(CQueryRemoteWork::DoWork, m_hr);
  534. }
  535. void CQueryRemoteWork::
  536. HandleQueryConfirmation ( QueryConfirmMessage * pQueryMessage )
  537. {
  538. UINT NumberOfConferences;
  539. GCCConferenceDescriptor ** ppConferenceDescriptor;
  540. PWSTR * ppTempTargetName;
  541. PWSTR ConferenceTextName;
  542. GCCConferenceName * pGCCConferenceName;
  543. PWSTR * ppTempTargetDescriptor;
  544. PWSTR pwszConfDescriptor=NULL;
  545. HRESULT hrTmp;
  546. DebugEntry(CQueryRemoteWork::HandleQueryConfirmation);
  547. // If no error, then package up information.
  548. m_hr = ::GetGCCResultDetails(pQueryMessage->result);
  549. if (NO_ERROR == m_hr)
  550. {
  551. m_fRemoteIsMCU = (pQueryMessage->node_type == GCC_MCU);
  552. NumberOfConferences = pQueryMessage->number_of_descriptors;
  553. DBG_SAVE_FILE_LINE
  554. m_apConfNames = new PWSTR[NumberOfConferences + 1];
  555. m_apConfDescriptors = new PWSTR[NumberOfConferences + 1];
  556. if (!m_apConfNames || !m_apConfDescriptors)
  557. {
  558. m_hr = UI_RC_OUT_OF_MEMORY;
  559. }
  560. else
  561. {
  562. ppConferenceDescriptor = pQueryMessage->conference_descriptor_list;
  563. ppTempTargetName = m_apConfNames;
  564. ppTempTargetDescriptor = m_apConfDescriptors;
  565. while (NumberOfConferences--)
  566. {
  567. pwszConfDescriptor = (*(ppConferenceDescriptor))->conference_descriptor;
  568. pGCCConferenceName = &(*(ppConferenceDescriptor++))->conference_name;
  569. if (pwszConfDescriptor != NULL)
  570. {
  571. pwszConfDescriptor = ::My_strdupW(pwszConfDescriptor);
  572. }
  573. ConferenceTextName = pGCCConferenceName->text_string;
  574. if (ConferenceTextName != NULL)
  575. {
  576. ConferenceTextName = ::My_strdupW(ConferenceTextName);
  577. if (!ConferenceTextName)
  578. {
  579. // Out of memory, give back what we have.
  580. m_hr = UI_RC_OUT_OF_MEMORY;
  581. break;
  582. }
  583. }
  584. else
  585. if (pGCCConferenceName->numeric_string != NULL)
  586. {
  587. ConferenceTextName = ::AnsiToUnicode((PCSTR)pGCCConferenceName->numeric_string);
  588. if (!ConferenceTextName)
  589. {
  590. // Out of memory, give back what we have.
  591. m_hr = UI_RC_OUT_OF_MEMORY;
  592. break;
  593. }
  594. }
  595. if (ConferenceTextName)
  596. {
  597. *(ppTempTargetName++) = ConferenceTextName;
  598. *(ppTempTargetDescriptor++) = pwszConfDescriptor;
  599. }
  600. }
  601. *ppTempTargetName = NULL;
  602. *ppTempTargetDescriptor = NULL;
  603. }
  604. }
  605. // Copy version information out of message.
  606. m_pVersion = ::GetVersionData(pQueryMessage->number_of_user_data_members,
  607. pQueryMessage->user_data_list);
  608. if (m_pVersion)
  609. {
  610. m_Version = *m_pVersion;
  611. m_pVersion = &m_Version;
  612. }
  613. m_fInUnknownQueryRequest = FALSE;
  614. hrTmp = m_hr;
  615. // Propagate the result directly without posting a message.
  616. SyncQueryRemoteResult();
  617. DebugExitHRESULT(CQueryRemoteWork::HandleQueryConfirmation, hrTmp);
  618. }
  619. void CQueryRemoteWork::
  620. SyncQueryRemoteResult(void)
  621. {
  622. DebugEntry(CQueryRemoteWork::SyncQueryRemoteResult);
  623. // Let the user know the result of his request.
  624. // The user is expected to call Release() after getting the result,
  625. // if he wants to drop the line - and should for errors.
  626. // Also, if the user is being called back before the inline code
  627. // has filled in the handle, then fill it in here - see comments in
  628. // DCRNCConferenceManager::QueryRemote for additional background.
  629. g_pCallbackInterface->OnQueryRemoteResult(
  630. m_pOwner,
  631. m_hr,
  632. m_fRemoteIsMCU,
  633. m_apConfNames,
  634. m_pVersion,
  635. m_apConfDescriptors);
  636. // If we are not inline, and this request made it into
  637. // the sequential work item list,
  638. // then remove from list (which will cause item to be deleted),
  639. // otherwise, just delete item.
  640. g_pQueryRemoteList->RemoveWorkItem(this);
  641. DebugExitVOID(CQueryRemoteWork::SyncQueryRemoteResult);
  642. }
  643. void CQueryRemoteWork::
  644. AsyncQueryRemoteResult(void)
  645. {
  646. g_pNCConfMgr->PostWndMsg(NCMSG_QUERY_REMOTE_FAILURE, (LPARAM) this);
  647. }
  648. int CQueryRemoteWork::
  649. GenerateRand(void)
  650. { // code from CRT
  651. return (((m_nRandSeed = m_nRandSeed * 214013L + 2531011L) >> 16) & 0x7fff);
  652. }
  653. HRESULT CQueryRemoteWorkList::
  654. Cancel ( LPVOID pCallerContext )
  655. {
  656. HRESULT hr = S_FALSE; // if not found
  657. CQueryRemoteWork *p;
  658. Reset();
  659. while (NULL != (p = Iterate()))
  660. {
  661. if (p->IsOwnedBy(pCallerContext))
  662. {
  663. // clean up the underlying plumbing.
  664. g_pIT120ControlSap->CancelConfQueryRequest(p->GetConnectionHandle());
  665. // clean up node controller data.
  666. RemoveWorkItem(p);
  667. hr = S_OK;
  668. break;
  669. }
  670. }
  671. return hr;
  672. }