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

1454 lines
35 KiB

  1. #include "precomp.h"
  2. //
  3. // HOST.CPP
  4. // Hosting, local and remote
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. #define MLZ_FILE_ZONE ZONE_CORE
  9. //
  10. // HET_Init()
  11. //
  12. // Initialization for hosting
  13. // * window tracking
  14. // * capabilities
  15. // * host UI
  16. //
  17. BOOL HET_Init(void)
  18. {
  19. BOOL rc = FALSE;
  20. int property;
  21. UINT i;
  22. LOGFONT lf;
  23. DebugEntry(HET_Init);
  24. //
  25. // Initialize T.128 capabilities, whether we can host or not.
  26. //
  27. ZeroMemory(&g_cpcLocalCaps, sizeof(g_cpcLocalCaps));
  28. g_cpcLocalCaps.header.numCapabilities = PROTCAPS_COUNT;
  29. // PROTCAPS_GENERAL
  30. // Check for compression setting (useful to debug protocol)
  31. // You can set CT_PKZIP (1) or none (0) instead of persistent PKZIP,
  32. // which is the default.
  33. //
  34. g_cpcLocalCaps.general.header.capID = CAPS_ID_GENERAL;
  35. g_cpcLocalCaps.general.header.capSize = sizeof(g_cpcLocalCaps.general);
  36. COM_ReadProfInt(DBG_INI_SECTION_NAME, GDC_INI_COMPRESSION,
  37. GCT_DEFAULT, &property);
  38. g_cpcLocalCaps.general.OS = CAPS_WINDOWS;
  39. g_cpcLocalCaps.general.OSVersion = (g_asWin95 ? CAPS_WINDOWS_95 : CAPS_WINDOWS_NT);
  40. g_cpcLocalCaps.general.typeFlags = 0;
  41. if (g_asOptions & AS_SERVICE)
  42. {
  43. g_cpcLocalCaps.general.typeFlags |= AS_SERVICE;
  44. }
  45. if (g_asOptions & AS_UNATTENDED)
  46. {
  47. g_cpcLocalCaps.general.typeFlags |= AS_UNATTENDED;
  48. }
  49. g_cpcLocalCaps.general.version = CAPS_VERSION_CURRENT;
  50. //
  51. // PROTCAPS_SCREEN
  52. //
  53. g_cpcLocalCaps.screen.header.capID = CAPS_ID_SCREEN;
  54. g_cpcLocalCaps.screen.header.capSize = sizeof(g_cpcLocalCaps.screen);
  55. g_cpcLocalCaps.screen.capsSupports1BPP = CAPS_UNSUPPORTED;
  56. g_cpcLocalCaps.screen.capsSupports4BPP = CAPS_SUPPORTED;
  57. g_cpcLocalCaps.screen.capsSupports8BPP = CAPS_SUPPORTED;
  58. g_cpcLocalCaps.screen.capsSupports24BPP = CAPS_SUPPORTED;
  59. g_cpcLocalCaps.screen.capsScreenWidth = (TSHR_UINT16)GetSystemMetrics(SM_CXSCREEN);
  60. g_cpcLocalCaps.screen.capsScreenHeight = (TSHR_UINT16)GetSystemMetrics(SM_CYSCREEN);
  61. g_cpcLocalCaps.screen.capsSupportsDesktopResize = CAPS_SUPPORTED;
  62. //
  63. // Set up the V1 and/or V2 Bitmap Compression capabilities. For the
  64. // V2.0 protocol, both are supported by default (supporting V1
  65. // compression allows for negotiation down to V1 protocol systems), but
  66. // can be overidden in the INI file.
  67. //
  68. g_cpcLocalCaps.screen.capsBPP = (TSHR_UINT16)g_usrScreenBPP;
  69. // PROTCAPS_SC
  70. g_cpcLocalCaps.share.header.capID = CAPS_ID_SC;
  71. g_cpcLocalCaps.share.header.capSize = sizeof(g_cpcLocalCaps.share);
  72. g_cpcLocalCaps.share.gccID = 0;
  73. // PROTCAPS_CM
  74. g_cpcLocalCaps.cursor.header.capID = CAPS_ID_CM;
  75. g_cpcLocalCaps.cursor.header.capSize = sizeof(g_cpcLocalCaps.cursor);
  76. g_cpcLocalCaps.cursor.capsSupportsColorCursors = CAPS_SUPPORTED;
  77. g_cpcLocalCaps.cursor.capsCursorCacheSize = TSHR_CM_CACHE_ENTRIES;
  78. // PROTCAPS_PM
  79. g_cpcLocalCaps.palette.header.capID = CAPS_ID_PM;
  80. g_cpcLocalCaps.palette.header.capSize = sizeof(g_cpcLocalCaps.palette);
  81. g_cpcLocalCaps.palette.capsColorTableCacheSize = TSHR_PM_CACHE_ENTRIES;
  82. //
  83. // PROTCAPS_BITMAPCACHE
  84. //
  85. g_cpcLocalCaps.bitmaps.header.capID = CAPS_ID_BITMAPCACHE;
  86. g_cpcLocalCaps.bitmaps.header.capSize = sizeof(g_cpcLocalCaps.bitmaps);
  87. //
  88. // SEND BITMAP CACHE
  89. //
  90. // The cache is now more in line with what the display driver is doing.
  91. // The memory size for medium/large is the same. But large bitmaps are
  92. // 4x bigger, so there are 1/4 as many. The # of small bitmaps is the
  93. // same as the # of medium bitmaps. Since small bitmaps are 1/4 the
  94. // size, only 1/4 as much memory is used.
  95. //
  96. if (g_sbcEnabled)
  97. {
  98. UINT maxSendBPP;
  99. ASSERT(g_asbcShuntBuffers[SBC_MEDIUM_TILE_INDEX]);
  100. ASSERT(g_asbcShuntBuffers[SBC_LARGE_TILE_INDEX]);
  101. g_cpcLocalCaps.bitmaps.sender.capsSmallCacheNumEntries =
  102. (TSHR_UINT16)g_asbcShuntBuffers[SBC_MEDIUM_TILE_INDEX]->numEntries;
  103. g_cpcLocalCaps.bitmaps.sender.capsMediumCacheNumEntries =
  104. (TSHR_UINT16)g_asbcShuntBuffers[SBC_MEDIUM_TILE_INDEX]->numEntries;
  105. g_cpcLocalCaps.bitmaps.sender.capsLargeCacheNumEntries =
  106. (TSHR_UINT16)g_asbcShuntBuffers[SBC_LARGE_TILE_INDEX]->numEntries;
  107. if (g_usrScreenBPP >= 24)
  108. {
  109. maxSendBPP = 24;
  110. }
  111. else
  112. {
  113. maxSendBPP = 8;
  114. }
  115. g_cpcLocalCaps.bitmaps.sender.capsSmallCacheCellSize =
  116. MP_CACHE_CELLSIZE(MP_SMALL_TILE_WIDTH, MP_SMALL_TILE_WIDTH,
  117. maxSendBPP);
  118. g_cpcLocalCaps.bitmaps.sender.capsMediumCacheCellSize =
  119. MP_CACHE_CELLSIZE(MP_MEDIUM_TILE_WIDTH, MP_MEDIUM_TILE_HEIGHT,
  120. maxSendBPP);
  121. g_cpcLocalCaps.bitmaps.sender.capsLargeCacheCellSize =
  122. MP_CACHE_CELLSIZE(MP_LARGE_TILE_WIDTH, MP_LARGE_TILE_HEIGHT,
  123. maxSendBPP);
  124. }
  125. else
  126. {
  127. //
  128. // We can't use sizes of zero, 2.x nodes will fail if we do. But
  129. // we can use a tiny number so they don't allocate huge hunks of
  130. // memory for no reason. And 3.0 will treat '1' like '0'.
  131. //
  132. g_cpcLocalCaps.bitmaps.sender.capsSmallCacheNumEntries = 1;
  133. g_cpcLocalCaps.bitmaps.sender.capsSmallCacheCellSize = 1;
  134. g_cpcLocalCaps.bitmaps.sender.capsMediumCacheNumEntries = 1;
  135. g_cpcLocalCaps.bitmaps.sender.capsMediumCacheCellSize = 1;
  136. g_cpcLocalCaps.bitmaps.sender.capsLargeCacheNumEntries = 1;
  137. g_cpcLocalCaps.bitmaps.sender.capsLargeCacheCellSize = 1;
  138. }
  139. TRACE_OUT(("SBC small cache: %d entries, size %d",
  140. g_cpcLocalCaps.bitmaps.sender.capsSmallCacheNumEntries,
  141. g_cpcLocalCaps.bitmaps.sender.capsSmallCacheCellSize));
  142. TRACE_OUT(("SBC medium cache: %d entries, size %d",
  143. g_cpcLocalCaps.bitmaps.sender.capsMediumCacheNumEntries,
  144. g_cpcLocalCaps.bitmaps.sender.capsMediumCacheCellSize));
  145. TRACE_OUT(("SBC large cache: %d entries, size %d",
  146. g_cpcLocalCaps.bitmaps.sender.capsLargeCacheNumEntries,
  147. g_cpcLocalCaps.bitmaps.sender.capsLargeCacheCellSize));
  148. //
  149. // PROTCAPS_ORDERS
  150. //
  151. g_cpcLocalCaps.orders.header.capID = CAPS_ID_ORDERS;
  152. g_cpcLocalCaps.orders.header.capSize = sizeof(g_cpcLocalCaps.orders);
  153. //
  154. // Fill in the SaveBitmap capabilities.
  155. //
  156. g_cpcLocalCaps.orders.capsSaveBitmapSize = TSHR_SSI_BITMAP_SIZE;
  157. g_cpcLocalCaps.orders.capsSaveBitmapXGranularity = TSHR_SSI_BITMAP_X_GRANULARITY;
  158. g_cpcLocalCaps.orders.capsSaveBitmapYGranularity = TSHR_SSI_BITMAP_Y_GRANULARITY;
  159. //
  160. // We support
  161. // * R20 Signatures (cell heights, better matching)
  162. // * Aspect matching
  163. // * Charset/code page matching
  164. // * Baseline text orders
  165. // * Em Heights
  166. // * DeltaX arrays for simulation if font not on remote
  167. //
  168. //
  169. // BOGUS LAURABU BUGBUG
  170. //
  171. // Baseline text orders not yet supported in Win95. But that's OK,
  172. // we don't mark any orders we generate on that platform with
  173. // NF_BASELINE, so they aren't treated as such.
  174. //
  175. g_cpcLocalCaps.orders.capsfFonts = CAPS_FONT_R20_SIGNATURE |
  176. CAPS_FONT_ASPECT |
  177. CAPS_FONT_CODEPAGE |
  178. CAPS_FONT_ALLOW_BASELINE |
  179. CAPS_FONT_EM_HEIGHT |
  180. CAPS_FONT_OLD_NEED_X |
  181. CAPS_FONT_NEED_X_SOMETIMES;
  182. //
  183. // Fill in which orders we support.
  184. //
  185. for (i = 0; i < ORD_NUM_LEVEL_1_ORDERS; i++)
  186. {
  187. //
  188. // Order indices for desktop-scrolling and memblt variants are not
  189. // to be negotiated by this mechanism... these currently consume
  190. // 3 order indices which must be excluded from this negotiation.
  191. //
  192. if ( (i == ORD_RESERVED_INDEX ) ||
  193. (i == ORD_MEMBLT_R2_INDEX ) ||
  194. (i == ORD_UNUSED_INDEX ) ||
  195. (i == ORD_MEM3BLT_R2_INDEX) )
  196. {
  197. continue;
  198. }
  199. g_cpcLocalCaps.orders.capsOrders[i] = ORD_LEVEL_1_ORDERS;
  200. }
  201. g_cpcLocalCaps.orders.capsMaxOrderlevel = ORD_LEVEL_1_ORDERS;
  202. //
  203. // Fill in encoding capabilities
  204. //
  205. //
  206. // Keep the "encoding disabled" option, it's handy for using our
  207. // protocol analyzer
  208. //
  209. COM_ReadProfInt(DBG_INI_SECTION_NAME, OE2_INI_2NDORDERENCODING,
  210. CAPS_ENCODING_DEFAULT, &property);
  211. g_cpcLocalCaps.orders.capsEncodingLevel = (TSHR_UINT16)property;
  212. //
  213. // Get the app and desktop icons, big and small
  214. //
  215. g_hetASIcon = LoadIcon(g_asInstance, MAKEINTRESOURCE(IDI_SHAREICON));
  216. if (!g_hetASIcon)
  217. {
  218. ERROR_OUT(("HET_Init: Failed to load app icon"));
  219. DC_QUIT;
  220. }
  221. g_hetDeskIcon = LoadIcon(g_asInstance, MAKEINTRESOURCE(IDI_DESKTOPICON));
  222. if (!g_hetDeskIcon)
  223. {
  224. ERROR_OUT(("HET_Init: failed to load desktop icon"));
  225. DC_QUIT;
  226. }
  227. // Get the small icon, created, that we paint on the window bar items
  228. g_hetASIconSmall = (HICON)LoadImage(g_asInstance, MAKEINTRESOURCE(IDI_SHAREICON),
  229. IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
  230. LR_DEFAULTCOLOR);
  231. if (!g_hetASIconSmall)
  232. {
  233. ERROR_OUT(("HET_Init: Failed to load app small icon"));
  234. DC_QUIT;
  235. }
  236. g_hetDeskIconSmall = (HICON)LoadImage(g_asInstance, MAKEINTRESOURCE(IDI_DESKTOPICON),
  237. IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
  238. LR_DEFAULTCOLOR);
  239. if (!g_hetDeskIconSmall)
  240. {
  241. ERROR_OUT(("HET_Init: Failed to load desktop small icon"));
  242. DC_QUIT;
  243. }
  244. //
  245. // Get the checkmark image
  246. //
  247. g_hetCheckBitmap = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_CHECK));
  248. if (!g_hetCheckBitmap)
  249. {
  250. ERROR_OUT(("HET_Init: Failed to load checkmark bitmap"));
  251. DC_QUIT;
  252. }
  253. //
  254. // Create a bolded font for shared items in the host list
  255. //
  256. GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
  257. lf.lfWeight += FW_LIGHT;
  258. g_hetSharedFont = CreateFontIndirect(&lf);
  259. if (!g_hetSharedFont)
  260. {
  261. ERROR_OUT(("HET_Init: Failed to create shared item font"));
  262. DC_QUIT;
  263. }
  264. rc = TRUE;
  265. DC_EXIT_POINT:
  266. DebugExitBOOL(HET_Init, rc);
  267. return(rc);
  268. }
  269. //
  270. // HET_Term()
  271. //
  272. // Cleanup hosting objects
  273. //
  274. void HET_Term(void)
  275. {
  276. DebugEntry(HET_Term);
  277. if (g_hetSharedFont != NULL)
  278. {
  279. DeleteFont(g_hetSharedFont);
  280. g_hetSharedFont = NULL;
  281. }
  282. if (g_hetCheckBitmap != NULL)
  283. {
  284. DeleteBitmap(g_hetCheckBitmap);
  285. g_hetCheckBitmap = NULL;
  286. }
  287. if (g_hetDeskIconSmall != NULL)
  288. {
  289. DestroyIcon(g_hetDeskIconSmall);
  290. g_hetDeskIconSmall = NULL;
  291. }
  292. if (g_hetDeskIcon != NULL)
  293. {
  294. DestroyIcon(g_hetDeskIcon);
  295. g_hetDeskIcon = NULL;
  296. }
  297. if (g_hetASIconSmall != NULL)
  298. {
  299. DestroyIcon(g_hetASIconSmall);
  300. g_hetASIconSmall = NULL;
  301. }
  302. if (g_hetASIcon != NULL)
  303. {
  304. DestroyIcon(g_hetASIcon);
  305. g_hetASIcon = NULL;
  306. }
  307. DebugExitVOID(HET_Term);
  308. }
  309. //
  310. // HET_ShareDesktop()
  311. //
  312. void ASShare::HET_ShareDesktop(void)
  313. {
  314. ASPerson * pasT;
  315. DebugEntry(ASShare:HET_ShareDesktop);
  316. //
  317. // If we're sharing apps, ignore this.
  318. //
  319. if (m_pasLocal->hetCount != 0)
  320. {
  321. WARNING_OUT(("Ignoring share desktop request, sharing apps"));
  322. DC_QUIT;
  323. }
  324. TRACE_OUT(("HET_ShareDesktop: starting share"));
  325. if (!HETStartHosting(TRUE))
  326. {
  327. ERROR_OUT(("HET_ShareDesktop cannot start sharing desktop"));
  328. DC_QUIT;
  329. }
  330. //
  331. // Update the count of hosted entities (ie user-hosted windows)
  332. //
  333. HETUpdateLocalCount(HET_DESKTOPSHARED);
  334. //
  335. // Get the desktop(s) repainted if anybody's viewing it.
  336. //
  337. ASSERT(m_pHost);
  338. m_pHost->HET_RepaintAll();
  339. DC_EXIT_POINT:
  340. DebugExitVOID(ASShare::HET_ShareDesktop);
  341. }
  342. //
  343. // HET_UnshareAll()
  344. // Unshares everything including the desktop. If we had been sharing
  345. // apps before, we will unshare them all.
  346. //
  347. void ASShare::HET_UnshareAll(void)
  348. {
  349. DebugEntry(ASShare::HET_UnshareAll);
  350. if (m_pasLocal->hetCount != 0)
  351. {
  352. HETUpdateLocalCount(0);
  353. }
  354. DebugExitVOID(ASShare::HET_UnshareAll);
  355. }
  356. //
  357. // HET_PartyJoiningShare()
  358. //
  359. BOOL ASShare::HET_PartyJoiningShare(ASPerson * pasPerson)
  360. {
  361. BOOL rc = TRUE;
  362. DebugEntry(ASShare::HET_PartyJoiningShare);
  363. HET_CalcViewers(NULL);
  364. DebugExitBOOL(ASShare::HET_PartyJoiningShare, rc);
  365. return(rc);
  366. }
  367. //
  368. // HET_PartyLeftShare()
  369. //
  370. void ASShare::HET_PartyLeftShare(ASPerson * pasPerson)
  371. {
  372. DebugEntry(ASShare::HET_PartyLeftShare);
  373. // This guy is leaving the share, cleanup if he was sharing.
  374. ValidatePerson(pasPerson);
  375. if (pasPerson->hetCount != 0)
  376. {
  377. // This person is hosting
  378. if (pasPerson == m_pasLocal)
  379. {
  380. HETUpdateLocalCount(0);
  381. }
  382. else
  383. {
  384. HETUpdateRemoteCount(pasPerson, 0);
  385. }
  386. }
  387. //
  388. // If we're hosting, stop viewing if this is the last person in the share.
  389. //
  390. HET_CalcViewers(pasPerson);
  391. DebugExitVOID(ASShare::HET_PartyLeftShare);
  392. }
  393. //
  394. // HET_CalcViewers()
  395. //
  396. // If we or a remote is viewing our shared stuff, then we must accumulate
  397. // graphic output. If not, don't other, but keep the app tracked as necessary.
  398. //
  399. // This is called when we start to host, when somebody joins, or somebody
  400. // leaves the conference.
  401. //
  402. void ASShare::HET_CalcViewers(ASPerson * pasLeaving)
  403. {
  404. BOOL fViewers;
  405. DebugEntry(ASShare::HET_CalcViewers);
  406. fViewers = FALSE;
  407. if (m_pHost)
  408. {
  409. if (m_scfViewSelf)
  410. {
  411. fViewers = TRUE;
  412. }
  413. else if (!pasLeaving)
  414. {
  415. //
  416. // Nobody is leaving, so just check if anybody else is in the
  417. // share.
  418. //
  419. if (m_pasLocal->pasNext)
  420. {
  421. fViewers = TRUE;
  422. }
  423. }
  424. else if (pasLeaving->pasNext || (m_pasLocal->pasNext != pasLeaving))
  425. {
  426. //
  427. // Sombody is leaving.
  428. // The person leaving isn't the only other one besides us in the
  429. // share, since there are others after it or before it in the
  430. // members linked list.
  431. //
  432. fViewers = TRUE;
  433. }
  434. }
  435. if (fViewers != m_hetViewers)
  436. {
  437. HET_VIEWER viewer;
  438. m_hetViewers = fViewers;
  439. viewer.viewersPresent = fViewers;
  440. OSI_FunctionRequest(HET_ESC_VIEWER, (LPOSI_ESCAPE_HEADER)&viewer,
  441. sizeof(viewer));
  442. }
  443. DebugExitVOID(ASShare::HET_CalcViewers);
  444. }
  445. //
  446. // HET_ReceivedPacket()
  447. //
  448. void ASShare::HET_ReceivedPacket
  449. (
  450. ASPerson * pasPerson,
  451. PS20DATAPACKET pPacket
  452. )
  453. {
  454. PHETPACKET pHETPacket;
  455. DebugEntry(ASShare:;HET_ReceivedPacket);
  456. ValidatePerson(pasPerson);
  457. pHETPacket = (PHETPACKET)pPacket;
  458. switch (pHETPacket->msg)
  459. {
  460. case HET_MSG_NUMHOSTED:
  461. HETUpdateRemoteCount(pasPerson, pHETPacket->hostState);
  462. break;
  463. default:
  464. ERROR_OUT(("Unknown HET packet type %u from [%d]", pHETPacket->msg,
  465. pasPerson->mcsID));
  466. break;
  467. }
  468. DebugExitVOID(ASShare::HET_ReceivedPacket);
  469. }
  470. //
  471. // HET_SyncCommon()
  472. //
  473. // Called when somebody joins a share, after it is fully joined. We repaint
  474. // all shared windows and send the current hosted top-level count.
  475. //
  476. // Also called when sharing, and somebody joins later.
  477. //
  478. // NOTE that some of the resets don't do anything when are just starting to
  479. // share. But all are quick and benign.
  480. //
  481. void ASHost::HET_SyncCommon(void)
  482. {
  483. OSI_ESCAPE_HEADER osi;
  484. DebugEntry(ASHost::HET_SyncCommon);
  485. m_upfSyncTokenRequired = TRUE;
  486. BA_SyncOutgoing();
  487. OE2_SyncOutgoing(); // To reset order encoding
  488. OA_SyncOutgoing(); // To clear pending orders
  489. SBC_SyncOutgoing(); // To clear bitmap cache
  490. PM_SyncOutgoing(); // To clear palette cache
  491. SSI_SyncOutgoing(); // To reset savebits orders
  492. CM_SyncOutgoing(); // To send cursor shape/pos
  493. //
  494. // Tell the driver we are syncing
  495. //
  496. OSI_FunctionRequest(OSI_ESC_SYNC_NOW, &osi, sizeof(osi));
  497. DebugExitVOID(ASHost::HET_SyncCommon);
  498. }
  499. //
  500. // HET_SyncAlreadyHosting()
  501. // Called in a sync when we are already hosting and somebody joins call
  502. //
  503. void ASHost::HET_SyncAlreadyHosting(void)
  504. {
  505. DebugEntry(ASHost::HET_SyncAlreadyHosting);
  506. HET_RepaintAll();
  507. // Send out the current hosted count
  508. m_pShare->m_hetRetrySendState = TRUE;
  509. DebugExitVOID(ASHost::HET_SyncAlreadyHosting);
  510. }
  511. //
  512. // HET_RepaintAll()
  513. //
  514. // Repaints all shared stuff if there's at least two people in the share...
  515. //
  516. void ASHost::HET_RepaintAll(void)
  517. {
  518. DebugEntry(ASHost::HET_RepaintAll);
  519. ASSERT(m_pShare);
  520. ASSERT(m_pShare->m_pasLocal);
  521. if (m_pShare->m_hetViewers)
  522. {
  523. //
  524. // Only repaint if somebody's viewing
  525. //
  526. if (m_pShare->m_pasLocal->hetCount == HET_DESKTOPSHARED)
  527. {
  528. // Desktop sharing, so repaint desktop(s)
  529. USR_RepaintWindow(NULL);
  530. OSI_RepaintDesktop(); //special repaint for winlogon desktop
  531. }
  532. else
  533. {
  534. ERROR_OUT(("HET_RepaintAll - not sharing dekstop!"));
  535. }
  536. }
  537. DebugExitVOID(ASHost::HET_RepaintAll);
  538. }
  539. //
  540. // HET_Periodic()
  541. //
  542. void ASShare::HET_Periodic(void)
  543. {
  544. DebugEntry(ASShare::HET_Periodic);
  545. if (m_hetRetrySendState)
  546. {
  547. TRACE_OUT(( "Retry sending hosted count"));
  548. HETSendLocalCount();
  549. }
  550. DebugExitVOID(ASShare::HET_Periodic);
  551. }
  552. //
  553. // HET_WindowIsHosted - see het.h
  554. //
  555. BOOL ASShare::HET_WindowIsHosted(HWND hwnd)
  556. {
  557. BOOL rc = FALSE;
  558. DebugEntry(ASShare::HET_WindowIsHosted);
  559. //
  560. // Desktop sharing: everything is shared
  561. //
  562. if (m_pasLocal->hetCount == HET_DESKTOPSHARED)
  563. {
  564. rc = TRUE;
  565. }
  566. DebugExitBOOL(ASShare::HET_WindowIsHosted, rc);
  567. return(rc);
  568. }
  569. //
  570. // HETStartHosting()
  571. //
  572. // Called when we are about to begin sharing windows. fDesktop is TRUE if
  573. // we are sharing the entire desktop, FALSE if just individual windows.
  574. //
  575. BOOL ASShare::HETStartHosting(BOOL fDesktop)
  576. {
  577. BOOL rc = FALSE;
  578. DebugEntry(ASShare::HETStartHosting);
  579. //
  580. // Create the hosting object
  581. //
  582. ASSERT(!m_pHost);
  583. m_pHost = new ASHost;
  584. if (!m_pHost)
  585. {
  586. ERROR_OUT(("HETStartHosting: couldn't create m_pHost"));
  587. DC_QUIT;
  588. }
  589. ZeroMemory(m_pHost, sizeof(*(m_pHost)));
  590. SET_STAMP(m_pHost, HOST);
  591. //
  592. // Init hosting
  593. //
  594. if (!m_pHost->HET_HostStarting(this))
  595. {
  596. ERROR_OUT(("Failed to init hosting for local person"));
  597. DC_QUIT;
  598. }
  599. //
  600. // Start tracking graphics/windows
  601. //
  602. ASSERT(fDesktop);
  603. {
  604. HET_SHARE_DESKTOP hdr;
  605. //
  606. // Shortcut directly to display driver. No need to track windows
  607. // since everything will be shared.
  608. //
  609. if (!OSI_FunctionRequest(HET_ESC_SHARE_DESKTOP, (LPOSI_ESCAPE_HEADER)&hdr, sizeof(hdr)))
  610. {
  611. ERROR_OUT(("HET_ESC_SHARE_DESKTOP failed"));
  612. DC_QUIT;
  613. }
  614. }
  615. if (m_scfViewSelf && !HET_ViewStarting(m_pasLocal))
  616. {
  617. ERROR_OUT(("ViewSelf option is on, but can't create ASView data"));
  618. DC_QUIT;
  619. }
  620. HET_CalcViewers(NULL);
  621. rc = TRUE;
  622. DC_EXIT_POINT:
  623. //
  624. // Return to caller
  625. //
  626. DebugExitBOOL(ASShare::HETStartHosting, rc);
  627. return(rc);
  628. }
  629. //
  630. //
  631. // Name: HETStopHosting
  632. //
  633. // Description: Called when the last hosted window is unshared
  634. // ALWAYS CALL THIS AFTER the "hethostedTopLevel" count is 0.
  635. //
  636. // Params: none
  637. //
  638. //
  639. void ASShare::HETStopHosting(BOOL fDesktop)
  640. {
  641. DebugEntry(ASShare::HETStopHosting);
  642. m_hetViewers = FALSE;
  643. //
  644. // Stop tracking graphics/windows. This will stop viewing, then uninstall
  645. // hooks.
  646. //
  647. ASSERT(fDesktop);
  648. {
  649. HET_UNSHARE_DESKTOP hdr;
  650. //
  651. // There is no window tracking, just shortcut directly to the
  652. // display driver.
  653. //
  654. OSI_FunctionRequest(HET_ESC_UNSHARE_DESKTOP, (LPOSI_ESCAPE_HEADER)&hdr, sizeof(hdr));
  655. }
  656. //
  657. // Tell areas we are finished hosting
  658. //
  659. if (m_pHost)
  660. {
  661. //
  662. // If we're viewing ourself, kill the view first
  663. //
  664. if (m_scfViewSelf)
  665. {
  666. HET_ViewEnded(m_pasLocal);
  667. }
  668. m_pHost->HET_HostEnded();
  669. //
  670. // Delete host object
  671. //
  672. delete m_pHost;
  673. m_pHost = NULL;
  674. }
  675. //
  676. // Return to caller
  677. //
  678. DebugExitVOID(ASShare::HETStopHosting);
  679. }
  680. //
  681. // HETSendLocalCount()
  682. // This sends the hosting count to remotes.
  683. // * If zero, we are not sharing
  684. // * If one, we are sharing apps
  685. // * If 0xFFFF, we are sharing desktop
  686. //
  687. // Note that we used to send the real count of top level windows, so every
  688. // time a new window came or went, we would broadcast a packet. But
  689. // remotes only care when the value goes from zero to non-zero or back,
  690. // and when non-zero if it's the special desktop value or not. So don't
  691. // repeatedly broadcast values remotes don't care about!
  692. //
  693. void ASShare::HETSendLocalCount(void)
  694. {
  695. PHETPACKET pHETPacket;
  696. #ifdef _DEBUG
  697. UINT sentSize;
  698. #endif // _DEBUG
  699. DebugEntry(ASShare::HETSendLocalCount);
  700. //
  701. // Allocate a packet for the HET data.
  702. //
  703. pHETPacket = (PHETPACKET)SC_AllocPkt(PROT_STR_MISC, g_s20BroadcastID,
  704. sizeof(HETPACKET));
  705. if (!pHETPacket)
  706. {
  707. WARNING_OUT(("Failed to alloc HET host packet"));
  708. m_hetRetrySendState = TRUE;
  709. DC_QUIT;
  710. }
  711. //
  712. // Packet successfully allocated. Fill in the data and send it.
  713. //
  714. pHETPacket->header.data.dataType = DT_HET;
  715. pHETPacket->msg = HET_MSG_NUMHOSTED;
  716. switch (m_pasLocal->hetCount)
  717. {
  718. case 0:
  719. // Not hosting
  720. pHETPacket->hostState = HET_NOTHOSTING;
  721. break;
  722. case HET_DESKTOPSHARED:
  723. // Sharing desktop - 3.0 only
  724. pHETPacket->header.data.dataType = DT_HET30;
  725. pHETPacket->hostState = HET_DESKTOPSHARED;
  726. break;
  727. default:
  728. // Sharing apps
  729. pHETPacket->hostState = HET_APPSSHARED;
  730. break;
  731. }
  732. //
  733. // Compress and send the packet.
  734. //
  735. #ifdef _DEBUG
  736. sentSize =
  737. #endif // _DEBUG
  738. DCS_CompressAndSendPacket(PROT_STR_MISC, g_s20BroadcastID,
  739. &(pHETPacket->header), sizeof(*pHETPacket));
  740. TRACE_OUT(("HET packet size: %08d, sent %08d", sizeof(*pHETPacket), sentSize));
  741. TRACE_OUT(("Sent new HET packet (%d)", m_pasLocal->hetCount));
  742. m_hetRetrySendState = FALSE;
  743. //
  744. // Return to caller
  745. //
  746. DC_EXIT_POINT:
  747. DebugExitVOID(ASShare::HETSendLocalCount);
  748. }
  749. //
  750. // HETUpdateLocalCount()
  751. //
  752. void ASShare::HETUpdateLocalCount(UINT newCount)
  753. {
  754. UINT oldCount;
  755. DebugEntry(ASShare::HETUpdateLocalCount);
  756. oldCount = m_pasLocal->hetCount;
  757. m_pasLocal->hetCount = newCount;
  758. if ((oldCount == 0) && (newCount != 0))
  759. {
  760. //
  761. // Don't bother sending net packets if nobody is viewing
  762. //
  763. if (m_hetViewers)
  764. {
  765. HETSendLocalCount();
  766. }
  767. HETCheckSharing(TRUE);
  768. }
  769. else if ((oldCount != 0) && (newCount == 0))
  770. {
  771. if (m_hetViewers)
  772. {
  773. //
  774. // Ending host, desktop or apps
  775. //
  776. HETSendLocalCount();
  777. }
  778. //
  779. // The local guy is stopping sharing.
  780. //
  781. HETStopHosting(oldCount == HET_DESKTOPSHARED);
  782. HETCheckSharing(FALSE);
  783. }
  784. DebugExitVOID(ASShare::HETUpdateLocalCount);
  785. }
  786. //
  787. // HETUpdateRemoteCount()
  788. //
  789. // Updates the count of shared top level windows from a remote, and notifies
  790. // the UI on transition from/to zero if a remote. If local, kills the share.
  791. //
  792. void ASShare::HETUpdateRemoteCount
  793. (
  794. ASPerson * pasPerson,
  795. UINT newCount
  796. )
  797. {
  798. UINT oldCount;
  799. DebugEntry(ASShare::HETUpdateRemoteCount);
  800. ValidatePerson(pasPerson);
  801. ASSERT(pasPerson != m_pasLocal);
  802. oldCount = pasPerson->hetCount;
  803. pasPerson->hetCount = newCount;
  804. TRACE_OUT(("HETUpdateRemoteCount: Person [%d] old %d, new %d",
  805. pasPerson->mcsID, oldCount, newCount));
  806. //
  807. // We generate events for remote people if
  808. // * They were sharing but now they aren't
  809. // * There weren't sharing but now they are
  810. //
  811. if ((oldCount == 0) && (newCount != 0))
  812. {
  813. //
  814. // The remote dude started to share
  815. //
  816. if (!HET_ViewStarting(pasPerson))
  817. {
  818. ERROR_OUT(("HET_ViewStarting failed; pretending remote not sharing"));
  819. pasPerson->hetCount = 0;
  820. HET_ViewEnded(pasPerson);
  821. }
  822. else
  823. {
  824. HETCheckSharing(TRUE);
  825. }
  826. }
  827. else if ((oldCount != 0) && (newCount == 0))
  828. {
  829. //
  830. // The remote dude stopped sharing. Notify the UI also.
  831. //
  832. HET_ViewEnded(pasPerson);
  833. HETCheckSharing(FALSE);
  834. }
  835. DebugExitVOID(ASShare::HETUpdateRemoteCount);
  836. }
  837. //
  838. // HETCheckSharing()
  839. // Called when any member of the conference (local or remote) transitions
  840. // to/from sharing. When the first person has shared something, we notify
  841. // the UI. When the last person has stopped sharing, we kill the share which
  842. // will notify the UI.
  843. //
  844. void ASShare::HETCheckSharing(BOOL fStarting)
  845. {
  846. DebugEntry(ASShare::HETCheckSharing);
  847. if (fStarting)
  848. {
  849. ++m_hetHostCount;
  850. if (m_hetHostCount == 1)
  851. {
  852. // First host started
  853. TRACE_OUT(("First person started hosting"));
  854. DCS_NotifyUI(SH_EVT_SHARING_STARTED, 0, 0);
  855. }
  856. }
  857. else
  858. {
  859. ASSERT(m_hetHostCount > 0);
  860. --m_hetHostCount;
  861. if (m_hetHostCount == 0)
  862. {
  863. //
  864. // Last host stopped sharing -- end share if we're not cleaning
  865. // up after the fact. But don't do it NOW, post a message.
  866. // We may have come in here because the share is ending already.
  867. //
  868. PostMessage(g_asMainWindow, DCS_KILLSHARE_MSG, 0, 0);
  869. }
  870. }
  871. DebugExitVOID(ASShare::HETCheckSharing);
  872. }
  873. //
  874. // HET_HostStarting()
  875. //
  876. // Called when we start to host applications. This creates our host data
  877. // then calls the component HostStarting() routines
  878. //
  879. BOOL ASHost::HET_HostStarting(ASShare * pShare)
  880. {
  881. BOOL rc = FALSE;
  882. DebugEntry(ASHost::HET_HostStarting);
  883. // Set back pointer to share
  884. m_pShare = pShare;
  885. //
  886. // Turn effects off
  887. //
  888. HET_SetGUIEffects(FALSE, &m_hetEffects);
  889. OSI_SetGUIEffects(FALSE);
  890. //
  891. // Now call HostStarting() routines
  892. //
  893. if (!USR_HostStarting())
  894. {
  895. ERROR_OUT(("USR_HostStarting failed"));
  896. DC_QUIT;
  897. }
  898. if (!OE2_HostStarting())
  899. {
  900. ERROR_OUT(("OE2_HostStarting failed"));
  901. DC_QUIT;
  902. }
  903. if (!SBC_HostStarting())
  904. {
  905. ERROR_OUT(("SBC_HostStarting failed"));
  906. DC_QUIT;
  907. }
  908. if (!CM_HostStarting())
  909. {
  910. ERROR_OUT(("CM_HostStarting failed"));
  911. DC_QUIT;
  912. }
  913. if (!SSI_HostStarting())
  914. {
  915. ERROR_OUT(("SSI_HostStarting failed"));
  916. DC_QUIT;
  917. }
  918. if (!PM_HostStarting())
  919. {
  920. ERROR_OUT(("PM_HostStarting failed"));
  921. DC_QUIT;
  922. }
  923. if (!SWL_HostStarting())
  924. {
  925. ERROR_OUT(("SWL_HostStarting failed"));
  926. DC_QUIT;
  927. }
  928. if (!VIEW_HostStarting())
  929. {
  930. ERROR_OUT(("VIEW_HostStarting failed"));
  931. DC_QUIT;
  932. }
  933. //
  934. // Now reset OUTGOING info. 2.x nodes do not; that's why we have to
  935. // hang on to RBC, OD2, CM, PM data for them. When 2.x compat is gone,
  936. // we can move ASPerson data in to ASView, which is only around while
  937. // the person is in fact hosting.
  938. //
  939. OA_LocalHostReset();
  940. //
  941. // Reset OUTGOING data.
  942. // Note corresponding cleanup for 3.0 nodes
  943. // in CM, OD2, RBC, and PM.
  944. // Note that we don't need to reset SSI incoming goop, since we will
  945. // clear all pending orders and are invalidating everything shared
  946. // from scratch. There will be no reference to a previous savebits.
  947. //
  948. HET_SyncCommon();
  949. rc = TRUE;
  950. DC_EXIT_POINT:
  951. DebugExitBOOL(ASHost::HET_HostStarting, rc);
  952. return(rc);
  953. }
  954. //
  955. // HET_HostEnded()
  956. //
  957. // Called when we stop hosting applications.
  958. //
  959. void ASHost::HET_HostEnded(void)
  960. {
  961. DebugEntry(ASHost::HET_HostEnded);
  962. //
  963. // Call HostEnded() routines
  964. //
  965. CA_HostEnded();
  966. PM_HostEnded();
  967. CM_HostEnded();
  968. SBC_HostEnded();
  969. OE2_HostEnded();
  970. USR_HostEnded();
  971. //
  972. // Restore windows animation.
  973. //
  974. HET_SetGUIEffects(TRUE, &m_hetEffects);
  975. OSI_SetGUIEffects(TRUE);
  976. DebugExitVOID(ASHost::HET_HostEnded);
  977. }
  978. //
  979. // HET_ViewStarting()
  980. //
  981. // Called to create the data needed to view somebody who is hosting.
  982. //
  983. BOOL ASShare::HET_ViewStarting(ASPerson * pasPerson)
  984. {
  985. BOOL rc = FALSE;
  986. DebugEntry(ASShare::HET_ViewStarting);
  987. ValidatePerson(pasPerson);
  988. //
  989. // Create ASView object
  990. //
  991. ASSERT(!pasPerson->m_pView);
  992. // Allocate VIEW structure
  993. pasPerson->m_pView = new ASView;
  994. if (!pasPerson->m_pView)
  995. {
  996. // Abject, total, failure.
  997. ERROR_OUT(("HET_ViewStarting: Couldn't allocate ASView for [%d]", pasPerson->mcsID));
  998. DC_QUIT;
  999. }
  1000. ZeroMemory(pasPerson->m_pView, sizeof(*(pasPerson->m_pView)));
  1001. SET_STAMP(pasPerson->m_pView, VIEW);
  1002. //
  1003. // Now call ViewStarting routines
  1004. //
  1005. if (!USR_ViewStarting(pasPerson))
  1006. {
  1007. ERROR_OUT(("USR_ViewStarting failed"));
  1008. DC_QUIT;
  1009. }
  1010. if (!OD2_ViewStarting(pasPerson))
  1011. {
  1012. ERROR_OUT(("OD2_ViewStarting failed"));
  1013. DC_QUIT;
  1014. }
  1015. if (!OD_ViewStarting(pasPerson))
  1016. {
  1017. ERROR_OUT(("OD_ViewStarting failed"));
  1018. DC_QUIT;
  1019. }
  1020. if (!RBC_ViewStarting(pasPerson))
  1021. {
  1022. ERROR_OUT(("RBC_ViewStarting failed"));
  1023. DC_QUIT;
  1024. }
  1025. if (!CM_ViewStarting(pasPerson))
  1026. {
  1027. ERROR_OUT(("CM_ViewStarting failed"));
  1028. DC_QUIT;
  1029. }
  1030. if (!SSI_ViewStarting(pasPerson))
  1031. {
  1032. ERROR_OUT(("SSI_ViewStarting failed"));
  1033. DC_QUIT;
  1034. }
  1035. if (!PM_ViewStarting(pasPerson))
  1036. {
  1037. ERROR_OUT(("PM_ViewStarting failed"));
  1038. DC_QUIT;
  1039. }
  1040. if (!VIEW_ViewStarting(pasPerson))
  1041. {
  1042. ERROR_OUT(("VIEW_ViewStarting failed"));
  1043. DC_QUIT;
  1044. }
  1045. if (!CA_ViewStarting(pasPerson))
  1046. {
  1047. ERROR_OUT(("CA_ViewStarting failed"));
  1048. DC_QUIT;
  1049. }
  1050. rc = TRUE;
  1051. DC_EXIT_POINT:
  1052. DebugExitBOOL(ASShare::HET_ViewStarting, rc);
  1053. return(rc);
  1054. }
  1055. //
  1056. // HET_ViewEnded()
  1057. //
  1058. // Called when we stop viewing a host
  1059. //
  1060. void ASShare::HET_ViewEnded(ASPerson * pasPerson)
  1061. {
  1062. DebugEntry(ASShare::HET_ViewEnded);
  1063. ValidatePerson(pasPerson);
  1064. if (pasPerson->m_pView)
  1065. {
  1066. //
  1067. // Call the component ViewEnded routines
  1068. //
  1069. CA_ViewEnded(pasPerson);
  1070. VIEW_ViewEnded(pasPerson);
  1071. PM_ViewEnded(pasPerson);
  1072. SSI_ViewEnded(pasPerson);
  1073. CM_ViewEnded(pasPerson);
  1074. RBC_ViewEnded(pasPerson);
  1075. OD_ViewEnded(pasPerson);
  1076. OD2_ViewEnded(pasPerson);
  1077. USR_ViewEnded(pasPerson);
  1078. delete pasPerson->m_pView;
  1079. pasPerson->m_pView = NULL;
  1080. }
  1081. DebugExitVOID(ASShare::HET_ViewEnded);
  1082. }
  1083. //
  1084. // HET_SetGUIEffects
  1085. //
  1086. // Turns various animations off/on when we start/stop hosting, to improve
  1087. // performance. Currently, we mess with
  1088. // * min animation
  1089. // * all of the effects in SPI_SETUIEFFECTS (tooltip fade, menu animation,
  1090. // etc.)
  1091. // * cursor shadows
  1092. //
  1093. // We don't turn off smooth scroll or full drag.
  1094. //
  1095. void HET_SetGUIEffects
  1096. (
  1097. BOOL fOn,
  1098. GUIEFFECTS * pEffects
  1099. )
  1100. {
  1101. DebugEntry(HET_SetGUIEffects);
  1102. ASSERT(!IsBadWritePtr(pEffects, sizeof(*pEffects)));
  1103. //
  1104. // NB. We deliberately do not track the state of animation whilst we
  1105. // are sharing. A determined user could, using some other app (such as
  1106. // the TweakUI control panel applet) reenable animation whilst in a
  1107. // share. We will respect this.
  1108. //
  1109. // We only affect the current 'in memory' setting - we do not write our
  1110. // temporary change to file.
  1111. //
  1112. if (fOn)
  1113. {
  1114. //
  1115. // If it was on before, restore it.
  1116. //
  1117. if (pEffects->hetAnimation.iMinAnimate)
  1118. {
  1119. pEffects->hetAnimation.cbSize = sizeof(pEffects->hetAnimation);
  1120. SystemParametersInfo(SPI_SETANIMATION, sizeof(pEffects->hetAnimation),
  1121. &pEffects->hetAnimation, 0);
  1122. }
  1123. if (pEffects->hetAdvanced)
  1124. {
  1125. SystemParametersInfo(SPI_SETUIEFFECTS, 0,
  1126. (LPVOID)pEffects->hetAdvanced, 0);
  1127. }
  1128. if (pEffects->hetCursorShadow)
  1129. {
  1130. SystemParametersInfo(SPI_SETCURSORSHADOW, 0,
  1131. (LPVOID)pEffects->hetCursorShadow, 0);
  1132. }
  1133. }
  1134. else
  1135. {
  1136. //
  1137. // Find out what animations are on.
  1138. //
  1139. ZeroMemory(&pEffects->hetAnimation, sizeof(pEffects->hetAnimation));
  1140. pEffects->hetAnimation.cbSize = sizeof(pEffects->hetAnimation);
  1141. SystemParametersInfo(SPI_GETANIMATION, sizeof(pEffects->hetAnimation),
  1142. &pEffects->hetAnimation, 0);
  1143. pEffects->hetAdvanced = FALSE;
  1144. SystemParametersInfo(SPI_GETUIEFFECTS, 0, &pEffects->hetAdvanced, 0);
  1145. pEffects->hetCursorShadow = FALSE;
  1146. SystemParametersInfo(SPI_GETCURSORSHADOW, 0, &pEffects->hetCursorShadow, 0);
  1147. //
  1148. // Turn off the animations which are on.
  1149. //
  1150. if (pEffects->hetAnimation.iMinAnimate)
  1151. {
  1152. //
  1153. // It's currently enabled, suppress it.
  1154. //
  1155. pEffects->hetAnimation.cbSize = sizeof(pEffects->hetAnimation);
  1156. pEffects->hetAnimation.iMinAnimate = FALSE;
  1157. SystemParametersInfo(SPI_SETANIMATION, sizeof(pEffects->hetAnimation),
  1158. &pEffects->hetAnimation, 0);
  1159. // SPI will wipe this out. Keep it set so we know to restore it.
  1160. pEffects->hetAnimation.iMinAnimate = TRUE;
  1161. }
  1162. if (pEffects->hetAdvanced)
  1163. {
  1164. SystemParametersInfo(SPI_SETUIEFFECTS, 0, FALSE, 0);
  1165. }
  1166. if (pEffects->hetCursorShadow)
  1167. {
  1168. SystemParametersInfo(SPI_SETCURSORSHADOW, 0, FALSE, 0);
  1169. }
  1170. }
  1171. DebugExitVOID(ASHost::HET_SetGUIEffects);
  1172. }