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.

450 lines
14 KiB

  1. #include "precomp.h"
  2. //
  3. // SSI.CPP
  4. // Save Screenbits Interceptor
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. #define MLZ_FILE_ZONE ZONE_CORE
  9. //
  10. // SSI_HostStarting()
  11. //
  12. // Called when we start to host, figures out the max save bitmap bits size
  13. // etc.
  14. //
  15. BOOL ASHost::SSI_HostStarting(void)
  16. {
  17. DebugEntry(ASHost::SSI_HostStarting);
  18. m_pShare->SSI_RecalcCaps(TRUE);
  19. DebugExitBOOL(ASHost::SSI_HostStarting, TRUE);
  20. return(TRUE);
  21. }
  22. //
  23. // SSI_ViewStarted()
  24. //
  25. // Called when someone we are viewing has started to host. Creates save bits
  26. // bitmap for them.
  27. //
  28. BOOL ASShare::SSI_ViewStarting(ASPerson * pasPerson)
  29. {
  30. BOOL rc = FALSE;
  31. HDC hdcScreen = NULL;
  32. DebugEntry(ASShare::SSI_ViewStarting);
  33. ValidateView(pasPerson);
  34. //
  35. // ASSERT that this persons' variables are clear.
  36. //
  37. ASSERT(pasPerson->m_pView->m_ssiBitmapHeight == 0);
  38. ASSERT(pasPerson->m_pView->m_ssiBitmap == NULL);
  39. ASSERT(pasPerson->m_pView->m_ssiOldBitmap == NULL);
  40. //
  41. // Does this person support savebits?
  42. //
  43. if (!pasPerson->cpcCaps.orders.capsSendSaveBitmapSize)
  44. {
  45. // No receive SSI capability, bail out now.
  46. rc = TRUE;
  47. DC_QUIT;
  48. }
  49. //
  50. // Store the height of this host's bitmap.
  51. //
  52. pasPerson->m_pView->m_ssiBitmapHeight = (int)
  53. (pasPerson->cpcCaps.orders.capsSendSaveBitmapSize / TSHR_SSI_BITMAP_WIDTH);
  54. //
  55. // If the calculated bitmap size is not exactly divisible by the bitmap
  56. // width increase the bitmap height to fit in the partial row.
  57. //
  58. if (pasPerson->cpcCaps.orders.capsSendSaveBitmapSize % TSHR_SSI_BITMAP_WIDTH)
  59. {
  60. pasPerson->m_pView->m_ssiBitmapHeight += pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity;
  61. }
  62. TRACE_OUT(("Person [%d] SSI Bitmap height %d",
  63. pasPerson->mcsID,
  64. pasPerson->m_pView->m_ssiBitmapHeight));
  65. //
  66. // Create this host's save screen bitmap.
  67. //
  68. hdcScreen = GetDC(NULL);
  69. if (hdcScreen == NULL)
  70. {
  71. ERROR_OUT(( "Failed to get screen surface"));
  72. DC_QUIT;
  73. }
  74. //
  75. // Create the save screen bitmap DC.
  76. //
  77. ASSERT(pasPerson->m_pView->m_ssiDC == NULL);
  78. pasPerson->m_pView->m_ssiDC = CreateCompatibleDC(hdcScreen);
  79. if (!pasPerson->m_pView->m_ssiDC)
  80. {
  81. ERROR_OUT(("Failed to create SSI DC"));
  82. DC_QUIT;
  83. }
  84. //
  85. // Create the save screen bitmap.
  86. //
  87. ASSERT(pasPerson->m_pView->m_ssiBitmap == NULL);
  88. pasPerson->m_pView->m_ssiBitmap = CreateCompatibleBitmap(hdcScreen,
  89. TSHR_SSI_BITMAP_WIDTH, pasPerson->m_pView->m_ssiBitmapHeight);
  90. if (!pasPerson->m_pView->m_ssiBitmap)
  91. {
  92. ERROR_OUT(("SSI_ViewStarting: can't create bitmap for person %x",
  93. pasPerson->mcsID));
  94. DC_QUIT;
  95. }
  96. //
  97. // Select the save screen bitmap into the DC
  98. //
  99. ASSERT(pasPerson->m_pView->m_ssiOldBitmap == NULL);
  100. pasPerson->m_pView->m_ssiOldBitmap = SelectBitmap(pasPerson->m_pView->m_ssiDC,
  101. pasPerson->m_pView->m_ssiBitmap);
  102. rc = TRUE;
  103. DC_EXIT_POINT:
  104. if (hdcScreen != NULL)
  105. {
  106. ReleaseDC(NULL, hdcScreen);
  107. }
  108. DebugExitBOOL(ASShare::SSI_ViewStarting, rc);
  109. return(rc);
  110. }
  111. //
  112. // SSI_ViewEnded()
  113. //
  114. // Called when someone we are viewing has stopped hosting, so we can clean
  115. // up our view data for them.
  116. //
  117. void ASShare::SSI_ViewEnded(ASPerson * pasPerson)
  118. {
  119. DebugEntry(ASShare::SSI_ViewEnded);
  120. ValidateView(pasPerson);
  121. //
  122. // Deselect the save screen bitmap if there is one
  123. //
  124. if (pasPerson->m_pView->m_ssiOldBitmap != NULL)
  125. {
  126. SelectBitmap(pasPerson->m_pView->m_ssiDC, pasPerson->m_pView->m_ssiOldBitmap);
  127. pasPerson->m_pView->m_ssiOldBitmap = NULL;
  128. }
  129. //
  130. // Delete the save screen bitmap
  131. //
  132. if (pasPerson->m_pView->m_ssiBitmap != NULL)
  133. {
  134. DeleteBitmap(pasPerson->m_pView->m_ssiBitmap);
  135. pasPerson->m_pView->m_ssiBitmap = NULL;
  136. }
  137. //
  138. // Delete the save screen DC
  139. //
  140. if (pasPerson->m_pView->m_ssiDC != NULL)
  141. {
  142. DeleteDC(pasPerson->m_pView->m_ssiDC);
  143. pasPerson->m_pView->m_ssiDC = NULL;
  144. }
  145. DebugExitVOID(ASShare::SSI_ViewEnded);
  146. }
  147. //
  148. // SSI_SyncOutgoing()
  149. // Called when NEW (3.0) dude starts to share, a share is created, or
  150. // someone new joins the share.
  151. // Resets save state for OUTGOING save/restore orders.
  152. //
  153. void ASHost::SSI_SyncOutgoing(void)
  154. {
  155. OSI_ESCAPE_HEADER request;
  156. DebugEntry(ASHost::SSI_SyncOutgoing);
  157. //
  158. // Discard any saved bitmaps. This ensures that the subsequent
  159. // datastream will not refer to any previously sent data.
  160. //
  161. //
  162. // Make sure the display driver resets the save level. Note we don't
  163. // really care what happens in the display driver, so don't bother with
  164. // a special request block - use a standard request header.
  165. //
  166. OSI_FunctionRequest(SSI_ESC_RESET_LEVEL, &request, sizeof(request));
  167. DebugExitVOID(ASHost::SSI_SyncOutgoing);
  168. }
  169. //
  170. // FUNCTION: SSI_SaveBitmap
  171. //
  172. // DESCRIPTION:
  173. // Replays a SaveBitmap order by saving or restoring a specified area of
  174. // the user's desktop bitmap.
  175. //
  176. //
  177. void ASShare::SSI_SaveBitmap
  178. (
  179. ASPerson * pasPerson,
  180. LPSAVEBITMAP_ORDER pSaveBitmap
  181. )
  182. {
  183. RECT screenBitmapRect;
  184. RECT saveBitmapRect;
  185. int xSaveBitmap;
  186. int ySaveBitmap;
  187. int xScreenBitmap;
  188. int yScreenBitmap;
  189. int cxTile;
  190. int cyTile;
  191. DebugEntry(ASShare::SSI_SaveBitmap);
  192. ValidateView(pasPerson);
  193. if ((pSaveBitmap->Operation != SV_SAVEBITS) &&
  194. (pSaveBitmap->Operation != SV_RESTOREBITS))
  195. {
  196. ERROR_OUT(("SSI_SaveBitmap: unrecognized SV_ value %d",
  197. pSaveBitmap->Operation));
  198. DC_QUIT;
  199. }
  200. //
  201. // Calculate the (x,y) start position from the pel start position
  202. // given in the order.
  203. //
  204. ySaveBitmap = (pSaveBitmap->SavedBitmapPosition /
  205. (TSHR_SSI_BITMAP_WIDTH *
  206. (UINT)pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity)) *
  207. pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity;
  208. xSaveBitmap = (pSaveBitmap->SavedBitmapPosition -
  209. (ySaveBitmap *
  210. (UINT)TSHR_SSI_BITMAP_WIDTH)) /
  211. pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity;
  212. screenBitmapRect.left = pSaveBitmap->nLeftRect
  213. - pasPerson->m_pView->m_dsScreenOrigin.x;
  214. screenBitmapRect.top = pSaveBitmap->nTopRect
  215. - pasPerson->m_pView->m_dsScreenOrigin.y;
  216. screenBitmapRect.right = pSaveBitmap->nRightRect + 1
  217. - pasPerson->m_pView->m_dsScreenOrigin.x;
  218. screenBitmapRect.bottom = pSaveBitmap->nBottomRect + 1
  219. - pasPerson->m_pView->m_dsScreenOrigin.y;
  220. saveBitmapRect.left = 0;
  221. saveBitmapRect.top = 0;
  222. saveBitmapRect.right = TSHR_SSI_BITMAP_WIDTH;
  223. saveBitmapRect.bottom = pasPerson->m_pView->m_ssiBitmapHeight;
  224. //
  225. // Start tiling in the top left corner of the Screen Bitmap rectangle.
  226. //
  227. xScreenBitmap = screenBitmapRect.left;
  228. yScreenBitmap = screenBitmapRect.top;
  229. //
  230. // The height of the tile is the vertical granularity (or less - if
  231. // the Screen Bitmap rect is thinner than the granularity).
  232. //
  233. cyTile = min(screenBitmapRect.bottom - yScreenBitmap,
  234. (int)pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity );
  235. //
  236. // Repeat while there are more tiles in the Screen Bitmap rect to
  237. // process.
  238. //
  239. while (yScreenBitmap < screenBitmapRect.bottom)
  240. {
  241. //
  242. // The width of the tile is the minimum of:
  243. //
  244. // - the width of the remaining rectangle in the current strip of
  245. // the Screen Bitmap rectangle
  246. //
  247. // - the width of the remaining empty space in the current strip of
  248. // the Save Bitmap
  249. //
  250. //
  251. cxTile = min( saveBitmapRect.right - xSaveBitmap,
  252. screenBitmapRect.right - xScreenBitmap );
  253. TRACE_OUT(( "screen(%d,%d) save(%d,%d) cx(%d) cy(%d)",
  254. xScreenBitmap,
  255. yScreenBitmap,
  256. xSaveBitmap,
  257. ySaveBitmap,
  258. cxTile,
  259. cyTile ));
  260. //
  261. // Save or Restore this tile
  262. //
  263. if (pSaveBitmap->Operation == SV_SAVEBITS)
  264. {
  265. //
  266. // Save user's desktop area to SSI bitmap
  267. //
  268. BitBlt(pasPerson->m_pView->m_ssiDC,
  269. xSaveBitmap, ySaveBitmap, cxTile, cyTile,
  270. pasPerson->m_pView->m_usrDC,
  271. xScreenBitmap, yScreenBitmap, SRCCOPY);
  272. }
  273. else
  274. {
  275. //
  276. // Restore user's desktop area from SSI bitmap
  277. //
  278. BitBlt(pasPerson->m_pView->m_usrDC,
  279. xScreenBitmap, yScreenBitmap, cxTile, cyTile,
  280. pasPerson->m_pView->m_ssiDC,
  281. xSaveBitmap, ySaveBitmap, SRCCOPY);
  282. }
  283. //
  284. // Move to the next tile in the Screen Bitmap rectangle.
  285. //
  286. xScreenBitmap += cxTile;
  287. if (xScreenBitmap >= screenBitmapRect.right)
  288. {
  289. xScreenBitmap = screenBitmapRect.left;
  290. yScreenBitmap += cyTile;
  291. cyTile = min( screenBitmapRect.bottom - yScreenBitmap,
  292. (int)pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity );
  293. }
  294. //
  295. // Move to the next free space in the Save Bitmap.
  296. //
  297. xSaveBitmap += ROUNDUP(cxTile, pasPerson->cpcCaps.orders.capsSaveBitmapXGranularity);
  298. if (xSaveBitmap >= saveBitmapRect.right)
  299. {
  300. xSaveBitmap = saveBitmapRect.left;
  301. ySaveBitmap += ROUNDUP(cyTile, pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity);
  302. }
  303. }
  304. DC_EXIT_POINT:
  305. DebugExitVOID(ASShare::SSI_SaveBitmap);
  306. }
  307. //
  308. // SSI_RecalcCaps()
  309. //
  310. // Called when we are hosting and someone joins/leaves the share.
  311. //
  312. // When 2.x COMPAT IS GONE, THIS IS OBSOLETE
  313. //
  314. void ASShare::SSI_RecalcCaps(BOOL fJoiner)
  315. {
  316. ASPerson * pasT;
  317. SSI_NEW_CAPABILITIES newCapabilities;
  318. DebugEntry(ASShare::SSI_RecalcCaps);
  319. if (!m_pHost)
  320. {
  321. //
  322. // Nothing to do. Note that we recalc when someone joins AND
  323. // when someone leaves, like SBC.
  324. //
  325. DC_QUIT;
  326. }
  327. ValidatePerson(m_pasLocal);
  328. //
  329. // Enumerate all the save screen bitmap receive capabilities of the
  330. // parties in the share. The usable size of the send save screen
  331. // bitmap is then the minimum of all the remote receive sizes and the
  332. // local send size.
  333. //
  334. //
  335. // Copy the locally registered send save screen bitmap size capability
  336. // to our global variable used to communicate with the enumeration
  337. // function SSIEnumBitmapCacheCaps().
  338. //
  339. m_pHost->m_ssiSaveBitmapSize = m_pasLocal->cpcCaps.orders.capsReceiveSaveBitmapSize;
  340. //
  341. // Now enumerate all the parties in the share and set our send bitmap
  342. // size appropriately.
  343. //
  344. if (m_scShareVersion < CAPS_VERSION_30)
  345. {
  346. TRACE_OUT(("In share with 2.x nodes; must recalc SSI caps"));
  347. for (pasT = m_pasLocal->pasNext; pasT != NULL; pasT = pasT->pasNext)
  348. {
  349. //
  350. // Set the size of the local send save screen bitmap to the minimum of
  351. // its current size and this party's receive save screen bitmap size.
  352. //
  353. m_pHost->m_ssiSaveBitmapSize = min(m_pHost->m_ssiSaveBitmapSize,
  354. pasT->cpcCaps.orders.capsReceiveSaveBitmapSize);
  355. }
  356. TRACE_OUT(("Recalced SSI caps: SS bitmap size 0x%08x",
  357. m_pHost->m_ssiSaveBitmapSize));
  358. }
  359. //
  360. // Set up the new capabilities structure...
  361. //
  362. newCapabilities.sendSaveBitmapSize = m_pHost->m_ssiSaveBitmapSize;
  363. newCapabilities.xGranularity = TSHR_SSI_BITMAP_X_GRANULARITY;
  364. newCapabilities.yGranularity = TSHR_SSI_BITMAP_Y_GRANULARITY;
  365. //
  366. // ... and pass it through to the driver.
  367. //
  368. if (!OSI_FunctionRequest(SSI_ESC_NEW_CAPABILITIES, (LPOSI_ESCAPE_HEADER)&newCapabilities,
  369. sizeof(newCapabilities)))
  370. {
  371. ERROR_OUT(("SSI_ESC_NEW_CAPABILITIES failed"));
  372. }
  373. DC_EXIT_POINT:
  374. DebugExitVOID(ASHost::SSI_RecalcCaps);
  375. }