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.

3628 lines
95 KiB

  1. #include "precomp.h"
  2. //
  3. // CONTROL.CPP
  4. // Control by us, control of us
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. #define MLZ_FILE_ZONE ZONE_CORE
  9. //
  10. // CA_ReceivedPacket()
  11. //
  12. void ASShare::CA_ReceivedPacket
  13. (
  14. ASPerson * pasFrom,
  15. PS20DATAPACKET pPacket
  16. )
  17. {
  18. PCAPACKET pCAPacket;
  19. DebugEntry(ASShare::CA_ReceivedPacket);
  20. ValidatePerson(pasFrom);
  21. pCAPacket = (PCAPACKET)pPacket;
  22. switch (pCAPacket->msg)
  23. {
  24. case CA_MSG_NOTIFY_STATE:
  25. if (pasFrom->cpcCaps.general.version < CAPS_VERSION_30)
  26. {
  27. ERROR_OUT(("Ignoring CA_MSG_NOTIFY_STATE from 2.x node [%d]",
  28. pasFrom->mcsID));
  29. }
  30. else
  31. {
  32. CAHandleNewState(pasFrom, (PCANOTPACKET)pPacket);
  33. }
  34. break;
  35. case CA_OLDMSG_DETACH:
  36. case CA_OLDMSG_COOPERATE:
  37. // Set "cooperating", and map it to allow/disallow control
  38. CA2xCooperateChange(pasFrom, (pCAPacket->msg == CA_OLDMSG_COOPERATE));
  39. break;
  40. case CA_OLDMSG_REQUEST_CONTROL:
  41. CA2xRequestControl(pasFrom, pCAPacket);
  42. break;
  43. case CA_OLDMSG_GRANTED_CONTROL:
  44. CA2xGrantedControl(pasFrom, pCAPacket);
  45. break;
  46. default:
  47. // Ignore for now -- old 2.x messages
  48. break;
  49. }
  50. DebugExitVOID(ASShare::CA_ReceivedPacket);
  51. }
  52. //
  53. // CA30_ReceivedPacket()
  54. //
  55. void ASShare::CA30_ReceivedPacket
  56. (
  57. ASPerson * pasFrom,
  58. PS20DATAPACKET pPacket
  59. )
  60. {
  61. LPBYTE pCAPacket;
  62. DebugEntry(ASShare::CA30_ReceivedPacket);
  63. pCAPacket = (LPBYTE)pPacket + sizeof(CA30PACKETHEADER);
  64. if (pasFrom->cpcCaps.general.version < CAPS_VERSION_30)
  65. {
  66. ERROR_OUT(("Ignoring CA30 packet %d from 2.x node [%d]",
  67. ((PCA30PACKETHEADER)pPacket)->msg, pasFrom->mcsID));
  68. DC_QUIT;
  69. }
  70. switch (((PCA30PACKETHEADER)pPacket)->msg)
  71. {
  72. // From VIEWER (remote) to HOST (us)
  73. case CA_REQUEST_TAKECONTROL:
  74. {
  75. CAHandleRequestTakeControl(pasFrom, (PCA_RTC_PACKET)pCAPacket);
  76. break;
  77. }
  78. // From HOST (remote) to VIEWER (us)
  79. case CA_REPLY_REQUEST_TAKECONTROL:
  80. {
  81. CAHandleReplyRequestTakeControl(pasFrom, (PCA_REPLY_RTC_PACKET)pCAPacket);
  82. break;
  83. }
  84. // From HOST (remote) to VIEWER (us)
  85. case CA_REQUEST_GIVECONTROL:
  86. {
  87. CAHandleRequestGiveControl(pasFrom, (PCA_RGC_PACKET)pCAPacket);
  88. break;
  89. }
  90. // From VIEWER (remote) to HOST (us)
  91. case CA_REPLY_REQUEST_GIVECONTROL:
  92. {
  93. CAHandleReplyRequestGiveControl(pasFrom, (PCA_REPLY_RGC_PACKET)pCAPacket);
  94. break;
  95. }
  96. // From CONTROLLER (remote) to HOST (us)
  97. case CA_PREFER_PASSCONTROL:
  98. {
  99. CAHandlePreferPassControl(pasFrom, (PCA_PPC_PACKET)pCAPacket);
  100. break;
  101. }
  102. // From CONTROLLER (remote) to HOST (us)
  103. case CA_INFORM_RELEASEDCONTROL:
  104. {
  105. CAHandleInformReleasedControl(pasFrom, (PCA_INFORM_PACKET)pCAPacket);
  106. break;
  107. }
  108. // From HOST (remote) to CONTROLLER (us)
  109. case CA_INFORM_REVOKEDCONTROL:
  110. {
  111. CAHandleInformRevokedControl(pasFrom, (PCA_INFORM_PACKET)pCAPacket);
  112. break;
  113. }
  114. // From HOST (remote) to CONTROLLER (us)
  115. case CA_INFORM_PAUSEDCONTROL:
  116. {
  117. CAHandleInformPausedControl(pasFrom, (PCA_INFORM_PACKET)pCAPacket);
  118. break;
  119. }
  120. // From HOST (remote) to CONTROLLER (us)
  121. case CA_INFORM_UNPAUSEDCONTROL:
  122. {
  123. CAHandleInformUnpausedControl(pasFrom, (PCA_INFORM_PACKET)pCAPacket);
  124. break;
  125. }
  126. default:
  127. {
  128. WARNING_OUT(("CA30_ReceivedPacket: unrecognized message %d",
  129. ((PCA30PACKETHEADER)pPacket)->msg));
  130. break;
  131. }
  132. }
  133. DC_EXIT_POINT:
  134. DebugExitVOID(ASShare::CA30_ReceivedPacket);
  135. }
  136. //
  137. // CANewRequestID()
  138. //
  139. // Returns a new token. It uses the current value, fills in the new one, and
  140. // also returns the new one. We wrap around if necessary. ZERO is never
  141. // valid. Note that this is a unique identifier only to us.
  142. //
  143. // It is a stamp for the control operation. Since you can't be controlling
  144. // and controlled at the same time, we have one stamp for all ops.
  145. //
  146. UINT ASShare::CANewRequestID(void)
  147. {
  148. DebugEntry(ASShare::CANewRequestID);
  149. ++(m_pasLocal->m_caControlID);
  150. if (m_pasLocal->m_caControlID == 0)
  151. {
  152. ++(m_pasLocal->m_caControlID);
  153. }
  154. DebugExitDWORD(ASShare::CANewRequestID, m_pasLocal->m_caControlID);
  155. return(m_pasLocal->m_caControlID);
  156. }
  157. //
  158. // CA_ViewStarting()
  159. // Called when a REMOTE starts hosting
  160. //
  161. // We only do anything if it's a 2.x node since they could be cooperating
  162. // but not hosting.
  163. //
  164. BOOL ASShare::CA_ViewStarting(ASPerson * pasPerson)
  165. {
  166. DebugEntry(ASShare::CA_ViewStarting);
  167. //
  168. // If this isn't a back level system, ignore it.
  169. //
  170. if (pasPerson->cpcCaps.general.version >= CAPS_VERSION_30)
  171. {
  172. DC_QUIT;
  173. }
  174. //
  175. // See if AllowControl should now be on.
  176. //
  177. if (pasPerson->m_ca2xCooperating)
  178. {
  179. //
  180. // Yes, it should. 2.x node is cooperating, now they are hosting,
  181. // and we can take control of them.
  182. //
  183. ASSERT(!pasPerson->m_caAllowControl);
  184. pasPerson->m_caAllowControl = TRUE;
  185. VIEW_HostStateChange(pasPerson);
  186. }
  187. DC_EXIT_POINT:
  188. DebugExitBOOL(ASShare::CA_ViewStarting, TRUE);
  189. return(TRUE);
  190. }
  191. //
  192. // CA_ViewEnded()
  193. // Called when a REMOTE stopped hosting
  194. //
  195. void ASShare::CA_ViewEnded(ASPerson * pasPerson)
  196. {
  197. PCAREQUEST pRequest;
  198. PCAREQUEST pNext;
  199. DebugEntry(ASShare::CA_ViewEnded);
  200. //
  201. // Clear any control stuff we are a part of where they are the host
  202. //
  203. CA_ClearLocalState(CACLEAR_VIEW, pasPerson, FALSE);
  204. //
  205. // Clear any control stuff involving remotes
  206. //
  207. if (pasPerson->m_caControlledBy)
  208. {
  209. ASSERT(pasPerson->m_caControlledBy != m_pasLocal);
  210. CAClearHostState(pasPerson, NULL);
  211. ASSERT(!pasPerson->m_caControlledBy);
  212. }
  213. pasPerson->m_caAllowControl = FALSE;
  214. //
  215. // Clean up outstanding control packets to this person
  216. //
  217. pRequest = (PCAREQUEST)COM_BasedListFirst(&m_caQueuedMsgs, FIELD_OFFSET(CAREQUEST, chain));
  218. while (pRequest)
  219. {
  220. pNext = (PCAREQUEST)COM_BasedListNext(&m_caQueuedMsgs, pRequest,
  221. FIELD_OFFSET(CAREQUEST, chain));
  222. if (pRequest->destID == pasPerson->mcsID)
  223. {
  224. if (pRequest->type == REQUEST_30)
  225. {
  226. //
  227. // Delete messages sent by us to this person who is hosting
  228. //
  229. switch (pRequest->msg)
  230. {
  231. case CA_REQUEST_TAKECONTROL:
  232. case CA_PREFER_PASSCONTROL:
  233. case CA_REPLY_REQUEST_GIVECONTROL:
  234. WARNING_OUT(("Deleting viewer control message %d, person [%d] stopped hosting",
  235. pRequest->msg, pasPerson->mcsID));
  236. COM_BasedListRemove(&pRequest->chain);
  237. delete pRequest;
  238. break;
  239. }
  240. }
  241. else
  242. {
  243. ASSERT(pRequest->type == REQUEST_2X);
  244. // Change GRANTED_CONTROL packets to this host to DETACH
  245. if (pRequest->msg == CA_OLDMSG_GRANTED_CONTROL)
  246. {
  247. //
  248. // For 2.x messages, destID is only non-zero when we are
  249. // attempting to control a particular node. It allows us
  250. // to undo/cancel control, to map our one-to-one model
  251. // into the global 2.x collaboration model.
  252. //
  253. //
  254. // Make this a DETACH, that way we don't have to worry if
  255. // part of the COOPERATE/GRANTED_CONTROL sequence got out
  256. // but part was left in the queue.
  257. //
  258. WARNING_OUT(("Changing GRANTED_CONTROL to 2.x host [%d] into DETATCH",
  259. pasPerson->mcsID));
  260. pRequest->destID = 0;
  261. pRequest->msg = CA_OLDMSG_DETACH;
  262. pRequest->req.req2x.data1 = 0;
  263. pRequest->req.req2x.data2 = 0;
  264. }
  265. }
  266. }
  267. pRequest = pNext;
  268. }
  269. DebugExitVOID(ASView::CA_ViewEnded);
  270. }
  271. //
  272. // CA_PartyLeftShare()
  273. //
  274. void ASShare::CA_PartyLeftShare(ASPerson * pasPerson)
  275. {
  276. DebugEntry(ASShare::CA_PartyLeftShare);
  277. ValidatePerson(pasPerson);
  278. //
  279. // Clean up 2.x control stuff
  280. //
  281. if (pasPerson == m_ca2xControlTokenOwner)
  282. {
  283. m_ca2xControlTokenOwner = NULL;
  284. }
  285. //
  286. // We must have cleaned up hosting info for this person already.
  287. // So it can't be controlled or controllable.
  288. //
  289. ASSERT(!pasPerson->m_caAllowControl);
  290. ASSERT(!pasPerson->m_caControlledBy);
  291. if (pasPerson != m_pasLocal)
  292. {
  293. PCAREQUEST pRequest;
  294. PCAREQUEST pNext;
  295. //
  296. // Clear any control stuff we are a part of where they are the
  297. // viewer.
  298. //
  299. CA_ClearLocalState(CACLEAR_HOST, pasPerson, FALSE);
  300. //
  301. // Clear any control stuff involving remotes
  302. //
  303. if (pasPerson->m_caInControlOf)
  304. {
  305. ASSERT(pasPerson->m_caInControlOf != m_pasLocal);
  306. CAClearHostState(pasPerson->m_caInControlOf, NULL);
  307. }
  308. //
  309. // Clean up outgoing packets meant for this person.
  310. //
  311. pRequest = (PCAREQUEST)COM_BasedListFirst(&m_caQueuedMsgs, FIELD_OFFSET(CAREQUEST, chain));
  312. while (pRequest)
  313. {
  314. pNext = (PCAREQUEST)COM_BasedListNext(&m_caQueuedMsgs, pRequest,
  315. FIELD_OFFSET(CAREQUEST, chain));
  316. //
  317. // This doesn't need to know if it's a 2.x or 3.0 request,
  318. // simply remove queued packets intended for somebody leaving.
  319. //
  320. // Only GRANTED_CONTROL requests will have non-zero destIDs of
  321. // the 2.x packets.
  322. //
  323. if (pRequest->destID == pasPerson->mcsID)
  324. {
  325. WARNING_OUT(("Freeing outgoing RESPONSE to node [%d]", pasPerson->mcsID));
  326. COM_BasedListRemove(&(pRequest->chain));
  327. delete pRequest;
  328. }
  329. pRequest = pNext;
  330. }
  331. ASSERT(m_caWaitingForReplyFrom != pasPerson);
  332. }
  333. else
  334. {
  335. //
  336. // When our waiting for/controlled dude stopped sharing, we should
  337. // have cleaned this goop up.
  338. //
  339. ASSERT(!pasPerson->m_caInControlOf);
  340. ASSERT(!pasPerson->m_caControlledBy);
  341. ASSERT(!m_caWaitingForReplyFrom);
  342. ASSERT(!m_caWaitingForReplyMsg);
  343. //
  344. // There should be NO outgoing control requests
  345. //
  346. ASSERT(COM_BasedListIsEmpty(&(m_caQueuedMsgs)));
  347. }
  348. DebugExitVOID(ASShare::CA_PartyLeftShare);
  349. }
  350. //
  351. // CA_Periodic() -> SHARE STUFF
  352. //
  353. void ASShare::CA_Periodic(void)
  354. {
  355. DebugEntry(ASShare::CA_Periodic);
  356. //
  357. // Flush as many queued outgoing messages as we can
  358. //
  359. CAFlushOutgoingPackets();
  360. DebugExitVOID(ASShare::CA_Periodic);
  361. }
  362. //
  363. // CA_SyncAlreadyHosting()
  364. //
  365. void ASHost::CA_SyncAlreadyHosting(void)
  366. {
  367. DebugEntry(ASHost::CA_SyncAlreadyHosting);
  368. m_caRetrySendState = TRUE;
  369. DebugExitVOID(ASHost::CA_SyncAlreadyHosting);
  370. }
  371. //
  372. // CA_Periodic() -> HOSTING STUFF
  373. //
  374. void ASHost::CA_Periodic(void)
  375. {
  376. DebugEntry(ASHost::CA_Periodic);
  377. if (m_caRetrySendState)
  378. {
  379. PCANOTPACKET pPacket;
  380. #ifdef _DEBUG
  381. UINT sentSize;
  382. #endif // _DEBUG
  383. pPacket = (PCANOTPACKET)m_pShare->SC_AllocPkt(PROT_STR_MISC, g_s20BroadcastID,
  384. sizeof(*pPacket));
  385. if (!pPacket)
  386. {
  387. WARNING_OUT(("CA_Periodic: couldn't broadcast new state"));
  388. }
  389. else
  390. {
  391. pPacket->header.data.dataType = DT_CA;
  392. pPacket->msg = CA_MSG_NOTIFY_STATE;
  393. pPacket->state = 0;
  394. if (m_pShare->m_pasLocal->m_caAllowControl)
  395. pPacket->state |= CASTATE_ALLOWCONTROL;
  396. if (m_pShare->m_pasLocal->m_caControlledBy)
  397. pPacket->controllerID = m_pShare->m_pasLocal->m_caControlledBy->mcsID;
  398. else
  399. pPacket->controllerID = 0;
  400. #ifdef _DEBUG
  401. sentSize =
  402. #endif // _DEBUG
  403. m_pShare->DCS_CompressAndSendPacket(PROT_STR_MISC, g_s20BroadcastID,
  404. &(pPacket->header), sizeof(*pPacket));
  405. m_caRetrySendState = FALSE;
  406. }
  407. }
  408. DebugExitVOID(ASHost::CA_Periodic);
  409. }
  410. //
  411. // CAFlushOutgoingPackets()
  412. //
  413. // This tries to send private packets (not broadcast notifications) that
  414. // we have accumulated. It returns TRUE if the outgoing queue is empty.
  415. //
  416. BOOL ASShare::CAFlushOutgoingPackets(void)
  417. {
  418. BOOL fEmpty = TRUE;
  419. PCAREQUEST pRequest;
  420. //
  421. // If we're hosting and haven't yet flushed the HET or CA state,
  422. // force queueing.
  423. //
  424. if (m_hetRetrySendState || (m_pHost && m_pHost->m_caRetrySendState))
  425. {
  426. TRACE_OUT(("CAFlushOutgoingPackets: force queuing, pending HET/CA state broadcast"));
  427. fEmpty = FALSE;
  428. DC_QUIT;
  429. }
  430. while (pRequest = (PCAREQUEST)COM_BasedListFirst(&m_caQueuedMsgs,
  431. FIELD_OFFSET(CAREQUEST, chain)))
  432. {
  433. //
  434. // Allocate/send packet
  435. //
  436. if (pRequest->type == REQUEST_30)
  437. {
  438. if (!CASendPacket(pRequest->destID, pRequest->msg,
  439. &pRequest->req.req30.packet))
  440. {
  441. WARNING_OUT(("CAFlushOutgoingPackets: couldn't send request"));
  442. fEmpty = FALSE;
  443. break;
  444. }
  445. }
  446. else
  447. {
  448. ASSERT(pRequest->type == REQUEST_2X);
  449. if (!CA2xSendMsg(pRequest->destID, pRequest->msg,
  450. pRequest->req.req2x.data1, pRequest->req.req2x.data2))
  451. {
  452. WARNING_OUT(("CAFlushOutgoingmsgs: couldn't send request"));
  453. fEmpty = FALSE;
  454. break;
  455. }
  456. }
  457. //
  458. // Do we do state transitions here or when things are added to queue?
  459. // requestID, results are calculated when put on queue. Results can
  460. // change though based on a future action.
  461. //
  462. COM_BasedListRemove(&(pRequest->chain));
  463. delete pRequest;
  464. }
  465. DC_EXIT_POINT:
  466. DebugExitBOOL(CAFlushOutgoingPackets, fEmpty);
  467. return(fEmpty);
  468. }
  469. //
  470. // CASendPacket()
  471. // This sends a private message (request or response) to the destination.
  472. // If there are queued private messages in front of this one, or we can't
  473. // send it, we add it to the pending queue.
  474. //
  475. // This TRUE if sent.
  476. //
  477. // It's up to the caller to change state info appropriately.
  478. //
  479. BOOL ASShare::CASendPacket
  480. (
  481. UINT_PTR destID,
  482. UINT msg,
  483. PCA30P pData
  484. )
  485. {
  486. BOOL fSent = FALSE;
  487. PCA30PACKETHEADER pPacket;
  488. #ifdef _DEBUG
  489. UINT sentSize;
  490. #endif // _DEBUG
  491. DebugEntry(ASShare::CASendPacket);
  492. //
  493. // Note that CA30P does not include size of header.
  494. //
  495. pPacket = (PCA30PACKETHEADER)SC_AllocPkt(PROT_STR_INPUT, destID,
  496. sizeof(CA30PACKETHEADER) + sizeof(*pData));
  497. if (!pPacket)
  498. {
  499. WARNING_OUT(("CASendPacket: no memory to send %d packet to [%d]",
  500. msg, destID));
  501. DC_QUIT;
  502. }
  503. pPacket->header.data.dataType = DT_CA30;
  504. pPacket->msg = msg;
  505. memcpy(pPacket+1, pData, sizeof(*pData));
  506. #ifdef _DEBUG
  507. sentSize =
  508. #endif // _DEBUG
  509. DCS_CompressAndSendPacket(PROT_STR_INPUT, destID,
  510. &(pPacket->header), sizeof(*pPacket));
  511. TRACE_OUT(("CA30 request packet size: %08d, sent %08d", sizeof(*pPacket), sentSize));
  512. fSent = TRUE;
  513. DC_EXIT_POINT:
  514. DebugExitBOOL(ASShare::CASendPacket, fSent);
  515. return(fSent);
  516. }
  517. //
  518. // CAQueueSendPacket()
  519. // This flushes pending queued requests if there are any, then tries to
  520. // send this one. If it can't, we add it to the queue. If there's not any
  521. // memory even for that, we return an error about it.
  522. //
  523. BOOL ASShare::CAQueueSendPacket
  524. (
  525. UINT_PTR destID,
  526. UINT msg,
  527. PCA30P pPacketSend
  528. )
  529. {
  530. BOOL rc = TRUE;
  531. PCAREQUEST pCARequest;
  532. DebugEntry(ASShare::CAQueueSendPacket);
  533. //
  534. // These must go out in order. So if any queued messages are still
  535. // present, those must be sent first.
  536. //
  537. if (!CAFlushOutgoingPackets() ||
  538. !CASendPacket(destID, msg, pPacketSend))
  539. {
  540. //
  541. // We must queue this.
  542. //
  543. TRACE_OUT(("CAQueueSendPacket: queuing request for send later"));
  544. pCARequest = new CAREQUEST;
  545. if (!pCARequest)
  546. {
  547. ERROR_OUT(("CAQueueSendPacket: can't even allocate memory to queue request; must fail"));
  548. rc = FALSE;
  549. }
  550. else
  551. {
  552. SET_STAMP(pCARequest, CAREQUEST);
  553. pCARequest->type = REQUEST_30;
  554. pCARequest->destID = destID;
  555. pCARequest->msg = msg;
  556. pCARequest->req.req30.packet = *pPacketSend;
  557. //
  558. // Stick this at the end of the queue
  559. //
  560. COM_BasedListInsertBefore(&(m_caQueuedMsgs), &(pCARequest->chain));
  561. }
  562. }
  563. DebugExitBOOL(ASShare::CAQueueSendPacket, rc);
  564. return(rc);
  565. }
  566. //
  567. // CALangToggle()
  568. //
  569. // This temporarily turns off the keyboard language toggle key, so that a
  570. // remote controlling us doesn't inadvertently change it. When we stop being
  571. // controlled, we put it back.
  572. //
  573. void ASShare::CALangToggle(BOOL fBackOn)
  574. {
  575. //
  576. // Local Variables
  577. //
  578. LONG rc;
  579. HKEY hkeyToggle;
  580. BYTE regValue[2];
  581. DWORD cbRegValue;
  582. DWORD dwType;
  583. LPCSTR szValue;
  584. DebugEntry(ASShare::CALangToggle);
  585. szValue = (g_asWin95) ? NULL : LANGUAGE_TOGGLE_KEY_VAL;
  586. if (fBackOn)
  587. {
  588. //
  589. // We are gaining control of our local keyboard again - we restore the
  590. // language togging functionality.
  591. //
  592. // We must directly access the registry to accomplish this.
  593. //
  594. if (m_caToggle != LANGUAGE_TOGGLE_NOT_PRESENT)
  595. {
  596. rc = RegOpenKey(HKEY_CURRENT_USER, LANGUAGE_TOGGLE_KEY,
  597. &hkeyToggle);
  598. if (rc == ERROR_SUCCESS)
  599. {
  600. //
  601. // Clear the value for this key.
  602. //
  603. regValue[0] = m_caToggle;
  604. regValue[1] = '\0'; // ensure NUL termination
  605. //
  606. // Restore the value.
  607. //
  608. RegSetValueEx(hkeyToggle, szValue, 0, REG_SZ,
  609. regValue, sizeof(regValue));
  610. //
  611. // We need to inform the system about this change. We do not
  612. // tell any other apps about this (ie do not set any of the
  613. // notification flags as the last parm)
  614. //
  615. SystemParametersInfo(SPI_SETLANGTOGGLE, 0, 0, 0);
  616. }
  617. RegCloseKey(hkeyToggle);
  618. }
  619. }
  620. else
  621. {
  622. //
  623. // We are losing control of our keyboard - ensure that remote key
  624. // events will not change our local keyboard settings by disabling the
  625. // keyboard language toggle.
  626. //
  627. // We must directly access the registry to accomplish this.
  628. //
  629. rc = RegOpenKey(HKEY_CURRENT_USER, LANGUAGE_TOGGLE_KEY,
  630. &hkeyToggle);
  631. if (rc == ERROR_SUCCESS)
  632. {
  633. cbRegValue = sizeof(regValue);
  634. rc = RegQueryValueEx(hkeyToggle, szValue, NULL,
  635. &dwType, regValue, &cbRegValue);
  636. if (rc == ERROR_SUCCESS)
  637. {
  638. m_caToggle = regValue[0];
  639. //
  640. // Clear the value for this key.
  641. //
  642. regValue[0] = '3';
  643. regValue[1] = '\0'; // ensure NUL termination
  644. //
  645. // Clear the value.
  646. //
  647. RegSetValueEx(hkeyToggle, szValue, 0, REG_SZ,
  648. regValue, sizeof(regValue));
  649. //
  650. // We need to inform the system about this change. We do not
  651. // tell any other apps about this (ie do not set any of the
  652. // notification flags as the last parm)
  653. //
  654. SystemParametersInfo(SPI_SETLANGTOGGLE, 0, 0, 0);
  655. }
  656. else
  657. {
  658. m_caToggle = LANGUAGE_TOGGLE_NOT_PRESENT;
  659. }
  660. RegCloseKey(hkeyToggle);
  661. }
  662. }
  663. DebugExitVOID(ASShare::CALangToggle);
  664. }
  665. //
  666. // CAStartControlled()
  667. //
  668. void ASShare::CAStartControlled
  669. (
  670. ASPerson * pasInControl,
  671. UINT controlID
  672. )
  673. {
  674. DebugEntry(ASShare::CAStartControlled);
  675. ValidatePerson(pasInControl);
  676. //
  677. // Undo last known state of remote
  678. //
  679. CAClearRemoteState(pasInControl);
  680. //
  681. // Get any VIEW frame UI out of the way
  682. //
  683. SendMessage(g_asSession.hwndHostUI, HOST_MSG_CONTROLLED, TRUE, 0);
  684. VIEWStartControlled(TRUE);
  685. ASSERT(!m_pasLocal->m_caControlledBy);
  686. m_pasLocal->m_caControlledBy = pasInControl;
  687. ASSERT(!pasInControl->m_caInControlOf);
  688. pasInControl->m_caInControlOf = m_pasLocal;
  689. ASSERT(!pasInControl->m_caControlID);
  690. ASSERT(controlID);
  691. pasInControl->m_caControlID = controlID;
  692. //
  693. // Notify IM.
  694. //
  695. IM_Controlled(pasInControl);
  696. //
  697. // Disable language toggling.
  698. //
  699. CALangToggle(FALSE);
  700. ASSERT(m_pHost);
  701. m_pHost->CM_Controlled(pasInControl);
  702. //
  703. // Notify the UI. Pass GCCID of controller
  704. //
  705. DCS_NotifyUI(SH_EVT_STARTCONTROLLED, pasInControl->cpcCaps.share.gccID, 0);
  706. //
  707. // Broadcast new state
  708. //
  709. m_pHost->m_caRetrySendState = TRUE;
  710. m_pHost->CA_Periodic();
  711. DebugExitVOID(ASShare::CAStartControlled);
  712. }
  713. //
  714. // CAStopControlled()
  715. //
  716. void ASShare::CAStopControlled(void)
  717. {
  718. ASPerson * pasControlledBy;
  719. DebugEntry(ASShare::CAStopControlled);
  720. pasControlledBy = m_pasLocal->m_caControlledBy;
  721. ValidatePerson(pasControlledBy);
  722. //
  723. // If control is paused, unpause it.
  724. //
  725. if (m_pasLocal->m_caControlPaused)
  726. {
  727. CA_PauseControl(pasControlledBy, FALSE, FALSE);
  728. }
  729. m_pasLocal->m_caControlledBy = NULL;
  730. ASSERT(pasControlledBy->m_caInControlOf == m_pasLocal);
  731. pasControlledBy->m_caInControlOf = NULL;
  732. ASSERT(pasControlledBy->m_caControlID);
  733. pasControlledBy->m_caControlID = 0;
  734. //
  735. // Notify IM.
  736. //
  737. IM_Controlled(NULL);
  738. //
  739. // Restore language toggling functionality.
  740. //
  741. CALangToggle(TRUE);
  742. ASSERT(m_pHost);
  743. m_pHost->CM_Controlled(NULL);
  744. VIEWStartControlled(FALSE);
  745. ASSERT(IsWindow(g_asSession.hwndHostUI));
  746. SendMessage(g_asSession.hwndHostUI, HOST_MSG_CONTROLLED, FALSE, 0);
  747. //
  748. // Notify the UI
  749. //
  750. DCS_NotifyUI(SH_EVT_STOPCONTROLLED, pasControlledBy->cpcCaps.share.gccID, 0);
  751. //
  752. // Broadcast the new state
  753. //
  754. m_pHost->m_caRetrySendState = TRUE;
  755. m_pHost->CA_Periodic();
  756. DebugExitVOID(ASShare::CAStopControlled);
  757. }
  758. //
  759. // CAStartInControl()
  760. //
  761. void ASShare::CAStartInControl
  762. (
  763. ASPerson * pasControlled,
  764. UINT controlID
  765. )
  766. {
  767. DebugEntry(ASShare::CAStartInControl);
  768. ValidatePerson(pasControlled);
  769. //
  770. // Undo last known state of host
  771. //
  772. CAClearRemoteState(pasControlled);
  773. ASSERT(!m_pasLocal->m_caInControlOf);
  774. m_pasLocal->m_caInControlOf = pasControlled;
  775. ASSERT(!pasControlled->m_caControlledBy);
  776. pasControlled->m_caControlledBy = m_pasLocal;
  777. ASSERT(!pasControlled->m_caControlID);
  778. ASSERT(controlID);
  779. pasControlled->m_caControlID = controlID;
  780. ASSERT(!g_lpimSharedData->imControlled);
  781. IM_InControl(pasControlled);
  782. VIEW_InControl(pasControlled, TRUE);
  783. //
  784. // Pass GCC ID of node we're controlling
  785. //
  786. DCS_NotifyUI(SH_EVT_STARTINCONTROL, pasControlled->cpcCaps.share.gccID, 0);
  787. DebugExitVOID(ASShare::CAStartInControl);
  788. }
  789. //
  790. // CAStopInControl()
  791. //
  792. void ASShare::CAStopInControl(void)
  793. {
  794. ASPerson * pasInControlOf;
  795. DebugEntry(ASShare::CAStopInControl);
  796. pasInControlOf = m_pasLocal->m_caInControlOf;
  797. ValidatePerson(pasInControlOf);
  798. if (pasInControlOf->m_caControlPaused)
  799. {
  800. pasInControlOf->m_caControlPaused = FALSE;
  801. }
  802. m_pasLocal->m_caInControlOf = NULL;
  803. ASSERT(pasInControlOf->m_caControlledBy == m_pasLocal);
  804. pasInControlOf->m_caControlledBy = NULL;
  805. ASSERT(pasInControlOf->m_caControlID);
  806. pasInControlOf->m_caControlID = 0;
  807. ASSERT(!g_lpimSharedData->imControlled);
  808. IM_InControl(NULL);
  809. VIEW_InControl(pasInControlOf, FALSE);
  810. DCS_NotifyUI(SH_EVT_STOPINCONTROL, pasInControlOf->cpcCaps.share.gccID, 0);
  811. DebugExitVOID(ASShare::CAStopInControl);
  812. }
  813. //
  814. // CA_AllowControl()
  815. // Allows/disallows remotes from controlling us.
  816. //
  817. void ASShare::CA_AllowControl(BOOL fAllow)
  818. {
  819. DebugEntry(ASShare::CA_AllowControl);
  820. if (!m_pHost)
  821. {
  822. WARNING_OUT(("CA_AllowControl: ignoring, we aren't hosting"));
  823. DC_QUIT;
  824. }
  825. if (fAllow != m_pasLocal->m_caAllowControl)
  826. {
  827. if (!fAllow)
  828. {
  829. // Undo pending control/control queries/being controlled stuff
  830. CA_ClearLocalState(CACLEAR_HOST, NULL, TRUE);
  831. }
  832. m_pasLocal->m_caAllowControl = fAllow;
  833. ASSERT(IsWindow(g_asSession.hwndHostUI));
  834. SendMessage(g_asSession.hwndHostUI, HOST_MSG_ALLOWCONTROL, fAllow, 0);
  835. DCS_NotifyUI(SH_EVT_CONTROLLABLE, fAllow, 0);
  836. m_pHost->m_caRetrySendState = TRUE;
  837. }
  838. DC_EXIT_POINT:
  839. DebugExitVOID(ASShare::CA_AllowControl);
  840. }
  841. //
  842. // CA_HostEnded()
  843. //
  844. // When we stop hosting, we do not need to flush queued control
  845. // responses. But we need to delete them!
  846. //
  847. void ASHost::CA_HostEnded(void)
  848. {
  849. PCAREQUEST pCARequest;
  850. PCAREQUEST pCANext;
  851. DebugEntry(ASHost::CA_HostEnded);
  852. m_pShare->CA_ClearLocalState(CACLEAR_HOST, NULL, FALSE);
  853. //
  854. // Delete now obsolete messages originating from us as host.
  855. //
  856. pCARequest = (PCAREQUEST)COM_BasedListFirst(&m_pShare->m_caQueuedMsgs,
  857. FIELD_OFFSET(CAREQUEST, chain));
  858. while (pCARequest)
  859. {
  860. pCANext = (PCAREQUEST)COM_BasedListNext(&m_pShare->m_caQueuedMsgs, pCARequest,
  861. FIELD_OFFSET(CAREQUEST, chain));
  862. if (pCARequest->type == REQUEST_30)
  863. {
  864. switch (pCARequest->msg)
  865. {
  866. //
  867. // Delete messages sent by us when we are hosting.
  868. //
  869. case CA_INFORM_PAUSEDCONTROL:
  870. case CA_INFORM_UNPAUSEDCONTROL:
  871. case CA_REPLY_REQUEST_TAKECONTROL:
  872. case CA_REQUEST_GIVECONTROL:
  873. WARNING_OUT(("Deleting host control message %d, we stopped hosting",
  874. pCARequest->msg));
  875. COM_BasedListRemove(&pCARequest->chain);
  876. delete pCARequest;
  877. break;
  878. }
  879. }
  880. pCARequest = pCANext;
  881. }
  882. if (m_pShare->m_pasLocal->m_caAllowControl)
  883. {
  884. m_pShare->m_pasLocal->m_caAllowControl = FALSE;
  885. ASSERT(IsWindow(g_asSession.hwndHostUI));
  886. SendMessage(g_asSession.hwndHostUI, HOST_MSG_ALLOWCONTROL, FALSE, 0);
  887. DCS_NotifyUI(SH_EVT_CONTROLLABLE, FALSE, 0);
  888. }
  889. DebugExitVOID(ASHost::CA_HostEnded);
  890. }
  891. //
  892. // CA_TakeControl()
  893. //
  894. // Called by viewer to ask to take control of host. Note parallels to
  895. // CA_GiveControl(), which is called by host to get same result.
  896. //
  897. void ASShare::CA_TakeControl(ASPerson * pasHost)
  898. {
  899. DebugEntry(ASShare::CA_TakeControl);
  900. ValidatePerson(pasHost);
  901. ASSERT(pasHost != m_pasLocal);
  902. //
  903. // If this person isn't hosting or controllable, fail.
  904. //
  905. if (!pasHost->m_pView)
  906. {
  907. WARNING_OUT(("CA_TakeControl: failing, person [%d] not hosting",
  908. pasHost->mcsID));
  909. DC_QUIT;
  910. }
  911. if (!pasHost->m_caAllowControl)
  912. {
  913. WARNING_OUT(("CA_TakeControl: failing, host [%d] not controllable",
  914. pasHost->mcsID));
  915. DC_QUIT;
  916. }
  917. //
  918. // Undo current state.
  919. //
  920. CA_ClearLocalState(CACLEAR_ALL, NULL, TRUE);
  921. //
  922. // Now take control.
  923. //
  924. if (pasHost->cpcCaps.general.version >= CAPS_VERSION_30)
  925. {
  926. //
  927. // 3.0 host
  928. //
  929. CA30P packetSend;
  930. ZeroMemory(&packetSend, sizeof(packetSend));
  931. packetSend.rtc.viewerControlID = CANewRequestID();
  932. if (CAQueueSendPacket(pasHost->mcsID, CA_REQUEST_TAKECONTROL, &packetSend))
  933. {
  934. //
  935. // Now we're in waiting state.
  936. //
  937. CAStartWaiting(pasHost, CA_REPLY_REQUEST_TAKECONTROL);
  938. VIEW_UpdateStatus(pasHost, IDS_STATUS_WAITINGFORCONTROL);
  939. }
  940. else
  941. {
  942. WARNING_OUT(("CA_TakeControl of [%d]: failing, out of memory", pasHost->mcsID));
  943. }
  944. }
  945. else
  946. {
  947. CA2xTakeControl(pasHost);
  948. }
  949. DC_EXIT_POINT:
  950. DebugExitVOID(ASShare::CA_TakeControl);
  951. }
  952. //
  953. // CA_CancelTakeControl()
  954. //
  955. void ASShare::CA_CancelTakeControl
  956. (
  957. ASPerson * pasHost,
  958. BOOL fPacket
  959. )
  960. {
  961. DebugEntry(ASShare::CA_CancelTakeControl);
  962. ValidatePerson(pasHost);
  963. ASSERT(pasHost != m_pasLocal);
  964. if ((m_caWaitingForReplyFrom != pasHost) ||
  965. (m_caWaitingForReplyMsg != CA_REPLY_REQUEST_TAKECONTROL))
  966. {
  967. // We're not waiting for control of this host.
  968. WARNING_OUT(("CA_CancelTakeControl failing; not waiting to take control of [%d]",
  969. pasHost->mcsID));
  970. DC_QUIT;
  971. }
  972. ASSERT(pasHost->cpcCaps.general.version >= CAPS_VERSION_30);
  973. ASSERT(pasHost->m_caControlID == 0);
  974. if (fPacket)
  975. {
  976. CA30P packetSend;
  977. ZeroMemory(&packetSend, sizeof(packetSend));
  978. packetSend.inform.viewerControlID = m_pasLocal->m_caControlID;
  979. packetSend.inform.hostControlID = pasHost->m_caControlID;
  980. if (!CAQueueSendPacket(pasHost->mcsID, CA_INFORM_RELEASEDCONTROL,
  981. &packetSend))
  982. {
  983. WARNING_OUT(("Couldn't tell node [%d] we're no longer waiting for control",
  984. pasHost->mcsID));
  985. }
  986. }
  987. m_caWaitingForReplyFrom = NULL;
  988. m_caWaitingForReplyMsg = 0;
  989. VIEW_UpdateStatus(pasHost, IDS_STATUS_NONE);
  990. DC_EXIT_POINT:
  991. DebugExitVOID(ASShare::CA_CancelTakeControl);
  992. }
  993. //
  994. // CA_ReleaseControl()
  995. //
  996. void ASShare::CA_ReleaseControl
  997. (
  998. ASPerson * pasHost,
  999. BOOL fPacket
  1000. )
  1001. {
  1002. DebugEntry(ASShare::CA_ReleaseControl);
  1003. ValidatePerson(pasHost);
  1004. ASSERT(pasHost != m_pasLocal);
  1005. if (pasHost->m_caControlledBy != m_pasLocal)
  1006. {
  1007. // We're not in control of this dude, nothing to do.
  1008. WARNING_OUT(("CA_ReleaseControl failing; not in control of [%d]",
  1009. pasHost->mcsID));
  1010. DC_QUIT;
  1011. }
  1012. ASSERT(!m_caWaitingForReplyFrom);
  1013. ASSERT(!m_caWaitingForReplyMsg);
  1014. if (fPacket)
  1015. {
  1016. if (pasHost->cpcCaps.general.version >= CAPS_VERSION_30)
  1017. {
  1018. CA30P packetSend;
  1019. ZeroMemory(&packetSend, sizeof(packetSend));
  1020. packetSend.inform.viewerControlID = m_pasLocal->m_caControlID;
  1021. packetSend.inform.hostControlID = pasHost->m_caControlID;
  1022. if (!CAQueueSendPacket(pasHost->mcsID, CA_INFORM_RELEASEDCONTROL,
  1023. &packetSend))
  1024. {
  1025. WARNING_OUT(("Couldn't tell node [%d] they're no longer controlled",
  1026. pasHost->mcsID));
  1027. }
  1028. }
  1029. else
  1030. {
  1031. if (!CA2xQueueSendMsg(0, CA_OLDMSG_DETACH, 0, 0))
  1032. {
  1033. WARNING_OUT(("Couldn't tell 2.x node [%d] they're no longer controlled",
  1034. pasHost->mcsID));
  1035. }
  1036. }
  1037. }
  1038. CAStopInControl();
  1039. DC_EXIT_POINT:
  1040. DebugExitVOID(ASShare::CA_ReleaseControl);
  1041. }
  1042. //
  1043. // CA_PassControl()
  1044. //
  1045. void ASShare::CA_PassControl(ASPerson * pasHost, ASPerson * pasViewer)
  1046. {
  1047. CA30P packetSend;
  1048. DebugEntry(ASShare::CA_PassControl);
  1049. ValidatePerson(pasHost);
  1050. ValidatePerson(pasViewer);
  1051. ASSERT(pasHost != pasViewer);
  1052. ASSERT(pasHost != m_pasLocal);
  1053. ASSERT(pasViewer != m_pasLocal);
  1054. if (pasHost->m_caControlledBy != m_pasLocal)
  1055. {
  1056. WARNING_OUT(("CA_PassControl: failing, we're not in control of [%d]",
  1057. pasHost->mcsID));
  1058. DC_QUIT;
  1059. }
  1060. ASSERT(!m_caWaitingForReplyFrom);
  1061. ASSERT(!m_caWaitingForReplyMsg);
  1062. //
  1063. // No 2.x nodes, neither host nor controller, allowed
  1064. //
  1065. if ((pasHost->cpcCaps.general.version < CAPS_VERSION_30) ||
  1066. (pasViewer->cpcCaps.general.version < CAPS_VERSION_30))
  1067. {
  1068. WARNING_OUT(("CA_PassControl: failing, we can't pass control with 2.x nodes"));
  1069. DC_QUIT;
  1070. }
  1071. ZeroMemory(&packetSend, sizeof(packetSend));
  1072. packetSend.ppc.viewerControlID = m_pasLocal->m_caControlID;
  1073. packetSend.ppc.hostControlID = pasHost->m_caControlID;
  1074. packetSend.ppc.mcsPassTo = pasViewer->mcsID;
  1075. if (CAQueueSendPacket(pasHost->mcsID, CA_PREFER_PASSCONTROL, &packetSend))
  1076. {
  1077. CAStopInControl();
  1078. }
  1079. else
  1080. {
  1081. WARNING_OUT(("Couldn't tell node [%d] we want them to pass control to [%d]",
  1082. pasHost->mcsID, pasViewer->mcsID));
  1083. }
  1084. DC_EXIT_POINT:
  1085. DebugExitVOID(ASShare::CA_PassControl);
  1086. }
  1087. //
  1088. // CA_GiveControl()
  1089. //
  1090. // Called by host to ask to grant control to viewer. Note parallels to
  1091. // CA_TakeControl(), which is called by viewer to get same result.
  1092. //
  1093. void ASShare::CA_GiveControl(ASPerson * pasTo)
  1094. {
  1095. CA30P packetSend;
  1096. DebugEntry(ASShare::CA_GiveControl);
  1097. ValidatePerson(pasTo);
  1098. ASSERT(pasTo != m_pasLocal);
  1099. //
  1100. // If we aren't hosting or controllable, fail.
  1101. //
  1102. if (!m_pHost)
  1103. {
  1104. WARNING_OUT(("CA_GiveControl: failing, we're not hosting"));
  1105. DC_QUIT;
  1106. }
  1107. if (!m_pasLocal->m_caAllowControl)
  1108. {
  1109. WARNING_OUT(("CA_GiveControl: failing, we're not controllable"));
  1110. DC_QUIT;
  1111. }
  1112. if (pasTo->cpcCaps.general.version < CAPS_VERSION_30)
  1113. {
  1114. //
  1115. // Can't do this with 2.x node.
  1116. //
  1117. WARNING_OUT(("CA_GiveControl: failing, can't invite 2.x node [%d]",
  1118. pasTo->mcsID));
  1119. DC_QUIT;
  1120. }
  1121. //
  1122. // Undo our control state.
  1123. //
  1124. CA_ClearLocalState(CACLEAR_ALL, NULL, TRUE);
  1125. //
  1126. // Now invite control.
  1127. //
  1128. ZeroMemory(&packetSend, sizeof(packetSend));
  1129. packetSend.rgc.hostControlID = CANewRequestID();
  1130. packetSend.rgc.mcsPassFrom = 0;
  1131. if (CAQueueSendPacket(pasTo->mcsID, CA_REQUEST_GIVECONTROL, &packetSend))
  1132. {
  1133. //
  1134. // Now we're in waiting state.
  1135. //
  1136. CAStartWaiting(pasTo, CA_REPLY_REQUEST_GIVECONTROL);
  1137. }
  1138. else
  1139. {
  1140. WARNING_OUT(("CA_GiveControl of [%d]: failing, out of memory", pasTo->mcsID));
  1141. }
  1142. DC_EXIT_POINT:
  1143. DebugExitVOID(ASShare::CA_GiveControl);
  1144. }
  1145. //
  1146. // CA_CancelGiveControl()
  1147. // Cancels an invite TAKE or PASS request.
  1148. //
  1149. void ASShare::CA_CancelGiveControl
  1150. (
  1151. ASPerson * pasTo,
  1152. BOOL fPacket
  1153. )
  1154. {
  1155. DebugEntry(ASShare::CA_CancelGiveControl);
  1156. ValidatePerson(pasTo);
  1157. ASSERT(pasTo != m_pasLocal);
  1158. //
  1159. // Have we invited this person, and are we now waiting for a response?
  1160. //
  1161. if ((m_caWaitingForReplyFrom != pasTo) ||
  1162. (m_caWaitingForReplyMsg != CA_REPLY_REQUEST_GIVECONTROL))
  1163. {
  1164. // We're not waiting to be controlled by this viewer.
  1165. WARNING_OUT(("CA_CancelGiveControl failing; not waiting to give control to [%d]",
  1166. pasTo->mcsID));
  1167. DC_QUIT;
  1168. }
  1169. ASSERT(pasTo->cpcCaps.general.version >= CAPS_VERSION_30);
  1170. ASSERT(!pasTo->m_caControlID);
  1171. if (fPacket)
  1172. {
  1173. CA30P packetSend;
  1174. ZeroMemory(&packetSend, sizeof(packetSend));
  1175. packetSend.inform.viewerControlID = pasTo->m_caControlID;
  1176. packetSend.inform.hostControlID = m_pasLocal->m_caControlID;
  1177. if (!CAQueueSendPacket(pasTo->mcsID, CA_INFORM_REVOKEDCONTROL,
  1178. &packetSend))
  1179. {
  1180. WARNING_OUT(("Couldn't tell node [%d] they're no longer invited to control us",
  1181. pasTo->mcsID));
  1182. }
  1183. }
  1184. m_caWaitingForReplyFrom = NULL;
  1185. m_caWaitingForReplyMsg = 0;
  1186. DC_EXIT_POINT:
  1187. DebugExitVOID(ASShare::CA_CancelGiveControl);
  1188. }
  1189. //
  1190. // CA_RevokeControl()
  1191. // Takes control back. If we're cleaning up (we've stopped hosting or
  1192. //
  1193. //
  1194. void ASShare::CA_RevokeControl
  1195. (
  1196. ASPerson * pasInControl,
  1197. BOOL fPacket
  1198. )
  1199. {
  1200. CA30P packetSend;
  1201. PCAREQUEST pRequest;
  1202. DebugEntry(ASShare::CA_RevokeControl);
  1203. //
  1204. // If the response to pasController is still queued, simply delete it.
  1205. // There should NOT be any CARESULT_CONFIRMED responses left.
  1206. //
  1207. // Otherwise, if it wasn't found, we must send a packet.
  1208. //
  1209. ValidatePerson(pasInControl);
  1210. ASSERT(pasInControl != m_pasLocal);
  1211. if (pasInControl != m_pasLocal->m_caControlledBy)
  1212. {
  1213. WARNING_OUT(("CA_RevokeControl: node [%d] not in control of us",
  1214. pasInControl->mcsID));
  1215. DC_QUIT;
  1216. }
  1217. //
  1218. // Take control back if we're being controlled
  1219. //
  1220. if (fPacket)
  1221. {
  1222. //
  1223. // Regardless of whether we can queue or not, we get control back!
  1224. // Note that we use the controller's request ID, so he knows if
  1225. // this is still applicable.
  1226. //
  1227. ZeroMemory(&packetSend, sizeof(packetSend));
  1228. packetSend.inform.viewerControlID = pasInControl->m_caControlID;
  1229. packetSend.inform.hostControlID = m_pasLocal->m_caControlID;
  1230. if (!CAQueueSendPacket(pasInControl->mcsID, CA_INFORM_REVOKEDCONTROL,
  1231. &packetSend))
  1232. {
  1233. WARNING_OUT(("Couldn't tell node [%d] they're no longer in control",
  1234. pasInControl->mcsID));
  1235. }
  1236. }
  1237. CAStopControlled();
  1238. DC_EXIT_POINT:
  1239. DebugExitVOID(ASShare::CA_RevokeControl);
  1240. }
  1241. //
  1242. // CA_PauseControl()
  1243. //
  1244. void ASShare::CA_PauseControl
  1245. (
  1246. ASPerson * pasControlledBy,
  1247. BOOL fPause,
  1248. BOOL fPacket
  1249. )
  1250. {
  1251. DebugEntry(ASShare::CA_PauseControl);
  1252. ValidatePerson(pasControlledBy);
  1253. ASSERT(pasControlledBy != m_pasLocal);
  1254. //
  1255. // If we aren't a controlled host, this doesn't do anything.
  1256. //
  1257. if (pasControlledBy != m_pasLocal->m_caControlledBy)
  1258. {
  1259. WARNING_OUT(("CA_PauseControl failing; not controlled by [%d]", pasControlledBy->mcsID));
  1260. DC_QUIT;
  1261. }
  1262. ASSERT(m_pHost);
  1263. ASSERT(m_pasLocal->m_caAllowControl);
  1264. if (m_pasLocal->m_caControlPaused == (fPause != FALSE))
  1265. {
  1266. WARNING_OUT(("CA_PauseControl failing; already in requested state"));
  1267. DC_QUIT;
  1268. }
  1269. if (fPacket)
  1270. {
  1271. CA30P packetSend;
  1272. ZeroMemory(&packetSend, sizeof(packetSend));
  1273. packetSend.inform.viewerControlID = m_pasLocal->m_caControlledBy->m_caControlID;
  1274. packetSend.inform.hostControlID = m_pasLocal->m_caControlID;
  1275. if (!CAQueueSendPacket(m_pasLocal->m_caControlledBy->mcsID,
  1276. (fPause ? CA_INFORM_PAUSEDCONTROL : CA_INFORM_UNPAUSEDCONTROL),
  1277. &packetSend))
  1278. {
  1279. WARNING_OUT(("CA_PauseControl: out of memory, can't notify [%d]",
  1280. m_pasLocal->m_caControlledBy->mcsID));
  1281. }
  1282. }
  1283. // Do pause
  1284. m_pasLocal->m_caControlPaused = (fPause != FALSE);
  1285. g_lpimSharedData->imPaused = (fPause != FALSE);
  1286. DCS_NotifyUI((fPause ? SH_EVT_PAUSEDCONTROLLED : SH_EVT_UNPAUSEDCONTROLLED),
  1287. pasControlledBy->cpcCaps.share.gccID, 0);
  1288. DC_EXIT_POINT:
  1289. DebugExitVOID(ASShare::CA_PauseControl);
  1290. }
  1291. //
  1292. // CAHandleRequestTakeControl()
  1293. // WE are HOST, REMOTE is VIEWER
  1294. // Handles incoming take control request. If our state is good, we accept.
  1295. //
  1296. void ASShare::CAHandleRequestTakeControl
  1297. (
  1298. ASPerson * pasViewer,
  1299. PCA_RTC_PACKET pPacketRecv
  1300. )
  1301. {
  1302. UINT result = CARESULT_CONFIRMED;
  1303. DebugEntry(ASShare::CAHandleRequestTakeControl);
  1304. ValidatePerson(pasViewer);
  1305. //
  1306. // If we aren't hosting, or haven't turned allow control on, we're
  1307. // not controllable.
  1308. //
  1309. if (!m_pHost || !m_pasLocal->m_caAllowControl)
  1310. {
  1311. result = CARESULT_DENIED_WRONGSTATE;
  1312. goto RESPOND_PACKET;
  1313. }
  1314. //
  1315. // Are we doing something else right now? Waiting to hear back about
  1316. // something?
  1317. //
  1318. if (m_caWaitingForReplyFrom)
  1319. {
  1320. result = CARESULT_DENIED_BUSY;
  1321. goto RESPOND_PACKET;
  1322. }
  1323. if (m_caQueryDlg)
  1324. {
  1325. result = CARESULT_DENIED_BUSY;
  1326. goto RESPOND_PACKET;
  1327. }
  1328. //
  1329. // LAURABU TEMPORARY:
  1330. // In a bit, if we're controlled when a new control request comes in,
  1331. // pause control then allow host to handle it.
  1332. //
  1333. if (m_pasLocal->m_caControlledBy)
  1334. {
  1335. result = CARESULT_DENIED_BUSY;
  1336. goto RESPOND_PACKET;
  1337. }
  1338. //
  1339. // Try to put up query dialog
  1340. //
  1341. if (!CAStartQuery(pasViewer, CA_REQUEST_TAKECONTROL, (PCA30P)pPacketRecv))
  1342. {
  1343. result = CARESULT_DENIED;
  1344. }
  1345. RESPOND_PACKET:
  1346. if (result != CARESULT_CONFIRMED)
  1347. {
  1348. // Instant failure.
  1349. CACompleteRequestTakeControl(pasViewer, pPacketRecv, result);
  1350. }
  1351. else
  1352. {
  1353. //
  1354. // We're in a waiting state. CACompleteRequestTakeControl() will
  1355. // complete later or the request will just go away.
  1356. //
  1357. }
  1358. DebugExitVOID(ASShare::CAHandleRequestTakeControl);
  1359. }
  1360. //
  1361. // CACompleteRequestTakeControl()
  1362. // WE are HOST, REMOTE is VIEWER
  1363. // Completes the take control request.
  1364. //
  1365. void ASShare::CACompleteRequestTakeControl
  1366. (
  1367. ASPerson * pasFrom,
  1368. PCA_RTC_PACKET pPacketRecv,
  1369. UINT result
  1370. )
  1371. {
  1372. CA30P packetSend;
  1373. DebugEntry(ASShare::CACompleteRequestTakeControl);
  1374. ValidatePerson(pasFrom);
  1375. ZeroMemory(&packetSend, sizeof(packetSend));
  1376. packetSend.rrtc.viewerControlID = pPacketRecv->viewerControlID;
  1377. packetSend.rrtc.result = result;
  1378. if (result == CARESULT_CONFIRMED)
  1379. {
  1380. packetSend.rrtc.hostControlID = CANewRequestID();
  1381. }
  1382. if (CAQueueSendPacket(pasFrom->mcsID, CA_REPLY_REQUEST_TAKECONTROL, &packetSend))
  1383. {
  1384. if (result == CARESULT_CONFIRMED)
  1385. {
  1386. // Clear current state, whatever that is.
  1387. CA_ClearLocalState(CACLEAR_ALL, NULL, TRUE);
  1388. // We are now controlled by the sender.
  1389. CAStartControlled(pasFrom, pPacketRecv->viewerControlID);
  1390. }
  1391. else
  1392. {
  1393. WARNING_OUT(("Denying REQUEST TAKE CONTROL from [%d] with reason %d",
  1394. pasFrom->mcsID, result));
  1395. }
  1396. }
  1397. else
  1398. {
  1399. WARNING_OUT(("Reply to REQUEST TAKE CONTROL from [%d] failing, out of memory",
  1400. pasFrom->mcsID));
  1401. }
  1402. DebugExitVOID(ASShare::CACompleteRequestTakeControl);
  1403. }
  1404. //
  1405. // CAHandleReplyRequestTakeControl()
  1406. // WE are VIEWER, REMOTE is HOST
  1407. // Handles reply to previous take control request.
  1408. //
  1409. void ASShare::CAHandleReplyRequestTakeControl
  1410. (
  1411. ASPerson * pasHost,
  1412. PCA_REPLY_RTC_PACKET pPacketRecv
  1413. )
  1414. {
  1415. DebugEntry(ASShare::CAHandleReplyRequestTakeControl);
  1416. ValidatePerson(pasHost);
  1417. if (pPacketRecv->result == CARESULT_CONFIRMED)
  1418. {
  1419. // On success, should have valid op ID.
  1420. ASSERT(pPacketRecv->hostControlID);
  1421. }
  1422. else
  1423. {
  1424. // On failure, should have invalid op ID.
  1425. ASSERT(!pPacketRecv->hostControlID);
  1426. }
  1427. //
  1428. // Is this response for the current control op?
  1429. //
  1430. if ((m_caWaitingForReplyFrom != pasHost) ||
  1431. (m_caWaitingForReplyMsg != CA_REPLY_REQUEST_TAKECONTROL))
  1432. {
  1433. WARNING_OUT(("Ignoring TAKE CONTROL REPLY from [%d], not waiting for one",
  1434. pasHost->mcsID));
  1435. DC_QUIT;
  1436. }
  1437. if (pPacketRecv->viewerControlID != m_pasLocal->m_caControlID)
  1438. {
  1439. WARNING_OUT(("Ignoring TAKE CONTROL REPLY from [%d], request %d is out of date",
  1440. pasHost->mcsID, pPacketRecv->viewerControlID));
  1441. DC_QUIT;
  1442. }
  1443. ASSERT(!m_caQueryDlg);
  1444. //
  1445. // Cleanup waiting state (for both failure & success)
  1446. //
  1447. CA_CancelTakeControl(pasHost, FALSE);
  1448. ASSERT(!m_caWaitingForReplyFrom);
  1449. ASSERT(!m_caWaitingForReplyMsg);
  1450. if (pPacketRecv->result == CARESULT_CONFIRMED)
  1451. {
  1452. // Success! We're now in control of the host.
  1453. // Make sure our own state is OK
  1454. ASSERT(!m_pasLocal->m_caControlledBy);
  1455. ASSERT(!m_pasLocal->m_caInControlOf);
  1456. CAStartInControl(pasHost, pPacketRecv->hostControlID);
  1457. }
  1458. else
  1459. {
  1460. UINT ids;
  1461. WARNING_OUT(("TAKE CONTROL REPLY from host [%d] is failure %d", pasHost->mcsID,
  1462. pPacketRecv->result));
  1463. ids = IDS_ERR_TAKECONTROL_MIN + pPacketRecv->result;
  1464. if ((ids < IDS_ERR_TAKECONTROL_FIRST) || (ids > IDS_ERR_TAKECONTROL_LAST))
  1465. ids = IDS_ERR_TAKECONTROL_LAST;
  1466. VIEW_Message(pasHost, ids);
  1467. }
  1468. DC_EXIT_POINT:
  1469. DebugExitVOID(ASShare::CAHandleReplyRequestTakeControl);
  1470. }
  1471. //
  1472. // CAHandleRequestGiveControl()
  1473. // WE are VIEWER, REMOTE is HOST
  1474. // Handles incoming take control invite. If our state is good, we accept.
  1475. //
  1476. // NOTE how similar this routine is to CAHandleRequestTakeControl(). They
  1477. // are inverses of each other. With RequestTake/Reply sequence, viewer
  1478. // initiates, host finishes. With RequestGive/Reply sequence, host initiates,
  1479. // viewer finishes. Both end up with viewer in control of host when
  1480. // completed successfully.
  1481. //
  1482. void ASShare::CAHandleRequestGiveControl
  1483. (
  1484. ASPerson * pasHost,
  1485. PCA_RGC_PACKET pPacketRecv
  1486. )
  1487. {
  1488. UINT result = CARESULT_CONFIRMED;
  1489. DebugEntry(ASShare::CAHandleRequestGiveControl);
  1490. ValidatePerson(pasHost);
  1491. //
  1492. // Is this node hosting as far as we know. If not, or has not turned
  1493. // on allow control, we can't do it.
  1494. //
  1495. if (!pasHost->m_pView)
  1496. {
  1497. WARNING_OUT(("GIVE CONTROL went ahead of HOSTING, that's bad"));
  1498. result = CARESULT_DENIED_WRONGSTATE;
  1499. goto RESPOND_PACKET;
  1500. }
  1501. if (!pasHost->m_caAllowControl)
  1502. {
  1503. //
  1504. // We haven't got an AllowControl notification yet, this info is
  1505. // more up to-date. Make use of it.
  1506. //
  1507. WARNING_OUT(("GIVE CONTROL went ahead of ALLOW CONTROL, that's kind of bad"));
  1508. result = CARESULT_DENIED_WRONGSTATE;
  1509. goto RESPOND_PACKET;
  1510. }
  1511. //
  1512. // Are we doing something else right now? Waiting to hear back about
  1513. // something?
  1514. //
  1515. if (m_caWaitingForReplyFrom)
  1516. {
  1517. result = CARESULT_DENIED_BUSY;
  1518. goto RESPOND_PACKET;
  1519. }
  1520. if (m_caQueryDlg)
  1521. {
  1522. result = CARESULT_DENIED_BUSY;
  1523. goto RESPOND_PACKET;
  1524. }
  1525. //
  1526. // LAURABU TEMPORARY:
  1527. // In a bit, if we're controlled when a new control request comes in,
  1528. // pause control then allow host to handle it.
  1529. //
  1530. if (m_pasLocal->m_caControlledBy)
  1531. {
  1532. result = CARESULT_DENIED_BUSY;
  1533. goto RESPOND_PACKET;
  1534. }
  1535. //
  1536. // Try to put up query dialog
  1537. //
  1538. if (!CAStartQuery(pasHost, CA_REQUEST_GIVECONTROL, (PCA30P)pPacketRecv))
  1539. {
  1540. result = CARESULT_DENIED;
  1541. }
  1542. RESPOND_PACKET:
  1543. if (result != CARESULT_CONFIRMED)
  1544. {
  1545. // Instant failure.
  1546. CACompleteRequestGiveControl(pasHost, pPacketRecv, result);
  1547. }
  1548. else
  1549. {
  1550. //
  1551. // We're in a waiting state. CACompleteRequestGiveControl() will
  1552. // complete later or the request will just go away.
  1553. //
  1554. }
  1555. DebugExitVOID(ASShare::CAHandleRequestGiveControl);
  1556. }
  1557. //
  1558. // CACompleteRequestGiveControl()
  1559. // WE are VIEWER, REMOTE is HOST
  1560. // Completes the invite control request.
  1561. //
  1562. void ASShare::CACompleteRequestGiveControl
  1563. (
  1564. ASPerson * pasFrom,
  1565. PCA_RGC_PACKET pPacketRecv,
  1566. UINT result
  1567. )
  1568. {
  1569. CA30P packetSend;
  1570. DebugEntry(ASShare::CACompleteRequestGiveControl);
  1571. ValidatePerson(pasFrom);
  1572. ZeroMemory(&packetSend, sizeof(packetSend));
  1573. packetSend.rrgc.hostControlID = pPacketRecv->hostControlID;
  1574. packetSend.rrgc.result = result;
  1575. if (result == CARESULT_CONFIRMED)
  1576. {
  1577. packetSend.rrgc.viewerControlID = CANewRequestID();
  1578. }
  1579. if (CAQueueSendPacket(pasFrom->mcsID, CA_REPLY_REQUEST_GIVECONTROL, &packetSend))
  1580. {
  1581. //
  1582. // If this is successful, change our state. We're now in control.
  1583. //
  1584. if (result == CARESULT_CONFIRMED)
  1585. {
  1586. // Clear current state, whatever that is.
  1587. CA_ClearLocalState(CACLEAR_ALL, NULL, TRUE);
  1588. CAStartInControl(pasFrom, pPacketRecv->hostControlID);
  1589. }
  1590. else
  1591. {
  1592. WARNING_OUT(("Denying GIVE CONTROL from [%d] with reason %d",
  1593. pasFrom->mcsID, result));
  1594. }
  1595. }
  1596. else
  1597. {
  1598. WARNING_OUT(("Reply to GIVE CONTROL from [%d] failing, out of memory",
  1599. pasFrom->mcsID));
  1600. }
  1601. DebugExitVOID(ASShare::CACompleteRequestGiveControl);
  1602. }
  1603. //
  1604. // CAHandleReplyRequestGiveControl()
  1605. // WE are HOST, REMOTE is VIEWER
  1606. // Handles reply to previous take control invite.
  1607. //
  1608. void ASShare::CAHandleReplyRequestGiveControl
  1609. (
  1610. ASPerson * pasViewer,
  1611. PCA_REPLY_RGC_PACKET pPacketRecv
  1612. )
  1613. {
  1614. DebugEntry(ASShare::CAHandleReplyRequestGiveControl);
  1615. ValidatePerson(pasViewer);
  1616. if (pPacketRecv->result == CARESULT_CONFIRMED)
  1617. {
  1618. // On success, should have valid op ID.
  1619. ASSERT(pPacketRecv->viewerControlID);
  1620. }
  1621. else
  1622. {
  1623. // On failure, should have invalid op ID.
  1624. ASSERT(!pPacketRecv->viewerControlID);
  1625. }
  1626. //
  1627. // Is this response for the latest control op?
  1628. //
  1629. if ((m_caWaitingForReplyFrom != pasViewer) ||
  1630. (m_caWaitingForReplyMsg != CA_REPLY_REQUEST_GIVECONTROL))
  1631. {
  1632. WARNING_OUT(("Ignoring GIVE CONTROL REPLY from [%d], not waiting for one",
  1633. pasViewer->mcsID));
  1634. DC_QUIT;
  1635. }
  1636. if (pPacketRecv->hostControlID != m_pasLocal->m_caControlID)
  1637. {
  1638. WARNING_OUT(("Ignoring GIVE CONTROL REPLY from [%d], request %d is out of date",
  1639. pasViewer->mcsID, pPacketRecv->hostControlID));
  1640. DC_QUIT;
  1641. }
  1642. ASSERT(!m_caQueryDlg);
  1643. ASSERT(m_pHost);
  1644. ASSERT(m_pasLocal->m_caAllowControl);
  1645. //
  1646. // Cleanup waiting state (for both failure & success)
  1647. //
  1648. CA_CancelGiveControl(pasViewer, FALSE);
  1649. ASSERT(!m_caWaitingForReplyFrom);
  1650. ASSERT(!m_caWaitingForReplyMsg);
  1651. if (pPacketRecv->result == CARESULT_CONFIRMED)
  1652. {
  1653. // Success! We are now controlled by the viewer
  1654. // Make sure our own state is OK
  1655. ASSERT(!m_pasLocal->m_caControlledBy);
  1656. ASSERT(!m_pasLocal->m_caInControlOf);
  1657. CAStartControlled(pasViewer, pPacketRecv->viewerControlID);
  1658. }
  1659. else
  1660. {
  1661. WARNING_OUT(("GIVE CONTROL to viewer [%d] was denied", pasViewer->mcsID));
  1662. }
  1663. DC_EXIT_POINT:
  1664. DebugExitVOID(ASShare::CAHandleReplyRequestGiveControl);
  1665. }
  1666. //
  1667. // CAHandlePreferPassControl()
  1668. // WE are HOST, REMOTE is CONTROLLER
  1669. // Handles incoming pass control request. If we are controlled by the
  1670. // remote, and end user is cool with it, accept.
  1671. //
  1672. void ASShare::CAHandlePreferPassControl
  1673. (
  1674. ASPerson * pasController,
  1675. PCA_PPC_PACKET pPacketRecv
  1676. )
  1677. {
  1678. ASPerson * pasNewController;
  1679. DebugEntry(ASShare::CAHandlePreferPassControl);
  1680. ValidatePerson(pasController);
  1681. //
  1682. // If we're not controlled by the requester, ignore it.
  1683. //
  1684. if (m_pasLocal->m_caControlledBy != pasController)
  1685. {
  1686. WARNING_OUT(("Ignoring PASS CONTROL from [%d], not controlled by him",
  1687. pasController->mcsID));
  1688. DC_QUIT;
  1689. }
  1690. if ((pPacketRecv->viewerControlID != pasController->m_caControlID) ||
  1691. (pPacketRecv->hostControlID != m_pasLocal->m_caControlID))
  1692. {
  1693. WARNING_OUT(("Ignoring PASS CONTROL from [%d], request %d %d out of date",
  1694. pasController->mcsID, pPacketRecv->viewerControlID, pPacketRecv->hostControlID));
  1695. DC_QUIT;
  1696. }
  1697. ASSERT(!m_caQueryDlg);
  1698. ASSERT(!m_caWaitingForReplyFrom);
  1699. ASSERT(!m_caWaitingForReplyMsg);
  1700. //
  1701. // OK, the sender is not in control of us anymore.
  1702. //
  1703. CA_RevokeControl(pasController, FALSE);
  1704. // Is the pass to person specified valid?
  1705. pasNewController = SC_PersonFromNetID(pPacketRecv->mcsPassTo);
  1706. if (!pasNewController ||
  1707. (pasNewController == pasController) ||
  1708. (pasNewController == m_pasLocal) ||
  1709. (pasNewController->cpcCaps.general.version < CAPS_VERSION_30))
  1710. {
  1711. WARNING_OUT(("PASS CONTROL to [%d] failing, not valid person to pass to",
  1712. pPacketRecv->mcsPassTo));
  1713. DC_QUIT;
  1714. }
  1715. //
  1716. // Try to put up query dialog
  1717. //
  1718. if (!CAStartQuery(pasController, CA_PREFER_PASSCONTROL, (PCA30P)pPacketRecv))
  1719. {
  1720. // Instant failure. In this case, no packet.
  1721. WARNING_OUT(("Denying PREFER PASS CONTROL from [%d], out of memory",
  1722. pasController->mcsID));
  1723. }
  1724. else
  1725. {
  1726. //
  1727. // We're in a waiting state. CACompletePreferPassControl() will
  1728. // complete later or the request will just go away.
  1729. //
  1730. }
  1731. DC_EXIT_POINT:
  1732. DebugExitVOID(ASShare::CAHandlePreferPassControl);
  1733. }
  1734. //
  1735. // CACompletePreferPassControl()
  1736. // WE are HOST, REMOTE is new potential CONTROLLER
  1737. // Completes the prefer pass control request.
  1738. //
  1739. void ASShare::CACompletePreferPassControl
  1740. (
  1741. ASPerson * pasTo,
  1742. UINT_PTR mcsOrg,
  1743. PCA_PPC_PACKET pPacketRecv,
  1744. UINT result
  1745. )
  1746. {
  1747. CA30P packetSend;
  1748. DebugEntry(ASShare::CACompletePreferPassControl);
  1749. ValidatePerson(pasTo);
  1750. if (result == CARESULT_CONFIRMED)
  1751. {
  1752. ZeroMemory(&packetSend, sizeof(packetSend));
  1753. packetSend.rgc.hostControlID = CANewRequestID();
  1754. packetSend.rgc.mcsPassFrom = mcsOrg;
  1755. if (CAQueueSendPacket(pasTo->mcsID, CA_REQUEST_GIVECONTROL,
  1756. &packetSend))
  1757. {
  1758. CA_ClearLocalState(CACLEAR_HOST, NULL, TRUE);
  1759. CAStartWaiting(pasTo, CA_REPLY_REQUEST_GIVECONTROL);
  1760. }
  1761. else
  1762. {
  1763. WARNING_OUT(("Reply to PREFER PASS CONTROL from [%d] to [%d] failing, out of memory",
  1764. mcsOrg, pasTo->mcsID));
  1765. }
  1766. }
  1767. else
  1768. {
  1769. WARNING_OUT(("Denying PREFER PASS CONTROL from [%d] to [%d] with reason %d",
  1770. mcsOrg, pasTo->mcsID, result));
  1771. }
  1772. DebugExitVOID(ASShare::CACompletePreferPassControl);
  1773. }
  1774. //
  1775. // CAHandleInformReleasedControl()
  1776. // WE are HOST, REMOTE is CONTROLLER
  1777. //
  1778. void ASShare::CAHandleInformReleasedControl
  1779. (
  1780. ASPerson * pasController,
  1781. PCA_INFORM_PACKET pPacketRecv
  1782. )
  1783. {
  1784. DebugEntry(ASShare::CAHandleInformReleasedControl);
  1785. ValidatePerson(pasController);
  1786. //
  1787. // Do we currently have a TakeControl dialog up for this request? If so,
  1788. // take it down but don't send a packet.
  1789. //
  1790. if (m_caQueryDlg &&
  1791. (m_caQuery.pasReplyTo == pasController) &&
  1792. (m_caQuery.msg == CA_REQUEST_TAKECONTROL) &&
  1793. (m_caQuery.request.rtc.viewerControlID == pPacketRecv->viewerControlID))
  1794. {
  1795. ASSERT(!pPacketRecv->hostControlID);
  1796. CACancelQuery(pasController, FALSE);
  1797. DC_QUIT;
  1798. }
  1799. //
  1800. // If this person isn't in control of us or the control op referred to
  1801. // isn't the current one, ignore. NULL hostControlID means the person
  1802. // cancelled a request before they heard back from us.
  1803. //
  1804. if (pasController->m_caInControlOf != m_pasLocal)
  1805. {
  1806. WARNING_OUT(("Ignoring RELEASE CONTROL from [%d], we're not controlled by them",
  1807. pasController->mcsID));
  1808. DC_QUIT;
  1809. }
  1810. if (pPacketRecv->viewerControlID != pasController->m_caControlID)
  1811. {
  1812. WARNING_OUT(("Ignoring RELEASE CONTROL from [%d], viewer ID out of date",
  1813. pasController->mcsID, pPacketRecv->viewerControlID));
  1814. DC_QUIT;
  1815. }
  1816. if (pPacketRecv->hostControlID && (pPacketRecv->hostControlID != m_pasLocal->m_caControlID))
  1817. {
  1818. WARNING_OUT(("Ignoring RELEASE CONTROL from [%d], host ID out of date",
  1819. pasController->mcsID, pPacketRecv->hostControlID));
  1820. DC_QUIT;
  1821. }
  1822. // Undo control, but no packet gets sent, we're just cleaning up.
  1823. CA_RevokeControl(pasController, FALSE);
  1824. DC_EXIT_POINT:
  1825. DebugExitVOID(ASShare::CAHandleInformReleasedControl);
  1826. }
  1827. //
  1828. // CAHandleInformRevokedControl()
  1829. // WE are CONTROLLER, REMOTE is HOST
  1830. //
  1831. void ASShare::CAHandleInformRevokedControl
  1832. (
  1833. ASPerson * pasHost,
  1834. PCA_INFORM_PACKET pPacketRecv
  1835. )
  1836. {
  1837. DebugEntry(ASShare::CAHandleInformRevokedControl);
  1838. ValidatePerson(pasHost);
  1839. //
  1840. // Do we currently have a GiveControl dialog up for this request? If so,
  1841. // take it down but don't send a packet.
  1842. //
  1843. if (m_caQueryDlg &&
  1844. (m_caQuery.pasReplyTo == pasHost) &&
  1845. (m_caQuery.msg == CA_REQUEST_GIVECONTROL) &&
  1846. (m_caQuery.request.rgc.hostControlID == pPacketRecv->hostControlID))
  1847. {
  1848. ASSERT(!pPacketRecv->viewerControlID);
  1849. CACancelQuery(pasHost, FALSE);
  1850. DC_QUIT;
  1851. }
  1852. //
  1853. // If this person isn't controlled by us or the control op referred to
  1854. // isn't the current one, ignore.
  1855. //
  1856. if (pasHost->m_caControlledBy != m_pasLocal)
  1857. {
  1858. WARNING_OUT(("Ignoring REVOKE CONTROL from [%d], not in control of them",
  1859. pasHost->mcsID));
  1860. DC_QUIT;
  1861. }
  1862. if (pPacketRecv->hostControlID != pasHost->m_caControlID)
  1863. {
  1864. WARNING_OUT(("Ignoring REVOKE CONTROL from [%d], host ID out of date",
  1865. pasHost->mcsID, pPacketRecv->hostControlID));
  1866. DC_QUIT;
  1867. }
  1868. if (pPacketRecv->viewerControlID && (pPacketRecv->viewerControlID != m_pasLocal->m_caControlID))
  1869. {
  1870. WARNING_OUT(("Ignoring REVOKE CONTROL from [%d], viewer ID out of date",
  1871. pasHost->mcsID, pPacketRecv->viewerControlID));
  1872. DC_QUIT;
  1873. }
  1874. // Undo control, but no packet gets sent, we're just cleaning up.
  1875. CA_ReleaseControl(pasHost, FALSE);
  1876. DC_EXIT_POINT:
  1877. DebugExitVOID(ASShare::CAHandleInformRevokedControl);
  1878. }
  1879. //
  1880. // CAHandleInformPausedControl()
  1881. // WE are CONTROLLER, REMOTE is HOST
  1882. //
  1883. void ASShare::CAHandleInformPausedControl
  1884. (
  1885. ASPerson * pasHost,
  1886. PCA_INFORM_PACKET pPacketRecv
  1887. )
  1888. {
  1889. DebugEntry(ASShare::CAHandleInformPausedControl);
  1890. ValidatePerson(pasHost);
  1891. if (pasHost->m_caControlledBy != m_pasLocal)
  1892. {
  1893. WARNING_OUT(("Ignoring control paused from [%d], not controlled by us",
  1894. pasHost->mcsID));
  1895. DC_QUIT;
  1896. }
  1897. if (pasHost->m_caControlPaused)
  1898. {
  1899. WARNING_OUT(("Ignoring control paused from [%d], already paused",
  1900. pasHost->mcsID));
  1901. DC_QUIT;
  1902. }
  1903. pasHost->m_caControlPaused = TRUE;
  1904. VIEW_PausedInControl(pasHost, TRUE);
  1905. DCS_NotifyUI(SH_EVT_PAUSEDINCONTROL, pasHost->cpcCaps.share.gccID, 0);
  1906. DC_EXIT_POINT:
  1907. DebugExitVOID(ASShare::CAHandleInformPausedControl);
  1908. }
  1909. //
  1910. // CAHandleInformUnpausedControl()
  1911. // WE are CONTROLLER, REMOTE is HOST
  1912. //
  1913. void ASShare::CAHandleInformUnpausedControl
  1914. (
  1915. ASPerson * pasHost,
  1916. PCA_INFORM_PACKET pPacketRecv
  1917. )
  1918. {
  1919. DebugEntry(ASShare::CAHandleInformUnpausedControl);
  1920. ValidatePerson(pasHost);
  1921. if (pasHost->m_caControlledBy != m_pasLocal)
  1922. {
  1923. WARNING_OUT(("Ignoring control unpaused from [%d], not controlled by us",
  1924. pasHost->mcsID));
  1925. DC_QUIT;
  1926. }
  1927. if (!pasHost->m_caControlPaused)
  1928. {
  1929. WARNING_OUT(("Ignoring control unpaused from [%d], not paused",
  1930. pasHost->mcsID));
  1931. DC_QUIT;
  1932. }
  1933. pasHost->m_caControlPaused = FALSE;
  1934. VIEW_PausedInControl(pasHost, FALSE);
  1935. DCS_NotifyUI(SH_EVT_UNPAUSEDINCONTROL, pasHost->cpcCaps.share.gccID, 0);
  1936. DC_EXIT_POINT:
  1937. DebugExitVOID(ASShare::CAHandleInformUnpausedControl);
  1938. }
  1939. void ASShare::CAHandleNewState
  1940. (
  1941. ASPerson * pasHost,
  1942. PCANOTPACKET pPacket
  1943. )
  1944. {
  1945. BOOL caOldAllowControl;
  1946. BOOL caNewAllowControl;
  1947. ASPerson * pasController;
  1948. DebugEntry(ASShare::CAHandleNewState);
  1949. //
  1950. // If this node isn't hosting, ignore this.
  1951. //
  1952. ValidatePerson(pasHost);
  1953. ASSERT(pasHost->cpcCaps.general.version >= CAPS_VERSION_30);
  1954. ASSERT(pasHost->hetCount);
  1955. //
  1956. // Update controllable state FIRST, so view window changes will
  1957. // reflect it.
  1958. //
  1959. caOldAllowControl = pasHost->m_caAllowControl;
  1960. caNewAllowControl = ((pPacket->state & CASTATE_ALLOWCONTROL) != 0);
  1961. if (!caNewAllowControl && (pasHost->m_caControlledBy == m_pasLocal))
  1962. {
  1963. //
  1964. // Fix up bogus notification
  1965. //
  1966. ERROR_OUT(("CA_STATE notification error! We're in control of [%d] but he says he's not controllable.",
  1967. pasHost->mcsID));
  1968. CA_ReleaseControl(pasHost, FALSE);
  1969. }
  1970. pasHost->m_caAllowControl = caNewAllowControl;
  1971. // Update/clear controller
  1972. if (!pPacket->controllerID)
  1973. {
  1974. pasController = NULL;
  1975. }
  1976. else
  1977. {
  1978. pasController = SC_PersonFromNetID(pPacket->controllerID);
  1979. if (pasController == pasHost)
  1980. {
  1981. ERROR_OUT(("Bogus controller, same as host [%d]", pPacket->controllerID));
  1982. pasController = NULL;
  1983. }
  1984. }
  1985. if (!CAClearHostState(pasHost, pasController))
  1986. {
  1987. // This failed. Put back old controllable state.
  1988. pasHost->m_caAllowControl = caOldAllowControl;
  1989. }
  1990. // Force a state change if the allow state has altered
  1991. if (caOldAllowControl != pasHost->m_caAllowControl)
  1992. {
  1993. VIEW_HostStateChange(pasHost);
  1994. }
  1995. DebugExitVOID(ASShare::CAHandleNewState);
  1996. }
  1997. //
  1998. // CAStartWaiting()
  1999. // Sets up vars for waiting state.
  2000. //
  2001. void ASShare::CAStartWaiting
  2002. (
  2003. ASPerson * pasWaitForReplyFrom,
  2004. UINT msgWaitForReplyFrom
  2005. )
  2006. {
  2007. DebugEntry(ASShare::CAStartWaiting);
  2008. ValidatePerson(pasWaitForReplyFrom);
  2009. ASSERT(msgWaitForReplyFrom);
  2010. ASSERT(!m_caWaitingForReplyFrom);
  2011. ASSERT(!m_caWaitingForReplyMsg);
  2012. m_caWaitingForReplyFrom = pasWaitForReplyFrom;
  2013. m_caWaitingForReplyMsg = msgWaitForReplyFrom;
  2014. DebugExitVOID(ASShare::CAStartWaiting);
  2015. }
  2016. //
  2017. // CA_ClearLocalState()
  2018. //
  2019. // Called to reset control state for LOCAL dude.
  2020. //
  2021. void ASShare::CA_ClearLocalState
  2022. (
  2023. UINT flags,
  2024. ASPerson * pasRemote,
  2025. BOOL fPacket
  2026. )
  2027. {
  2028. DebugEntry(ASShare::CA_ClearLocalState);
  2029. //
  2030. // Clear HOST stuff
  2031. //
  2032. if (flags & CACLEAR_HOST)
  2033. {
  2034. if (m_caWaitingForReplyMsg == CA_REPLY_REQUEST_GIVECONTROL)
  2035. {
  2036. if (!pasRemote || (pasRemote == m_caWaitingForReplyFrom))
  2037. {
  2038. // Kill the outstanding invitation to the remote
  2039. CA_CancelGiveControl(m_caWaitingForReplyFrom, fPacket);
  2040. }
  2041. }
  2042. if (m_caQueryDlg &&
  2043. ((m_caQuery.msg == CA_REQUEST_TAKECONTROL) ||
  2044. (m_caQuery.msg == CA_PREFER_PASSCONTROL)))
  2045. {
  2046. if (!pasRemote || (pasRemote == m_caQuery.pasReplyTo))
  2047. {
  2048. // Kill the user query dialog that's up
  2049. CACancelQuery(m_caQuery.pasReplyTo, fPacket);
  2050. }
  2051. }
  2052. if (m_pasLocal->m_caControlledBy)
  2053. {
  2054. if (!pasRemote || (pasRemote == m_pasLocal->m_caControlledBy))
  2055. {
  2056. CA_RevokeControl(m_pasLocal->m_caControlledBy, fPacket);
  2057. ASSERT(!m_pasLocal->m_caControlledBy);
  2058. }
  2059. }
  2060. }
  2061. //
  2062. // Clear VIEW stuff
  2063. //
  2064. if (flags & CACLEAR_VIEW)
  2065. {
  2066. if (m_caWaitingForReplyMsg == CA_REPLY_REQUEST_TAKECONTROL)
  2067. {
  2068. if (!pasRemote || (pasRemote == m_caWaitingForReplyFrom))
  2069. {
  2070. CA_CancelTakeControl(m_caWaitingForReplyFrom, fPacket);
  2071. }
  2072. }
  2073. if (m_caQueryDlg && (m_caQuery.msg == CA_REQUEST_GIVECONTROL))
  2074. {
  2075. if (!pasRemote || (pasRemote == m_caQuery.pasReplyTo))
  2076. {
  2077. // Kill the user query dialog that's up
  2078. CACancelQuery(m_caQuery.pasReplyTo, fPacket);
  2079. }
  2080. }
  2081. if (m_pasLocal->m_caInControlOf)
  2082. {
  2083. if (!pasRemote || (pasRemote == m_pasLocal->m_caInControlOf))
  2084. {
  2085. CA_ReleaseControl(m_pasLocal->m_caInControlOf, fPacket);
  2086. ASSERT(!m_pasLocal->m_caInControlOf);
  2087. }
  2088. }
  2089. }
  2090. DebugExitVOID(ASShare::CA_ClearLocalState);
  2091. }
  2092. //
  2093. // CAClearRemoteState()
  2094. //
  2095. // Called to reset all control state for a REMOTE node
  2096. //
  2097. void ASShare::CAClearRemoteState(ASPerson * pasClear)
  2098. {
  2099. DebugEntry(ASShare::CAClearRemoteState);
  2100. if (pasClear->m_caInControlOf)
  2101. {
  2102. CAClearHostState(pasClear->m_caInControlOf, NULL);
  2103. ASSERT(!pasClear->m_caInControlOf);
  2104. ASSERT(!pasClear->m_caControlledBy);
  2105. }
  2106. else if (pasClear->m_caControlledBy)
  2107. {
  2108. CAClearHostState(pasClear, NULL);
  2109. ASSERT(!pasClear->m_caControlledBy);
  2110. ASSERT(!pasClear->m_caInControlOf);
  2111. }
  2112. DebugExitVOID(ASShare:CAClearRemoteState);
  2113. }
  2114. //
  2115. // CAClearHostState()
  2116. //
  2117. // Called to clean up the mutual pointers when undoing a node's host state.
  2118. // We need to undo the previous states:
  2119. // * Clear the previous controller of the host
  2120. // * Clear the previous controller of the controller
  2121. // * Clear the previous controllee of the controller
  2122. //
  2123. // This may be recursive.
  2124. //
  2125. // It returns TRUE if the change takes effect, FALSE if it's ignored because
  2126. // it involves us and we have more recent information.
  2127. //
  2128. BOOL ASShare::CAClearHostState
  2129. (
  2130. ASPerson * pasHost,
  2131. ASPerson * pasController
  2132. )
  2133. {
  2134. BOOL rc = FALSE;
  2135. UINT gccID;
  2136. DebugEntry(ASShare::CAClearHostState);
  2137. ValidatePerson(pasHost);
  2138. //
  2139. // If nothing is changing, do nothing
  2140. //
  2141. if (pasHost->m_caControlledBy == pasController)
  2142. {
  2143. TRACE_OUT(("Ignoring control change; nothing's changing"));
  2144. rc = TRUE;
  2145. DC_QUIT;
  2146. }
  2147. //
  2148. // If the host is us, ignore.
  2149. // Also, if the host isn't hosting yet we got an in control change,
  2150. // ignore it too.
  2151. //
  2152. if ((pasHost == m_pasLocal) ||
  2153. (pasController && !pasHost->hetCount))
  2154. {
  2155. WARNING_OUT(("Ignoring control change; host is us or not sharing"));
  2156. DC_QUIT;
  2157. }
  2158. //
  2159. // UNDO any old state of the controller
  2160. //
  2161. if (pasController)
  2162. {
  2163. if (pasController == m_pasLocal)
  2164. {
  2165. TRACE_OUT(("Ignoring control with us as controller"));
  2166. DC_QUIT;
  2167. }
  2168. else if (pasController->m_caInControlOf)
  2169. {
  2170. ASSERT(!pasController->m_caControlledBy);
  2171. ASSERT(pasController->m_caInControlOf->m_caControlledBy == pasController);
  2172. rc = CAClearHostState(pasController->m_caInControlOf, NULL);
  2173. if (!rc)
  2174. {
  2175. DC_QUIT;
  2176. }
  2177. ASSERT(!pasController->m_caInControlOf);
  2178. }
  2179. else if (pasController->m_caControlledBy)
  2180. {
  2181. ASSERT(!pasController->m_caInControlOf);
  2182. ASSERT(pasController->m_caControlledBy->m_caInControlOf == pasController);
  2183. rc = CAClearHostState(pasController, NULL);
  2184. if (!rc)
  2185. {
  2186. DC_QUIT;
  2187. }
  2188. ASSERT(!pasController->m_caControlledBy);
  2189. }
  2190. }
  2191. //
  2192. // UNDO any old IN CONTROL state of the host
  2193. //
  2194. if (pasHost->m_caInControlOf)
  2195. {
  2196. ASSERT(!pasHost->m_caControlledBy);
  2197. ASSERT(pasHost->m_caInControlOf->m_caControlledBy == pasHost);
  2198. rc = CAClearHostState(pasHost->m_caInControlOf, NULL);
  2199. if (!rc)
  2200. {
  2201. DC_QUIT;
  2202. }
  2203. ASSERT(!pasHost->m_caInControlOf);
  2204. }
  2205. //
  2206. // FINALLY! Update CONTROLLED BY state of the host
  2207. //
  2208. // Clear OLD ControlledBy
  2209. if (pasHost->m_caControlledBy)
  2210. {
  2211. ASSERT(pasHost->m_caControlledBy->m_caInControlOf == pasHost);
  2212. pasHost->m_caControlledBy->m_caInControlOf = NULL;
  2213. }
  2214. // Set NEW ControlledBy
  2215. pasHost->m_caControlledBy = pasController;
  2216. if (pasController)
  2217. {
  2218. pasController->m_caInControlOf = pasHost;
  2219. gccID = pasController->cpcCaps.share.gccID;
  2220. }
  2221. else
  2222. {
  2223. gccID = 0;
  2224. }
  2225. VIEW_HostStateChange(pasHost);
  2226. //
  2227. // The hosts' controller has changed. Repaint the shadow cursor with/wo
  2228. // the new initials.
  2229. //
  2230. CM_UpdateShadowCursor(pasHost, pasHost->cmShadowOff, pasHost->cmPos.x,
  2231. pasHost->cmPos.y, pasHost->cmHotSpot.x, pasHost->cmHotSpot.y);
  2232. rc = TRUE;
  2233. DC_EXIT_POINT:
  2234. DebugExitBOOL(ASShare::CAClearHostState, rc);
  2235. return(rc);
  2236. }
  2237. //
  2238. // 2.X COMPATIBILITY STUFF
  2239. // This is so that we can do a decent job of reflecting old 2.x control
  2240. // stuff, and allow a 3.0 node to take control of a 2.x system.
  2241. //
  2242. //
  2243. // CA2xCooperateChange()
  2244. //
  2245. // This is called when a 2.x node is cooperating or not. When a 2.x node
  2246. // is a host and cooperating, he is "controllable" by 3.0 standards. So
  2247. // when he starts/stops hosting or starts/stops cooperating we must
  2248. // recalculate "AllowControl"
  2249. //
  2250. void ASShare::CA2xCooperateChange
  2251. (
  2252. ASPerson * pasPerson,
  2253. BOOL fCooperating
  2254. )
  2255. {
  2256. BOOL fAllowControl;
  2257. DebugEntry(ASShare::CA2xCooperateChange);
  2258. ValidatePerson(pasPerson);
  2259. //
  2260. // If this isn't a back level system, ignore it.
  2261. //
  2262. if (pasPerson->cpcCaps.general.version >= CAPS_VERSION_30)
  2263. {
  2264. WARNING_OUT(("Received old CA cooperate message from 3.0 node [%d]",
  2265. pasPerson->mcsID));
  2266. DC_QUIT;
  2267. }
  2268. //
  2269. // Update the cooperating state.
  2270. //
  2271. pasPerson->m_ca2xCooperating = fCooperating;
  2272. //
  2273. // If cooperating & this person owns the control token, this person
  2274. // is now in control of all 2.x cooperating nodes. If we were
  2275. // controlling a 2.x host, act like we've been bounced. But we MUST
  2276. // send a packet.
  2277. //
  2278. if (fCooperating)
  2279. {
  2280. if (pasPerson == m_ca2xControlTokenOwner)
  2281. {
  2282. //
  2283. // This person is now "in control" of the 2.x cooperating nodes.
  2284. // If we were in control of a 2.x host, we've basically been
  2285. // bounced and another 2.x node is running the show. With 3.0,
  2286. // it doesn't matter and we don't need to find out what's going
  2287. // on with a 3.0 node in control of 2.x dudes.
  2288. //
  2289. if (m_pasLocal->m_caInControlOf &&
  2290. (m_pasLocal->m_caInControlOf->cpcCaps.general.version < CAPS_VERSION_30))
  2291. {
  2292. CA_ReleaseControl(pasPerson, TRUE);
  2293. }
  2294. }
  2295. }
  2296. //
  2297. // Figure out whether we need to set/clear AllowControl
  2298. //
  2299. fAllowControl = (fCooperating && pasPerson->m_pView);
  2300. if (pasPerson->m_caAllowControl != fAllowControl)
  2301. {
  2302. if (pasPerson->m_pView && !fAllowControl)
  2303. {
  2304. //
  2305. // This 2.x node is hosting, and no longer is cooperating.
  2306. // Cleanup the controller
  2307. //
  2308. if (pasPerson->m_caControlledBy == m_pasLocal)
  2309. {
  2310. CA_ReleaseControl(pasPerson, TRUE);
  2311. }
  2312. else
  2313. {
  2314. CAClearHostState(pasPerson, NULL);
  2315. }
  2316. }
  2317. pasPerson->m_caAllowControl = fAllowControl;
  2318. // This will do nothing if this person isn't hosting.
  2319. VIEW_HostStateChange(pasPerson);
  2320. }
  2321. DC_EXIT_POINT:
  2322. DebugExitVOID(ASShare::CA2xCooperateChange);
  2323. }
  2324. //
  2325. // CA2xRequestControl()
  2326. //
  2327. // Called when a 2.x node requests control.
  2328. //
  2329. void ASShare::CA2xRequestControl
  2330. (
  2331. ASPerson * pasPerson,
  2332. PCAPACKET pCAPacket
  2333. )
  2334. {
  2335. DebugEntry(ASShare::CA2xRequestControl);
  2336. //
  2337. // A 2.x node has sent this. 3.0 hosts never request, they simply
  2338. // grab control.
  2339. //
  2340. ValidatePerson(pasPerson);
  2341. //
  2342. // If it's from a 3.0 node, it's an error.
  2343. //
  2344. if (pasPerson->cpcCaps.general.version >= CAPS_VERSION_30)
  2345. {
  2346. ERROR_OUT(("Received CA_OLDMSG_REQUEST_CONTROL from 3.0 node [%d]",
  2347. pasPerson->mcsID));
  2348. DC_QUIT;
  2349. }
  2350. //
  2351. // If we have the token, grant it. We must release control of a host if
  2352. // that person is 2.x.
  2353. //
  2354. if (m_ca2xControlTokenOwner == m_pasLocal)
  2355. {
  2356. //
  2357. // In this case, we do NOT want a dest ID. This isn't us trying to
  2358. // take control of a 2.x host. It is simply granting control to
  2359. // a 2.x dude.
  2360. //
  2361. if (CA2xQueueSendMsg(0, CA_OLDMSG_GRANTED_CONTROL,
  2362. pasPerson->mcsID, m_ca2xControlGeneration))
  2363. {
  2364. m_ca2xControlTokenOwner = pasPerson;
  2365. // Release control of 2.x host.
  2366. if (m_pasLocal->m_caInControlOf &&
  2367. (m_pasLocal->m_caInControlOf->cpcCaps.general.version < CAPS_VERSION_30))
  2368. {
  2369. CA_ReleaseControl(m_pasLocal->m_caInControlOf, TRUE);
  2370. }
  2371. }
  2372. else
  2373. {
  2374. ERROR_OUT(("CA2xRequestControl: Unable to respond GRANTED to node [%d]",
  2375. pasPerson->mcsID));
  2376. }
  2377. }
  2378. DC_EXIT_POINT:
  2379. DebugExitVOID(ASShare::CA2xRequestControl);
  2380. }
  2381. //
  2382. // CA2xGrantedControl()
  2383. //
  2384. // Called when any node (2.x or 3.0 controlling 2.x) broadcasts granted
  2385. // control. If we are controlling a 2.x host, it is now nuked.
  2386. //
  2387. void ASShare::CA2xGrantedControl
  2388. (
  2389. ASPerson * pasPerson,
  2390. PCAPACKET pCAPacket
  2391. )
  2392. {
  2393. DebugEntry(ASShare::CA2xGrantedControl);
  2394. ValidatePerson(pasPerson);
  2395. if ((pCAPacket->data2 >= m_ca2xControlGeneration) ||
  2396. ((m_ca2xControlGeneration - pCAPacket->data2) > 0x80000000))
  2397. {
  2398. ASPerson * pas2xNewTokenOwner;
  2399. //
  2400. // This dude is now the controller of 2.x nodes. Remember it for
  2401. // later COOPERATE msgs. If nothing has changed (this is a sync
  2402. // broadcast for example, do nothing ourselvs).
  2403. //
  2404. pas2xNewTokenOwner = SC_PersonFromNetID(pCAPacket->data1);
  2405. if (pas2xNewTokenOwner != m_ca2xControlTokenOwner)
  2406. {
  2407. m_ca2xControlTokenOwner = pas2xNewTokenOwner;
  2408. m_ca2xControlGeneration = pCAPacket->data2;
  2409. //
  2410. // Are we in control of a 2.x node? If so, undo it.
  2411. //
  2412. if (m_pasLocal->m_caInControlOf &&
  2413. (m_pasLocal->m_caInControlOf->cpcCaps.general.version < CAPS_VERSION_30))
  2414. {
  2415. CA_ReleaseControl(m_pasLocal->m_caInControlOf, TRUE);
  2416. }
  2417. }
  2418. }
  2419. DebugExitVOID(ASShare::CA2xGrantedControl);
  2420. }
  2421. //
  2422. // CA2xTakeControl()
  2423. //
  2424. // This fakes up packets to take control of a 2.x node. We don't broadcast,
  2425. // we send them privately just to the individual node so we don't control
  2426. // any other host but him.
  2427. //
  2428. // We do this by sending COOPERATE then GRANTED_CONTROL. If there's a
  2429. // collision, we'll see a GRANTED_CONTROL from somebody else that outdates
  2430. // ours.
  2431. //
  2432. void ASShare::CA2xTakeControl(ASPerson * pasHost)
  2433. {
  2434. UINT_PTR caNew2xControlGeneration;
  2435. DebugEntry(ASShare::CA2xTakeControl);
  2436. ValidateView(pasHost);
  2437. caNew2xControlGeneration = m_ca2xControlGeneration + m_pasLocal->mcsID;
  2438. if (CA2xQueueSendMsg(0, CA_OLDMSG_COOPERATE, 0, 0))
  2439. {
  2440. if (!CA2xQueueSendMsg(pasHost->mcsID, CA_OLDMSG_GRANTED_CONTROL,
  2441. m_pasLocal->mcsID, caNew2xControlGeneration))
  2442. {
  2443. //
  2444. // Failure. Best we can do is follow it with a DETACH
  2445. //
  2446. ERROR_OUT(("CA2xTakeControl: Can't take control of [%d]", pasHost->mcsID));
  2447. CA2xQueueSendMsg(0, CA_OLDMSG_DETACH, 0, 0);
  2448. }
  2449. else
  2450. {
  2451. m_ca2xControlGeneration = caNew2xControlGeneration;
  2452. m_ca2xControlTokenOwner = m_pasLocal;
  2453. CANewRequestID();
  2454. CAStartInControl(pasHost, 1);
  2455. }
  2456. }
  2457. else
  2458. {
  2459. ERROR_OUT(("CA2xTakeControl: Can't take control of [%d]", pasHost->mcsID));
  2460. }
  2461. DebugExitVOID(ASShare::CA2xTakeControl);
  2462. }
  2463. //
  2464. // CA2xSendMsg()
  2465. // This sends a 2.x node CA message. It returns FALSE if it can't alloc
  2466. // a packet.
  2467. //
  2468. BOOL ASShare::CA2xSendMsg
  2469. (
  2470. UINT_PTR destID,
  2471. UINT msg,
  2472. UINT_PTR data1,
  2473. UINT_PTR data2
  2474. )
  2475. {
  2476. BOOL fSent = FALSE;
  2477. PCAPACKET pPacket;
  2478. #ifdef _DEBUG
  2479. UINT sentSize;
  2480. #endif // _DEBUG
  2481. DebugEntry(ASShare::CASendPacket);
  2482. //
  2483. // For cooperate/detach, there's no target. We broadcast them no
  2484. // matter what so everybody knows what state we're in.
  2485. //
  2486. if (msg != CA_OLDMSG_GRANTED_CONTROL)
  2487. {
  2488. ASSERT(!destID);
  2489. }
  2490. //
  2491. // WE MUST USE PROT_STR_MISC! Backlevel nodes will uncompress it
  2492. // using that prot dictionary. And note that we must broadcast 2.x
  2493. // CA packets so everybody knows what's going on.
  2494. //
  2495. pPacket = (PCAPACKET)SC_AllocPkt(PROT_STR_MISC, g_s20BroadcastID,
  2496. sizeof(*pPacket));
  2497. if (!pPacket)
  2498. {
  2499. WARNING_OUT(("CA2xSendMsg: can't get packet to send"));
  2500. WARNING_OUT((" msg 0x%08x", msg));
  2501. WARNING_OUT((" data1 0x%08x", data1));
  2502. WARNING_OUT((" data2 0x%08x", data2));
  2503. DC_QUIT;
  2504. }
  2505. pPacket->header.data.dataType = DT_CA;
  2506. pPacket->msg = (TSHR_UINT16)msg;
  2507. pPacket->data1 = (TSHR_UINT16)data1;
  2508. pPacket->data2 = data2;
  2509. #ifdef _DEBUG
  2510. sentSize =
  2511. #endif
  2512. DCS_CompressAndSendPacket(PROT_STR_MISC, g_s20BroadcastID,
  2513. &(pPacket->header), sizeof(*pPacket));
  2514. TRACE_OUT(("CA request packet size: %08d, sent %08d", sizeof(*pPacket), sentSize));
  2515. fSent = TRUE;
  2516. DC_EXIT_POINT:
  2517. DebugExitBOOL(ASShare::CA2xSendMsg, fSent);
  2518. return(fSent);
  2519. }
  2520. //
  2521. // CA2xQueueSendMsg()
  2522. // This sends (or queues if failure) a 2.x node CA message. It has different
  2523. // fields, hence a different routine.
  2524. //
  2525. BOOL ASShare::CA2xQueueSendMsg
  2526. (
  2527. UINT_PTR destID,
  2528. UINT msg,
  2529. UINT_PTR data1,
  2530. UINT_PTR data2
  2531. )
  2532. {
  2533. BOOL rc = TRUE;
  2534. PCAREQUEST pCARequest;
  2535. DebugEntry(ASShare::CA2xQueueSendMsg);
  2536. if (msg != CA_OLDMSG_GRANTED_CONTROL)
  2537. {
  2538. ASSERT(!destID);
  2539. }
  2540. //
  2541. // A DETACH message will cancel out a pending GRANTED_CONTROL message.
  2542. // So look for that first. If we find one (and there can only be at
  2543. // most one), replace it.
  2544. //
  2545. if (msg == CA_OLDMSG_DETACH)
  2546. {
  2547. pCARequest = (PCAREQUEST)COM_BasedListFirst(&m_caQueuedMsgs,
  2548. FIELD_OFFSET(CAREQUEST, chain));
  2549. while (pCARequest)
  2550. {
  2551. if ((pCARequest->type == REQUEST_2X) &&
  2552. (pCARequest->destID == destID) &&
  2553. (pCARequest->msg == CA_OLDMSG_GRANTED_CONTROL))
  2554. {
  2555. // Replace it
  2556. WARNING_OUT(("Replacing cancelled GRANTED_CONTROL msg to 2.x host"));
  2557. pCARequest->destID = 0;
  2558. pCARequest->msg = CA_OLDMSG_DETACH;
  2559. pCARequest->req.req2x.data1 = 0;
  2560. pCARequest->req.req2x.data2 = 0;
  2561. // We're done.
  2562. DC_QUIT;
  2563. }
  2564. pCARequest = (PCAREQUEST)COM_BasedListNext(&m_caQueuedMsgs, pCARequest,
  2565. FIELD_OFFSET(CAREQUEST, chain));
  2566. }
  2567. }
  2568. //
  2569. // The messages must go out in order. So we must flush pending
  2570. // queued messages first.
  2571. //
  2572. if (!CAFlushOutgoingPackets() ||
  2573. !CA2xSendMsg(destID, msg, data1, data2))
  2574. {
  2575. //
  2576. // We must queue this.
  2577. //
  2578. WARNING_OUT(("CA2xQueueSendMsg: queueing request for send later"));
  2579. pCARequest = new CAREQUEST;
  2580. if (!pCARequest)
  2581. {
  2582. ERROR_OUT(("CA2xQueueSendMsg: can't even allocate memory to queue request; must fail"));
  2583. rc = FALSE;
  2584. }
  2585. else
  2586. {
  2587. SET_STAMP(pCARequest, CAREQUEST);
  2588. pCARequest->type = REQUEST_2X;
  2589. pCARequest->destID = destID;
  2590. pCARequest->msg = msg;
  2591. pCARequest->req.req2x.data1 = data1;
  2592. pCARequest->req.req2x.data2 = data2;
  2593. //
  2594. // Stick this at the end of the queue
  2595. //
  2596. COM_BasedListInsertBefore(&(m_caQueuedMsgs),
  2597. &(pCARequest->chain));
  2598. }
  2599. }
  2600. DC_EXIT_POINT:
  2601. DebugExitBOOL(ASShare::CA2xQueueSendMsg, rc);
  2602. return(rc);
  2603. }
  2604. //
  2605. // CAStartQuery()
  2606. //
  2607. // This puts up the modeless dialog to query the user about a control
  2608. // request. It will timeout if not handled.
  2609. //
  2610. BOOL ASShare::CAStartQuery
  2611. (
  2612. ASPerson * pasFrom,
  2613. UINT msg,
  2614. PCA30P pReq
  2615. )
  2616. {
  2617. BOOL rc = FALSE;
  2618. DebugEntry(ASShare::CAStartQuery);
  2619. ValidatePerson(pasFrom);
  2620. //
  2621. // We have no stacked queries. If another comes in while the current
  2622. // one is up, it gets an immediate failure busy.
  2623. //
  2624. ASSERT(!m_caQueryDlg);
  2625. ASSERT(!m_caQuery.pasReplyTo);
  2626. ASSERT(!m_caQuery.msg);
  2627. //
  2628. // Setup for new query
  2629. //
  2630. if (msg == CA_PREFER_PASSCONTROL)
  2631. {
  2632. //
  2633. // With forwarding, the person we're going to send a packet to
  2634. // if accepted is not the person who sent us the request. It's the
  2635. // person we're forwarding to.
  2636. //
  2637. m_caQuery.pasReplyTo = SC_PersonFromNetID(pReq->ppc.mcsPassTo);
  2638. ValidatePerson(m_caQuery.pasReplyTo);
  2639. }
  2640. else
  2641. {
  2642. m_caQuery.pasReplyTo = pasFrom;
  2643. }
  2644. m_caQuery.mcsOrg = pasFrom->mcsID;
  2645. m_caQuery.msg = msg;
  2646. m_caQuery.request = *pReq;
  2647. //
  2648. // If we are unattended, or the requester is unattended, instantly
  2649. // confirm. That's why we show the window after creating the dialog.
  2650. //
  2651. if ((m_pasLocal->cpcCaps.general.typeFlags & AS_UNATTENDED) ||
  2652. (pasFrom->cpcCaps.general.typeFlags & AS_UNATTENDED))
  2653. {
  2654. CAFinishQuery(CARESULT_CONFIRMED);
  2655. rc = TRUE;
  2656. }
  2657. else
  2658. {
  2659. //
  2660. // If this is a request to us && we're hosting, check auto-accept/
  2661. // auto-reject settings.
  2662. //
  2663. if (m_pHost &&
  2664. ((msg == CA_REQUEST_TAKECONTROL) || (msg == CA_PREFER_PASSCONTROL)))
  2665. {
  2666. if (m_pHost->m_caTempRejectRequests)
  2667. {
  2668. CAFinishQuery(CARESULT_DENIED_BUSY);
  2669. rc = TRUE;
  2670. DC_QUIT;
  2671. }
  2672. else if (m_pHost->m_caAutoAcceptRequests)
  2673. {
  2674. CAFinishQuery(CARESULT_CONFIRMED);
  2675. rc = TRUE;
  2676. DC_QUIT;
  2677. }
  2678. }
  2679. m_caQueryDlg = CreateDialogParam(g_asInstance,
  2680. MAKEINTRESOURCE(IDD_QUERY), NULL, CAQueryDlgProc, 0);
  2681. if (!m_caQueryDlg)
  2682. {
  2683. ERROR_OUT(("Failed to create query message box from [%d]",
  2684. pasFrom->mcsID));
  2685. m_caQuery.pasReplyTo = NULL;
  2686. m_caQuery.mcsOrg = 0;
  2687. m_caQuery.msg = 0;
  2688. }
  2689. else
  2690. {
  2691. // Success
  2692. rc = TRUE;
  2693. }
  2694. }
  2695. DC_EXIT_POINT:
  2696. DebugExitBOOL(ASShare::CAStartQuery, rc);
  2697. return(rc);
  2698. }
  2699. //
  2700. // CAFinishQuery()
  2701. //
  2702. // Called to finish the query we started, either because of UI or because
  2703. // we or the remote are unattended.
  2704. //
  2705. void ASShare::CAFinishQuery(UINT result)
  2706. {
  2707. CA30PENDING request;
  2708. DebugEntry(ASShare::CAFinishQuery);
  2709. ValidatePerson(m_caQuery.pasReplyTo);
  2710. // Make a copy of our request
  2711. request = m_caQuery;
  2712. //
  2713. // If we have a dialog up, destroy it NOW. Completing the request
  2714. // may cause us to be controlled or whatever. So get the dialog
  2715. // out of the way immediately.
  2716. //
  2717. // Note that destroying ourself will clear the request vars, hence the
  2718. // copy above.
  2719. //
  2720. if (m_caQueryDlg)
  2721. {
  2722. DestroyWindow(m_caQueryDlg);
  2723. }
  2724. else
  2725. {
  2726. m_caQuery.pasReplyTo = NULL;
  2727. m_caQuery.mcsOrg = 0;
  2728. m_caQuery.msg = 0;
  2729. }
  2730. switch (request.msg)
  2731. {
  2732. case CA_REQUEST_TAKECONTROL:
  2733. {
  2734. CACompleteRequestTakeControl(request.pasReplyTo,
  2735. &request.request.rtc, result);
  2736. break;
  2737. }
  2738. case CA_REQUEST_GIVECONTROL:
  2739. {
  2740. CACompleteRequestGiveControl(request.pasReplyTo,
  2741. &request.request.rgc, result);
  2742. break;
  2743. }
  2744. case CA_PREFER_PASSCONTROL:
  2745. {
  2746. CACompletePreferPassControl(request.pasReplyTo,
  2747. request.mcsOrg, &request.request.ppc, result);
  2748. break;
  2749. }
  2750. default:
  2751. {
  2752. ERROR_OUT(("Unrecognized query msg %d", request.msg));
  2753. break;
  2754. }
  2755. }
  2756. DebugExitVOID(ASShare::CAFinishQuery);
  2757. }
  2758. //
  2759. // CA_QueryDlgProc()
  2760. //
  2761. // Handles querying user dialog
  2762. //
  2763. INT_PTR CALLBACK CAQueryDlgProc
  2764. (
  2765. HWND hwnd,
  2766. UINT message,
  2767. WPARAM wParam,
  2768. LPARAM lParam
  2769. )
  2770. {
  2771. return(g_asSession.pShare->CA_QueryDlgProc(hwnd, message, wParam, lParam));
  2772. }
  2773. BOOL ASShare::CA_QueryDlgProc
  2774. (
  2775. HWND hwnd,
  2776. UINT message,
  2777. WPARAM wParam,
  2778. LPARAM lParam
  2779. )
  2780. {
  2781. BOOL rc = TRUE;
  2782. DebugEntry(CA_QueryDlgProc);
  2783. switch (message)
  2784. {
  2785. case WM_INITDIALOG:
  2786. {
  2787. char szT[256];
  2788. char szRes[512];
  2789. char szShared[64];
  2790. UINT idsTitle;
  2791. ASPerson * pasT;
  2792. HDC hdc;
  2793. HFONT hfn;
  2794. RECT rcTxt;
  2795. RECT rcOwner;
  2796. ValidatePerson(m_caQuery.pasReplyTo);
  2797. pasT = NULL;
  2798. // Set title.
  2799. ASSERT(m_caQuery.msg);
  2800. switch (m_caQuery.msg)
  2801. {
  2802. case CA_REQUEST_TAKECONTROL:
  2803. {
  2804. idsTitle = IDS_TITLE_QUERY_TAKECONTROL;
  2805. if (m_pasLocal->hetCount == HET_DESKTOPSHARED)
  2806. LoadString(g_asInstance, IDS_DESKTOP_LOWER, szShared, sizeof(szShared));
  2807. else
  2808. LoadString(g_asInstance, IDS_PROGRAMS_LOWER, szShared, sizeof(szShared));
  2809. LoadString(g_asInstance, IDS_MSG_QUERY_TAKECONTROL, szT, sizeof(szT));
  2810. wsprintf(szRes, szT, m_caQuery.pasReplyTo->scName, szShared);
  2811. break;
  2812. }
  2813. case CA_REQUEST_GIVECONTROL:
  2814. {
  2815. if (m_caQuery.pasReplyTo->hetCount == HET_DESKTOPSHARED)
  2816. LoadString(g_asInstance, IDS_DESKTOP_LOWER, szShared, sizeof(szShared));
  2817. else
  2818. LoadString(g_asInstance, IDS_PROGRAMS_LOWER, szShared, sizeof(szShared));
  2819. if (m_caQuery.request.rgc.mcsPassFrom)
  2820. {
  2821. pasT = SC_PersonFromNetID(m_caQuery.request.rgc.mcsPassFrom);
  2822. }
  2823. if (pasT)
  2824. {
  2825. idsTitle = IDS_TITLE_QUERY_YIELDCONTROL;
  2826. LoadString(g_asInstance, IDS_MSG_QUERY_YIELDCONTROL,
  2827. szT, sizeof(szT));
  2828. wsprintf(szRes, szT, pasT->scName, m_caQuery.pasReplyTo->scName, szShared);
  2829. }
  2830. else
  2831. {
  2832. idsTitle = IDS_TITLE_QUERY_GIVECONTROL;
  2833. LoadString(g_asInstance, IDS_MSG_QUERY_GIVECONTROL,
  2834. szT, sizeof(szT));
  2835. wsprintf(szRes, szT, m_caQuery.pasReplyTo->scName, szShared);
  2836. }
  2837. break;
  2838. }
  2839. case CA_PREFER_PASSCONTROL:
  2840. {
  2841. pasT = SC_PersonFromNetID(m_caQuery.mcsOrg);
  2842. ValidatePerson(pasT);
  2843. idsTitle = IDS_TITLE_QUERY_FORWARDCONTROL;
  2844. if (m_pasLocal->hetCount == HET_DESKTOPSHARED)
  2845. LoadString(g_asInstance, IDS_DESKTOP_LOWER, szShared, sizeof(szShared));
  2846. else
  2847. LoadString(g_asInstance, IDS_PROGRAMS_LOWER, szShared, sizeof(szShared));
  2848. LoadString(g_asInstance, IDS_MSG_QUERY_FORWARDCONTROL, szT, sizeof(szT));
  2849. wsprintf(szRes, szT, pasT->scName, szShared, m_caQuery.pasReplyTo->scName);
  2850. break;
  2851. }
  2852. default:
  2853. {
  2854. ERROR_OUT(("Bogus m_caQuery.msg %d", m_caQuery.msg));
  2855. rc = FALSE;
  2856. break;
  2857. }
  2858. }
  2859. if(FALSE == rc)
  2860. {
  2861. break;
  2862. }
  2863. LoadString(g_asInstance, idsTitle, szT, sizeof(szT));
  2864. SetWindowText(hwnd, szT);
  2865. // Set message.
  2866. SetDlgItemText(hwnd, CTRL_QUERY, szRes);
  2867. // Center the message vertically
  2868. GetWindowRect(GetDlgItem(hwnd, CTRL_QUERY), &rcOwner);
  2869. MapWindowPoints(NULL, hwnd, (LPPOINT)&rcOwner, 2);
  2870. rcTxt = rcOwner;
  2871. hdc = GetDC(hwnd);
  2872. hfn = (HFONT)SendDlgItemMessage(hwnd, CTRL_QUERY, WM_GETFONT, 0, 0);
  2873. hfn = SelectFont(hdc, hfn);
  2874. DrawText(hdc, szRes, -1, &rcTxt, DT_NOCLIP | DT_EXPANDTABS |
  2875. DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT);
  2876. SelectFont(hdc, hfn);
  2877. ReleaseDC(hwnd, hdc);
  2878. ASSERT((rcTxt.bottom - rcTxt.top) <= (rcOwner.bottom - rcOwner.top));
  2879. SetWindowPos(GetDlgItem(hwnd, CTRL_QUERY), NULL,
  2880. rcOwner.left,
  2881. ((rcOwner.top + rcOwner.bottom) - (rcTxt.bottom - rcTxt.top)) / 2,
  2882. (rcOwner.right - rcOwner.left),
  2883. rcTxt.bottom - rcTxt.top,
  2884. SWP_NOACTIVATE | SWP_NOZORDER);
  2885. SetTimer(hwnd, IDT_CAQUERY, PERIOD_CAQUERY, 0);
  2886. //
  2887. // Show window, the user will handle
  2888. //
  2889. ShowWindow(hwnd, SW_SHOWNORMAL);
  2890. SetForegroundWindow(hwnd);
  2891. UpdateWindow(hwnd);
  2892. break;
  2893. }
  2894. case WM_COMMAND:
  2895. {
  2896. switch (GET_WM_COMMAND_ID(wParam, lParam))
  2897. {
  2898. case IDOK:
  2899. {
  2900. CAFinishQuery(CARESULT_CONFIRMED);
  2901. break;
  2902. }
  2903. case IDCANCEL:
  2904. {
  2905. CAFinishQuery(CARESULT_DENIED_USER);
  2906. break;
  2907. }
  2908. }
  2909. break;
  2910. }
  2911. case WM_TIMER:
  2912. {
  2913. if (wParam != IDT_CAQUERY)
  2914. {
  2915. rc = FALSE;
  2916. }
  2917. else
  2918. {
  2919. KillTimer(hwnd, IDT_CAQUERY);
  2920. // Timed out failure.
  2921. CAFinishQuery(CARESULT_DENIED_TIMEDOUT);
  2922. }
  2923. break;
  2924. }
  2925. case WM_DESTROY:
  2926. {
  2927. //
  2928. // Clear pending info
  2929. //
  2930. m_caQueryDlg = NULL;
  2931. m_caQuery.pasReplyTo = NULL;
  2932. m_caQuery.mcsOrg = 0;
  2933. m_caQuery.msg = 0;
  2934. break;
  2935. }
  2936. default:
  2937. {
  2938. rc = FALSE;
  2939. break;
  2940. }
  2941. }
  2942. DebugExitBOOL(CA_QueryDlgProc, rc);
  2943. return(rc);
  2944. }
  2945. //
  2946. // CACancelQuery()
  2947. //
  2948. // If a dialog is up for a take control request, it hasn't been handled yet,
  2949. // and we get a cancel notification from the viewer, we need to take the
  2950. // dialog down WITHOUT generating a response packet.
  2951. //
  2952. void ASShare::CACancelQuery
  2953. (
  2954. ASPerson * pasFrom,
  2955. BOOL fPacket
  2956. )
  2957. {
  2958. DebugEntry(ASShare::CACancelQuery);
  2959. ASSERT(m_caQueryDlg);
  2960. ASSERT(m_caQuery.pasReplyTo == pasFrom);
  2961. if (fPacket)
  2962. {
  2963. // This will send a packet then destroy the dialog
  2964. CAFinishQuery(CARESULT_DENIED);
  2965. }
  2966. else
  2967. {
  2968. // Destroy the dialog
  2969. DestroyWindow(m_caQueryDlg);
  2970. }
  2971. ASSERT(!m_caQueryDlg);
  2972. ASSERT(!m_caQuery.pasReplyTo);
  2973. ASSERT(!m_caQuery.msg);
  2974. DebugExitVOID(ASShare::CACancelQuery);
  2975. }
  2976.