Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

549 lines
15 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. CWorkItem::~CWorkItem(void) { } // pure virtual
  9. BOOL GetSecurityInfo(ConnectionHandle connection_handle, PBYTE pInfo, PDWORD pcbInfo);
  10. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  11. //
  12. // Implementation of Methods for CInviteIndWork
  13. //
  14. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  15. CInviteIndWork::
  16. CInviteIndWork
  17. (
  18. PCONFERENCE _pConference,
  19. LPCWSTR _wszCallerID,
  20. CLogicalConnection * _pConEntry
  21. )
  22. :
  23. CWorkItem(_pConference),
  24. m_pConf(_pConference),
  25. m_fSecure(_pConEntry->IsConnectionSecure())
  26. {
  27. DebugEntry(CInviteIndWork::CInviteIndWork);
  28. // Take copy of caller ID.
  29. // Note memory allocation failure proceeds with NULL ID.
  30. m_pwszCallerID = ::My_strdupW(_wszCallerID);
  31. DebugExitVOID(CInviteIndWork::CInviteIndWork);
  32. }
  33. CInviteIndWork::
  34. ~CInviteIndWork(void)
  35. {
  36. DebugEntry(CInviteIndWork::~CInviteIndWork);
  37. //
  38. // If we substituted transport security data for roster data,
  39. // free that buffer now
  40. //
  41. delete m_pwszCallerID;
  42. DebugExitVOID(CInviteIndWork::~CInviteIndWork);
  43. }
  44. void CInviteIndWork::
  45. DoWork(void)
  46. {
  47. DebugEntry(CInviteIndWork::DoWork);
  48. // Now we are actually processing the invite, validate that there
  49. // are no other conferences of the same name, and, if not, block
  50. // a conference of the same name by setting the conference to be active,
  51. // and give invite request up to the UI.
  52. PCONFERENCE pOtherConf = g_pNCConfMgr->GetConferenceFromName(m_pConf->GetName());
  53. if (NULL == pOtherConf)
  54. {
  55. m_pConf->SetNotifyToDo(TRUE);
  56. g_pCallbackInterface->OnIncomingInviteRequest((CONF_HANDLE) m_pConf,
  57. GetCallerID(),
  58. m_fSecure);
  59. }
  60. else
  61. {
  62. m_pConf->InviteResponse(UI_RC_CONFERENCE_ALREADY_EXISTS);
  63. }
  64. DebugExitVOID(CInviteIndWork::DoWork);
  65. }
  66. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  67. //
  68. // Implementation of Methods for CJoinIndWork
  69. //
  70. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  71. CJoinIndWork::
  72. CJoinIndWork
  73. (
  74. GCCResponseTag Tag,
  75. PCONFERENCE _pConference,
  76. LPCWSTR _wszCallerID,
  77. CLogicalConnection *_pConEntry,
  78. HRESULT *pRetCode
  79. )
  80. :
  81. CWorkItem(_pConference),
  82. m_nResponseTag(Tag),
  83. m_pConf(_pConference),
  84. m_pConEntry(_pConEntry)
  85. {
  86. DebugEntry(CJoinIndWork::CJoinIndWork);
  87. *pRetCode = NO_ERROR;
  88. #ifdef DEBUG
  89. SOCKET socket_number;
  90. g_pMCSController->FindSocketNumber(m_pConEntry->GetConnectionHandle(),&socket_number);
  91. #endif
  92. // Take copy of caller ID because T120
  93. // implementation is not keeping its copy valid
  94. // until the join response.
  95. // Note that memory allocation failure proceeds with
  96. // NULL caller ID.
  97. m_pwszCallerID = ::My_strdupW(_wszCallerID);
  98. DebugExitVOID(CJoinIndWork::CJoinIndWork);
  99. }
  100. CJoinIndWork::
  101. ~CJoinIndWork(void)
  102. {
  103. DebugEntry(CJoinIndWork::~CJoinIndWork);
  104. delete m_pwszCallerID;
  105. DebugExitVOID(CJoinIndWork::~CJoinIndWork);
  106. }
  107. void CJoinIndWork::
  108. DoWork(void)
  109. {
  110. DebugEntry(CJoinIndWork::DoWork);
  111. // Notify the core.
  112. g_pCallbackInterface->OnIncomingJoinRequest((CONF_HANDLE) m_pConf,
  113. m_pwszCallerID);
  114. DebugExitVOID(CJoinIndWork::DoWork);
  115. }
  116. HRESULT CJoinIndWork::
  117. Respond ( GCCResult _Result )
  118. {
  119. DebugEntry(CJoinIndWork::Respond);
  120. // It is a response from the core.
  121. HRESULT hr = ::GCCJoinResponseWrapper(m_nResponseTag,
  122. NULL,
  123. _Result,
  124. m_pConf->GetID(),
  125. 0, NULL);
  126. DebugExitHRESULT(CJoinIndWork::Respond, hr);
  127. return hr;
  128. }
  129. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  130. //
  131. // Implementation of Methods for CSequentialWorkList
  132. //
  133. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  134. void CSequentialWorkList::
  135. AddWorkItem ( CWorkItem *pWorkItem )
  136. {
  137. DebugEntry(CSequentialWorkList::AddWorkItem);
  138. Append(pWorkItem);
  139. // If first entry in list, then kick off handler.
  140. if (1 == GetCount())
  141. {
  142. pWorkItem->DoWork();
  143. }
  144. DebugExitVOID(CSequentialWorkList::AddWorkItem);
  145. }
  146. void CSequentialWorkList::
  147. RemoveWorkItem ( CWorkItem *pWorkItem )
  148. {
  149. DebugEntry(CSequentialWorkList::RemoveWorkItem);
  150. if (pWorkItem)
  151. {
  152. // Make a note as to whether we are going to remove the head
  153. // work item in the list.
  154. BOOL bHeadItemRemoved = (pWorkItem == PeekHead());
  155. // Remove work item from list and destroy it.
  156. if (Remove(pWorkItem))
  157. {
  158. delete pWorkItem;
  159. // If there are more entries in the list, and we removed the
  160. // first one, then start the work of the next one in line.
  161. // Note that before doing this, the pointer to the workitem
  162. // was NULLed out (above) to prevent reentracy problems.
  163. if (bHeadItemRemoved && !IsEmpty())
  164. {
  165. PeekHead()->DoWork();
  166. }
  167. }
  168. else
  169. {
  170. ASSERT(! bHeadItemRemoved);
  171. }
  172. }
  173. DebugExitVOID(CSequentialWorkList::RemoveWorkItem);
  174. }
  175. void CSequentialWorkList::
  176. PurgeListEntriesByOwner ( DCRNCConference *pOwner )
  177. {
  178. CWorkItem *pWorkItem;
  179. DebugEntry(CSequentialWorkList::PurgeListEntriesByOwner);
  180. if (NULL != pOwner)
  181. {
  182. // Note that head entry is removed last to stop work being started
  183. // on other entries in the list that are owned by pOwner.
  184. // Check to ensure there is a head item in the list.
  185. if (NULL != (pWorkItem = PeekHead()))
  186. {
  187. // Remember we are going to remove the head.
  188. BOOL fHeadToRemove = pWorkItem->IsOwnedBy(pOwner);
  189. // Walk remaining entries in the list removing them.
  190. BOOL fMoreToRemove;
  191. do
  192. {
  193. fMoreToRemove = FALSE;
  194. Reset();
  195. while (NULL != (pWorkItem = Iterate()))
  196. {
  197. if (pWorkItem->IsOwnedBy(pOwner))
  198. {
  199. Remove(pWorkItem);
  200. delete pWorkItem;
  201. fMoreToRemove = TRUE;
  202. break;
  203. }
  204. }
  205. }
  206. while (fMoreToRemove);
  207. // Now done removing all entries, including the head if needed...
  208. if (fHeadToRemove && ! IsEmpty())
  209. {
  210. PeekHead()->DoWork();
  211. }
  212. }
  213. }
  214. DebugExitVOID(CSequentialWorkList::PurgeListEntriesByOwner);
  215. }
  216. void CSequentialWorkList::
  217. DeleteList(void)
  218. {
  219. CWorkItem *pWorkItem;
  220. while (NULL != (pWorkItem = Get()))
  221. {
  222. delete pWorkItem;
  223. }
  224. }
  225. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  226. //
  227. // Implementation of Methods for CQueryRemoteWork
  228. //
  229. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  230. CQueryRemoteWork::
  231. CQueryRemoteWork
  232. (
  233. LPVOID pCallerContext,
  234. GCCAsymmetryType eAsymType,
  235. LPCSTR pcszNodeAddress,
  236. BOOL fSecure,
  237. HRESULT *pRetCode
  238. )
  239. :
  240. CWorkItem(pCallerContext),
  241. m_hGCCConnHandle(NULL),
  242. m_apConfNames(NULL),
  243. m_fRemoteIsMCU(FALSE),
  244. m_eAsymType(eAsymType),
  245. m_fSecure(fSecure),
  246. m_apConfDescriptors(NULL)
  247. {
  248. DebugEntry(CQueryRemoteWork::CQueryRemoteWork);
  249. char szAddress[RNC_MAX_NODE_STRING_LEN];
  250. ::BuildAddressFromNodeDetails((LPSTR) pcszNodeAddress, &szAddress[0]);
  251. m_pszAddress = ::My_strdupA(&szAddress[0]);
  252. m_hr = (NULL != m_pszAddress) ? NO_ERROR : UI_RC_OUT_OF_MEMORY;
  253. *pRetCode = m_hr;
  254. DebugExitVOID(CQueryRemoteWork::CQueryRemoteWork);
  255. }
  256. CQueryRemoteWork::
  257. ~CQueryRemoteWork(void)
  258. {
  259. LPWSTR *ppTempTargetName;
  260. LPWSTR *ppTempTargetDescriptor;
  261. DebugEntry(CQueryRemoteWork::~CQueryRemoteWork);
  262. // Clean up memory allocated.
  263. if (m_apConfNames)
  264. {
  265. ppTempTargetName = m_apConfNames;
  266. while (*ppTempTargetName)
  267. {
  268. delete *(ppTempTargetName++);
  269. }
  270. delete [] m_apConfNames;
  271. }
  272. if (m_apConfDescriptors)
  273. {
  274. ppTempTargetDescriptor = m_apConfDescriptors;
  275. while (*ppTempTargetDescriptor)
  276. {
  277. delete *(ppTempTargetDescriptor++);
  278. }
  279. delete [] m_apConfDescriptors;
  280. }
  281. delete m_pszAddress;
  282. DebugExitVOID(CQueryRemoteWork::~CQueryRemoteWork);
  283. }
  284. void CQueryRemoteWork::
  285. DoWork(void)
  286. {
  287. GCCError GCCrc;
  288. GCCNodeType nodeType;
  289. GCCAsymmetryIndicator asymmetry_indicator;
  290. DebugEntry(CQueryRemoteWork::DoWork);
  291. ::LoadAnnouncePresenceParameters(&nodeType, NULL, NULL, NULL);
  292. asymmetry_indicator.asymmetry_type = m_eAsymType;
  293. asymmetry_indicator.random_number = 0;
  294. if (asymmetry_indicator.asymmetry_type == GCC_ASYMMETRY_UNKNOWN)
  295. {
  296. m_nRandSeed = (int) ::GetTickCount();
  297. m_LocalAsymIndicator.random_number = ((GenerateRand() << 16) + GenerateRand());
  298. asymmetry_indicator.random_number = m_LocalAsymIndicator.random_number;
  299. m_LocalAsymIndicator.asymmetry_type = GCC_ASYMMETRY_UNKNOWN;
  300. m_fInUnknownQueryRequest = TRUE;
  301. }
  302. GCCrc = g_pIT120ControlSap->ConfQueryRequest(
  303. nodeType,
  304. &asymmetry_indicator,
  305. NULL,
  306. (TransportAddress) m_pszAddress,
  307. m_fSecure,
  308. 0,
  309. NULL,
  310. &m_hGCCConnHandle);
  311. TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfQueryRequest, rc=%d", GCCrc));
  312. if (NO_ERROR != (m_hr = ::GetGCCRCDetails(GCCrc)))
  313. {
  314. AsyncQueryRemoteResult();
  315. }
  316. DebugExitHRESULT(CQueryRemoteWork::DoWork, m_hr);
  317. }
  318. void CQueryRemoteWork::
  319. HandleQueryConfirmation ( QueryConfirmMessage * pQueryMessage )
  320. {
  321. UINT NumberOfConferences;
  322. GCCConferenceDescriptor ** ppConferenceDescriptor;
  323. PWSTR * ppTempTargetName;
  324. PWSTR ConferenceTextName;
  325. GCCConferenceName * pGCCConferenceName;
  326. PWSTR * ppTempTargetDescriptor;
  327. PWSTR pwszConfDescriptor=NULL;
  328. HRESULT hrTmp;
  329. DebugEntry(CQueryRemoteWork::HandleQueryConfirmation);
  330. // If no error, then package up information.
  331. m_hr = ::GetGCCResultDetails(pQueryMessage->result);
  332. if (NO_ERROR == m_hr)
  333. {
  334. m_fRemoteIsMCU = (pQueryMessage->node_type == GCC_MCU);
  335. NumberOfConferences = pQueryMessage->number_of_descriptors;
  336. DBG_SAVE_FILE_LINE
  337. m_apConfNames = new PWSTR[NumberOfConferences + 1];
  338. m_apConfDescriptors = new PWSTR[NumberOfConferences + 1];
  339. if (!m_apConfNames || !m_apConfDescriptors)
  340. {
  341. m_hr = UI_RC_OUT_OF_MEMORY;
  342. }
  343. else
  344. {
  345. ppConferenceDescriptor = pQueryMessage->conference_descriptor_list;
  346. ppTempTargetName = m_apConfNames;
  347. ppTempTargetDescriptor = m_apConfDescriptors;
  348. while (NumberOfConferences--)
  349. {
  350. pwszConfDescriptor = (*(ppConferenceDescriptor))->conference_descriptor;
  351. pGCCConferenceName = &(*(ppConferenceDescriptor++))->conference_name;
  352. if (pwszConfDescriptor != NULL)
  353. {
  354. pwszConfDescriptor = ::My_strdupW(pwszConfDescriptor);
  355. }
  356. ConferenceTextName = pGCCConferenceName->text_string;
  357. if (ConferenceTextName != NULL)
  358. {
  359. ConferenceTextName = ::My_strdupW(ConferenceTextName);
  360. if (!ConferenceTextName)
  361. {
  362. // Out of memory, give back what we have.
  363. m_hr = UI_RC_OUT_OF_MEMORY;
  364. break;
  365. }
  366. }
  367. else
  368. if (pGCCConferenceName->numeric_string != NULL)
  369. {
  370. ConferenceTextName = ::AnsiToUnicode((PCSTR)pGCCConferenceName->numeric_string);
  371. if (!ConferenceTextName)
  372. {
  373. // Out of memory, give back what we have.
  374. m_hr = UI_RC_OUT_OF_MEMORY;
  375. break;
  376. }
  377. }
  378. if (ConferenceTextName)
  379. {
  380. *(ppTempTargetName++) = ConferenceTextName;
  381. *(ppTempTargetDescriptor++) = pwszConfDescriptor;
  382. }
  383. }
  384. *ppTempTargetName = NULL;
  385. *ppTempTargetDescriptor = NULL;
  386. }
  387. }
  388. m_fInUnknownQueryRequest = FALSE;
  389. hrTmp = m_hr;
  390. // Propagate the result directly without posting a message.
  391. SyncQueryRemoteResult();
  392. DebugExitHRESULT(CQueryRemoteWork::HandleQueryConfirmation, hrTmp);
  393. }
  394. void CQueryRemoteWork::
  395. SyncQueryRemoteResult(void)
  396. {
  397. DebugEntry(CQueryRemoteWork::SyncQueryRemoteResult);
  398. // Let the user know the result of his request.
  399. // The user is expected to call Release() after getting the result,
  400. // if he wants to drop the line - and should for errors.
  401. // Also, if the user is being called back before the inline code
  402. // has filled in the handle, then fill it in here - see comments in
  403. // DCRNCConferenceManager::QueryRemote for additional background.
  404. g_pCallbackInterface->OnQueryRemoteResult(
  405. m_pOwner,
  406. m_hr,
  407. m_fRemoteIsMCU,
  408. m_apConfNames,
  409. m_apConfDescriptors);
  410. // If we are not inline, and this request made it into
  411. // the sequential work item list,
  412. // then remove from list (which will cause item to be deleted),
  413. // otherwise, just delete item.
  414. g_pQueryRemoteList->RemoveWorkItem(this);
  415. DebugExitVOID(CQueryRemoteWork::SyncQueryRemoteResult);
  416. }
  417. void CQueryRemoteWork::
  418. AsyncQueryRemoteResult(void)
  419. {
  420. g_pNCConfMgr->PostWndMsg(NCMSG_QUERY_REMOTE_FAILURE, (LPARAM) this);
  421. }
  422. int CQueryRemoteWork::
  423. GenerateRand(void)
  424. { // code from CRT
  425. return (((m_nRandSeed = m_nRandSeed * 214013L + 2531011L) >> 16) & 0x7fff);
  426. }
  427. HRESULT CQueryRemoteWorkList::
  428. Cancel ( LPVOID pCallerContext )
  429. {
  430. HRESULT hr = S_FALSE; // if not found
  431. CQueryRemoteWork *p;
  432. Reset();
  433. while (NULL != (p = Iterate()))
  434. {
  435. if (p->IsOwnedBy(pCallerContext))
  436. {
  437. // clean up the underlying plumbing.
  438. g_pIT120ControlSap->CancelConfQueryRequest(p->GetConnectionHandle());
  439. // clean up node controller data.
  440. RemoveWorkItem(p);
  441. hr = S_OK;
  442. break;
  443. }
  444. }
  445. return hr;
  446. }