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.

814 lines
30 KiB

  1. #include "precomp.h"
  2. //
  3. // SDG.CPP
  4. // Screen Data Grabber
  5. // Sends OUTGOING screen data when hosting
  6. //
  7. // Copyright(c) Microsoft 1997-
  8. //
  9. #define MLZ_FILE_ZONE ZONE_CORE
  10. //
  11. // SDG_SendScreenDataArea()
  12. //
  13. void ASHost::SDG_SendScreenDataArea(LPBOOL pBackPressure, UINT * pcPackets)
  14. {
  15. UINT i;
  16. BOOL fBltOK = TRUE;
  17. RECT sdaRect[BA_NUM_RECTS];
  18. UINT cRects;
  19. BOOL backPressure = FALSE;
  20. BOOL secondaryTransmit = FALSE;
  21. DebugEntry(ASHost::SDG_SendScreenDataArea);
  22. //
  23. // Get the bounds of the screen data area. At entry this is always
  24. // our primary transmission area. Even if we had already flushed
  25. // the primary region and were in the middle of the secondary region
  26. // we will switch back to the primary region if any more SD
  27. // accumulates. In this way we keep our spoiling of the secondary
  28. // screendata maximized.
  29. //
  30. BA_CopyBounds(sdaRect, &cRects, TRUE);
  31. //
  32. // If there is a pending rectangle that was unable to be sent on a
  33. // previous transmission then try to send it first.
  34. //
  35. // Leave the lossy flag as it was at the last pass
  36. //
  37. if (m_sdgRectIsPending)
  38. {
  39. TRACE_OUT(( "Sending pending rectangle"));
  40. m_sdgRectIsPending = FALSE;
  41. //
  42. // Try to send the pending rectangle. SDGSplitBlt... will remove
  43. // any portions of it that are sent successfully. We will add all
  44. // the rest of the SDA back to the bounds in the loop below
  45. //
  46. if (!SDGSplitBltToNetwork(&m_sdgPendingRect, pcPackets))
  47. {
  48. fBltOK = FALSE;
  49. m_sdgRectIsPending = TRUE;
  50. }
  51. else
  52. {
  53. //
  54. // The pending rectangle was successfully sent.
  55. //
  56. TRACE_OUT(( "Sent pending rect"));
  57. }
  58. }
  59. //
  60. // We have copied the primary transmit region so now move the secondary
  61. // transmit bounds into the screendata bounds because when we send data
  62. // in the primary transmission we want to accumulate any rectangles
  63. // that need subsequent retransmission. The retransmit bounds are
  64. // generally different from the original SD bounds because the
  65. // compression function is permitted to override our lossy request for
  66. // any portion of the data if it finds that the data is pretty
  67. // compressible anyway. In this way we end up with retransmission of
  68. // embedded photos etc, but the toolbars/buttons are only sent once.
  69. //
  70. // For the non-lossy case the secondary bounds will always be null,
  71. // so there is no point in special casing here.
  72. //
  73. if (fBltOK)
  74. {
  75. for (i = 0; i < m_sdgcLossy; i++)
  76. {
  77. TRACE_OUT(("Setting up pseudo-primary bounds {%d, %d, %d, %d}",
  78. m_asdgLossyRect[i].left, m_asdgLossyRect[i].top,
  79. m_asdgLossyRect[i].right, m_asdgLossyRect[i].bottom ));
  80. //
  81. // Add the rectangle into the bounds.
  82. //
  83. BA_AddRect(&m_asdgLossyRect[i]);
  84. }
  85. //
  86. // If there is no primary bitmap data to send then send the
  87. // secondary data. If none of that either then just exit
  88. //
  89. if (cRects == 0)
  90. {
  91. BA_CopyBounds(sdaRect, &cRects, TRUE);
  92. if (cRects == 0)
  93. {
  94. DC_QUIT;
  95. }
  96. else
  97. {
  98. TRACE_OUT(("Starting secondary transmission now"));
  99. secondaryTransmit = TRUE;
  100. }
  101. }
  102. }
  103. //
  104. // Process each of the supplied rectangles in turn.
  105. //
  106. TRACE_OUT(( "%d SDA rectangles", cRects));
  107. for (i = 0; i < cRects; i++)
  108. {
  109. TRACE_OUT(("Rect %d: {%d, %d, %d, %d}", i,
  110. sdaRect[i].left, sdaRect[i].top, sdaRect[i].right, sdaRect[i].bottom ));
  111. //
  112. // Clip the rectangle to the physical screen and reject totally
  113. // any rectangle that refers to data that has now been scrolled off
  114. // the physical screen as a result of a desktop scroll between the
  115. // time the rectangle was accumulated and now.
  116. //
  117. if (sdaRect[i].left < 0)
  118. {
  119. if (sdaRect[i].right < 0)
  120. {
  121. //
  122. // This was scrolled off the physical screen by a desktop
  123. // scroll.
  124. //
  125. continue;
  126. }
  127. //
  128. // Partially off screen - just clip the left edge.
  129. //
  130. sdaRect[i].left = 0;
  131. }
  132. if (sdaRect[i].top < 0)
  133. {
  134. if (sdaRect[i].bottom < 0)
  135. {
  136. //
  137. // This was scrolled off the physical screen by a desktop
  138. // scroll.
  139. //
  140. continue;
  141. }
  142. //
  143. // Partially off screen - just clip the top edge.
  144. //
  145. sdaRect[i].top = 0;
  146. }
  147. if (sdaRect[i].right >= m_pShare->m_pasLocal->cpcCaps.screen.capsScreenWidth)
  148. {
  149. if (sdaRect[i].left >= m_pShare->m_pasLocal->cpcCaps.screen.capsScreenWidth)
  150. {
  151. //
  152. // This was scrolled off the physical screen by a desktop
  153. // scroll.
  154. //
  155. continue;
  156. }
  157. //
  158. // Partially off screen - just clip the right edge.
  159. //
  160. sdaRect[i].right = m_pShare->m_pasLocal->cpcCaps.screen.capsScreenWidth-1;
  161. }
  162. if (sdaRect[i].bottom >= m_pShare->m_pasLocal->cpcCaps.screen.capsScreenHeight)
  163. {
  164. if (sdaRect[i].top >= m_pShare->m_pasLocal->cpcCaps.screen.capsScreenHeight)
  165. {
  166. //
  167. // This was scrolled off the physical screen by a desktop
  168. // scroll.
  169. //
  170. continue;
  171. }
  172. //
  173. // Partially off screen - just clip the bottom edge.
  174. //
  175. sdaRect[i].bottom = m_pShare->m_pasLocal->cpcCaps.screen.capsScreenHeight-1;
  176. }
  177. //
  178. // If all of the previous rectangles have been successfully sent
  179. // then try to send this rectangle.
  180. // If a previous rectangle failed to be sent then we don't bother
  181. // trying to send the rest of the rectangles in the same batch -
  182. // they are added back into the SDA so that they will be sent later.
  183. //
  184. if (fBltOK)
  185. {
  186. fBltOK = SDGSplitBltToNetwork(&(sdaRect[i]), pcPackets);
  187. //
  188. // On the first blit failure we must transfer the posible
  189. // secondary transmit bounds over to the save area for next
  190. // time because down below we are going to add back any unsent
  191. // transmit rectangles to the primary SD area.
  192. //
  193. // Dont worry if this was a secondary transmit because these
  194. // bounds will be zero and will be overwritten when we copy
  195. // the current SDA region to the secondary area for our next
  196. // pass
  197. //
  198. if (!fBltOK && !secondaryTransmit)
  199. {
  200. TRACE_OUT(("Send failed so getting new secondary bounds"));
  201. BA_CopyBounds(m_asdgLossyRect, &m_sdgcLossy, TRUE);
  202. }
  203. }
  204. if (!fBltOK)
  205. {
  206. //
  207. // The blt to network failed - probably because a network
  208. // packet could not be allocated.
  209. // We add the rectangle back into the SDA so that we will try
  210. // to retransmit the area later.
  211. //
  212. TRACE_OUT(("Blt failed - add back rect {%d, %d, %d, %d}",
  213. sdaRect[i].left,
  214. sdaRect[i].top,
  215. sdaRect[i].right,
  216. sdaRect[i].bottom ));
  217. //
  218. // Add the rectangle into the bounds.
  219. //
  220. BA_AddRect(&(sdaRect[i]));
  221. backPressure = TRUE;
  222. }
  223. }
  224. //
  225. // If all went fine and we were sending primary transmit data then we
  226. // should just go back and send secondary data, using the bounds which
  227. // are located in the SD area at the moment. We can do this by copying
  228. // these secondary bounds to the save area, where they will be used at
  229. // the next schedule pass. It is a good idea to yield, because we may
  230. // be about to accumulate some more primary data.
  231. //
  232. if (fBltOK || secondaryTransmit)
  233. {
  234. TRACE_OUT(("Done with the primary bounds so getting pseudo-primary to secondary"));
  235. BA_CopyBounds(m_asdgLossyRect, &m_sdgcLossy, TRUE);
  236. }
  237. DC_EXIT_POINT:
  238. *pBackPressure = backPressure;
  239. DebugExitVOID(ASHost::SDG_SendScreenDataArea);
  240. }
  241. //
  242. // SDGSplitBltToNetwork(..)
  243. //
  244. // Sends the specified rectangle over the network.
  245. //
  246. // The Screen Data rects that we can send over the network are limited
  247. // to certain sizes (determined by the sizes of the Transfer Bitmaps).
  248. // If necessary, this function splits the rect into smaller sub-rectangles
  249. // for transmission.
  250. //
  251. // PARAMETERS:
  252. //
  253. // pRect - pointer to the rectangle to send.
  254. //
  255. // RETURNS:
  256. //
  257. // TRUE - rectangle was successfully sent. Supplied rectangle is updated
  258. // to be NULL.
  259. //
  260. // FALSE - rectangle was not completely sent. Supplied rectangle is
  261. // updated to contain the area that was NOT sent.
  262. //
  263. //
  264. BOOL ASHost::SDGSplitBltToNetwork(LPRECT pRect, UINT * pcPackets)
  265. {
  266. RECT smallRect;
  267. UINT maxHeight;
  268. BOOL rc;
  269. DebugEntry(ASHost::SDGSplitBltToNetwork);
  270. //
  271. // Loop processing strips.
  272. //
  273. while (pRect->top <= pRect->bottom)
  274. {
  275. smallRect = *pRect;
  276. //
  277. // Split the given rectangles into multiple smaller rects if
  278. // necessary. If it is wider than our 256 byte work bitmap then
  279. // switch to the mega 1024 byte one first.
  280. //
  281. // Note that the calculations don't work for VGA...
  282. maxHeight = max(8, m_usrSendingBPP);
  283. if ((smallRect.right-smallRect.left+1) > MEGA_X_SIZE)
  284. {
  285. maxHeight = MaxBitmapHeight(MEGA_WIDE_X_SIZE, maxHeight);
  286. }
  287. else
  288. {
  289. maxHeight = MaxBitmapHeight(MEGA_X_SIZE, maxHeight);
  290. }
  291. if ((unsigned)(smallRect.bottom - smallRect.top + 1) > maxHeight)
  292. {
  293. //
  294. // Split the rectangle to bring the height within the correct
  295. // range.
  296. //
  297. TRACE_OUT(( "Split Y size(%d) by maxHeight(%d)",
  298. smallRect.bottom - smallRect.top,
  299. maxHeight));
  300. smallRect.bottom = smallRect.top + maxHeight - 1;
  301. }
  302. while ((pRect->right - smallRect.left + 1) > 0)
  303. {
  304. if (!SDGSmallBltToNetwork(&smallRect))
  305. {
  306. TRACE_OUT(( "Small blt failed"));
  307. rc = FALSE;
  308. DC_QUIT;
  309. }
  310. else
  311. {
  312. ++(*pcPackets);
  313. }
  314. }
  315. //
  316. // Move to the next strip.
  317. //
  318. pRect->top = smallRect.bottom+1;
  319. }
  320. rc = TRUE;
  321. DC_EXIT_POINT:
  322. if (!rc)
  323. {
  324. //
  325. // A small blt failed. If we return FALSE then the supplied
  326. // rectangle will be added back into the SDA bounds so that it will
  327. // be retransmitted later.
  328. //
  329. // However, we want to avoid the situation where we have sent the
  330. // top left-hand corner of a rectangle and then add the remainder
  331. // back into the SDA bounds, because this could cause the original
  332. // bounding rectangle to be regenerated (because the bounds are
  333. // stored in a fixed number of rectangles).
  334. //
  335. // Therefore if we are not on the last strip of the rectangle then
  336. // we keep the current strip as a "pending" rectangle. The
  337. // supplied rectangle is adjusted to remove the whole of this
  338. // strip. Next time this function is called the pending rectangle
  339. // will be sent before anything else.
  340. //
  341. // If we are on the last strip (which will be the normal case -
  342. // there will usually only be one strip) then we update the
  343. // supplied rectangle to be the area that has not been sent and
  344. // return FALSE to indicate that it must be added back into the
  345. // SDA.
  346. //
  347. if (m_sdgRectIsPending)
  348. {
  349. ERROR_OUT(( "Unexpected small blt failure with pending rect"));
  350. }
  351. else
  352. {
  353. if (smallRect.bottom == pRect->bottom)
  354. {
  355. //
  356. // This is the last strip. Adjust the supplied rect to
  357. // contain the area that has not been sent.
  358. //
  359. pRect->top = smallRect.top;
  360. pRect->left = smallRect.left;
  361. }
  362. else
  363. {
  364. //
  365. // This is not the last strip Copy the remainder of the
  366. // current strip into the pending rect.
  367. //
  368. smallRect.right = pRect->right;
  369. m_sdgPendingRect = smallRect;
  370. m_sdgRectIsPending = TRUE;
  371. //
  372. // Adjust the supplied rectangle to contain the remaining
  373. // area that we have not sent and is not covered by the
  374. // pending rect.
  375. //
  376. pRect->top = smallRect.bottom+1;
  377. }
  378. }
  379. }
  380. DebugExitBOOL(ASHost::SDGSplitBltToNetwork, rc);
  381. return(rc);
  382. }
  383. //
  384. // FUNCTION: SDGSmallBltToNetwork
  385. //
  386. // DESCRIPTION:
  387. //
  388. // Sends the screen data within the specified rectangle across the network.
  389. //
  390. // PARAMETERS:
  391. //
  392. // pRect - pointer to the rectangle (in screen coords) to send as Screen
  393. // Data.
  394. //
  395. // RETURNS:
  396. //
  397. // TRUE - screen data successfully sent
  398. //
  399. // FALSE - screen data could not be sent. Caller should retry later.
  400. //
  401. //
  402. //
  403. // BOGUS BUGBUG LAURABU!
  404. // This function affects the results on the screen! If drawing happens
  405. // between the time we realize the palette then unrealize it, it will look
  406. // messed up. You can easily see this in Visio 4.5 when it is in the
  407. // foreground (in the background, NM controls the colors so no effect).
  408. //
  409. BOOL ASHost::SDGSmallBltToNetwork(LPRECT pRect)
  410. {
  411. BOOL fLossy = FALSE;
  412. HDC hdcDesktop;
  413. HBITMAP hBitmap = NULL;
  414. HBITMAP hOldBitmap = NULL;
  415. UINT width;
  416. UINT height;
  417. UINT fixedWidth;
  418. PSDPACKET pSDPacket = NULL;
  419. BITMAPINFO_ours bitmapInfo;
  420. UINT sizeBitmapPkt;
  421. UINT sizeBitmap;
  422. HPALETTE hpalOldDIB = NULL;
  423. HPALETTE hpalOldDesktop = NULL;
  424. HPALETTE hpalLocal;
  425. BOOL fPacketSent = FALSE;
  426. RECT smallRect;
  427. int useWidth;
  428. #ifdef _DEBUG
  429. UINT sentSize;
  430. #endif // _DEBUG
  431. DebugEntry(ASHost::SDGSmallBltToNetwork);
  432. hdcDesktop = GetDC(NULL);
  433. if (!hdcDesktop)
  434. {
  435. DC_QUIT;
  436. }
  437. width = pRect->right - pRect->left + 1;
  438. height = pRect->bottom - pRect->top + 1;
  439. //
  440. // Determine the width of the work buffer and the width that we
  441. // will be sending this time
  442. //
  443. fixedWidth = ((width + 15) / 16) * 16;
  444. useWidth = width;
  445. if (fixedWidth > MAX_X_SIZE)
  446. {
  447. if (fixedWidth > MEGA_X_SIZE)
  448. {
  449. fixedWidth = MEGA_WIDE_X_SIZE;
  450. if (width > MEGA_WIDE_X_SIZE)
  451. {
  452. useWidth = fixedWidth;
  453. }
  454. }
  455. else
  456. {
  457. fixedWidth = MEGA_X_SIZE;
  458. if (width > MEGA_X_SIZE)
  459. {
  460. useWidth = fixedWidth;
  461. }
  462. }
  463. }
  464. switch (fixedWidth)
  465. {
  466. case 16:
  467. hBitmap = m_pShare->m_usrBmp16;
  468. break;
  469. case 32:
  470. hBitmap = m_pShare->m_usrBmp32;
  471. break;
  472. case 48:
  473. hBitmap = m_pShare->m_usrBmp48;
  474. break;
  475. case 64:
  476. hBitmap = m_pShare->m_usrBmp64;
  477. break;
  478. case 80:
  479. hBitmap = m_pShare->m_usrBmp80;
  480. break;
  481. case 96:
  482. hBitmap = m_pShare->m_usrBmp96;
  483. break;
  484. case 112:
  485. hBitmap = m_pShare->m_usrBmp112;
  486. break;
  487. case 128:
  488. hBitmap = m_pShare->m_usrBmp128;
  489. break;
  490. case 256:
  491. hBitmap = m_pShare->m_usrBmp256;
  492. break;
  493. case 1024:
  494. hBitmap = m_pShare->m_usrBmp1024;
  495. break;
  496. default:
  497. ERROR_OUT(( "Invalid bitmap size(%d)", fixedWidth));
  498. break;
  499. }
  500. //
  501. // Initialise the BITMAPINFO_ours local structure header contents.
  502. // This structure will be used in the GetDIBits calls but only the
  503. // header part of the structure will be sent across the network, the
  504. // color table is sent via the Palette Manager.
  505. //
  506. m_pShare->USR_InitDIBitmapHeader((BITMAPINFOHEADER *)&bitmapInfo, m_usrSendingBPP);
  507. bitmapInfo.bmiHeader.biWidth = fixedWidth;
  508. bitmapInfo.bmiHeader.biHeight = height;
  509. //
  510. // Calculate the size of the bitmap packet in BYTES.
  511. //
  512. sizeBitmap = BYTES_IN_BITMAP(fixedWidth, height, bitmapInfo.bmiHeader.biBitCount);
  513. sizeBitmapPkt = sizeof(SDPACKET) + sizeBitmap - 1;
  514. ASSERT(sizeBitmapPkt <= TSHR_MAX_SEND_PKT);
  515. //
  516. // Allocate a packet for the bitmap data.
  517. //
  518. // *** NB. This assumes that this code is called ONLY when there ***
  519. // *** no unacknowledged bitmaps packets floating around the ***
  520. // *** network layer. This means, at the moment, if this code is ***
  521. // *** called due to anything other than a WM_TIMER ***
  522. // *** message we're in trouble. ***
  523. //
  524. //
  525. pSDPacket = (PSDPACKET)m_pShare->SC_AllocPkt(PROT_STR_UPDATES, g_s20BroadcastID,
  526. sizeBitmapPkt);
  527. if (!pSDPacket)
  528. {
  529. //
  530. // Failed to allocate the bitmap packet - clear up and exit adding
  531. // the rectangle back into the bounds.
  532. //
  533. TRACE_OUT(("Failed to alloc SDG packet, size %u", sizeBitmapPkt));
  534. DC_QUIT;
  535. }
  536. //
  537. // Since we are bltting off the screen, which by definition is using
  538. // the system palette, we place the system palette in both DC's (so
  539. // that the bitblt we are about to do will not do any color
  540. // conversion).
  541. //
  542. //
  543. // This will determine if the palette changed since the last time we
  544. // sent one to the remote.
  545. //
  546. if (m_usrSendingBPP <= 8)
  547. {
  548. hpalLocal = PM_GetLocalPalette();
  549. }
  550. hOldBitmap = SelectBitmap(m_usrWorkDC, hBitmap);
  551. if (m_usrSendingBPP <= 8)
  552. {
  553. hpalOldDIB = SelectPalette(m_usrWorkDC, hpalLocal, FALSE);
  554. RealizePalette(m_usrWorkDC);
  555. }
  556. //
  557. // We can now do a bitblt from the screen (hpDesktop) to memory and the
  558. // bits are untranslated.
  559. //
  560. // We then do a GetDIBits using the local palette which returns us the
  561. // bits at the correct bits per pel, (and with properly translated
  562. // colors) in order to transmit the data.
  563. //
  564. BitBlt(m_usrWorkDC, 0, 0, useWidth, height, hdcDesktop,
  565. pRect->left, pRect->top, SRCCOPY);
  566. //
  567. // Zero any unused space on the right side to aid compression.
  568. //
  569. if (width < fixedWidth)
  570. {
  571. PatBlt(m_usrWorkDC, width, 0, fixedWidth - width, height, BLACKNESS);
  572. }
  573. //
  574. // Do a GetDIBits into our global stash of memory for now. We will try
  575. // and compress this data into our packet after.
  576. //
  577. GetDIBits(m_usrWorkDC, hBitmap, 0, height, m_pShare->m_usrPBitmapBuffer,
  578. (PBITMAPINFO)&bitmapInfo, DIB_RGB_COLORS);
  579. //
  580. // Deselect the bitmap
  581. //
  582. SelectBitmap(m_usrWorkDC, hOldBitmap);
  583. //
  584. // Get the color table directly from the system since we can't trust
  585. // any palette realization color stuff via the messages at this stage.
  586. // We only need to do this on an 8bpp host sending 8bpp data.
  587. //
  588. if ((g_usrScreenBPP == 8) && (m_usrSendingBPP == 8))
  589. {
  590. PM_GetSystemPaletteEntries(bitmapInfo.bmiColors);
  591. }
  592. if (m_usrSendingBPP <= 8)
  593. {
  594. //
  595. // Whack old palettes back.
  596. //
  597. SelectPalette(m_usrWorkDC, hpalOldDIB, FALSE);
  598. }
  599. //
  600. // Fill in packet contents and send it.
  601. //
  602. pSDPacket->header.header.data.dataType = DT_UP;
  603. pSDPacket->header.updateType = UPD_SCREEN_DATA;
  604. //
  605. // Send Virtual desktop coordinates.
  606. //
  607. pSDPacket->position.left = (TSHR_INT16)(pRect->left);
  608. pSDPacket->position.right = (TSHR_INT16)(pRect->left + useWidth - 1);
  609. pSDPacket->position.top = (TSHR_INT16)(pRect->top);
  610. pSDPacket->position.bottom = (TSHR_INT16)(pRect->bottom);
  611. pSDPacket->realWidth = (TSHR_UINT16)fixedWidth;
  612. pSDPacket->realHeight = (TSHR_UINT16)height;
  613. pSDPacket->format = (TSHR_UINT16)m_usrSendingBPP;
  614. pSDPacket->compressed = FALSE;
  615. //
  616. // Compress the bitmap data
  617. //
  618. if (m_pShare->BC_CompressBitmap(m_pShare->m_usrPBitmapBuffer,
  619. pSDPacket->data,
  620. &sizeBitmap,
  621. fixedWidth,
  622. height,
  623. bitmapInfo.bmiHeader.biBitCount,
  624. &fLossy) )
  625. {
  626. //
  627. // We have successfully compressed the bitmap data into our packet
  628. // data buffer.
  629. //
  630. pSDPacket->compressed = TRUE;
  631. //
  632. // Write the updated size of the data into the header.
  633. //
  634. pSDPacket->dataSize = (TSHR_UINT16)sizeBitmap;
  635. //
  636. // Now update the size of the total data (including header)
  637. //
  638. sizeBitmapPkt = sizeof(SDPACKET) + sizeBitmap - 1;
  639. pSDPacket->header.header.dataLength = sizeBitmapPkt - sizeof(S20DATAPACKET)
  640. + sizeof(DATAPACKETHEADER);
  641. }
  642. else
  643. {
  644. //
  645. // The compression failed so just copy the uncompressed data from
  646. // the global buffer to the packet and send it uncompressed.
  647. //
  648. TRACE_OUT(("Failed to compress bitmap of size %d cx(%d) cy(%d) bpp(%d)",
  649. sizeBitmap, fixedWidth, height, bitmapInfo.bmiHeader.biBitCount));
  650. memcpy(pSDPacket->data,
  651. m_pShare->m_usrPBitmapBuffer,
  652. sizeBitmap );
  653. //
  654. // Write the size of the data into the header.
  655. //
  656. pSDPacket->dataSize = (TSHR_UINT16)sizeBitmap;
  657. }
  658. TRACE_OUT(("Sending %d bytes of screen data", sizeBitmap));
  659. if (m_pShare->m_scfViewSelf)
  660. m_pShare->UP_ReceivedPacket(m_pShare->m_pasLocal, &(pSDPacket->header.header));
  661. #ifdef _DEBUG
  662. sentSize =
  663. #endif // _DEBUG
  664. m_pShare->DCS_CompressAndSendPacket(PROT_STR_UPDATES, g_s20BroadcastID,
  665. &(pSDPacket->header.header), sizeBitmapPkt);
  666. TRACE_OUT(("SDG packet size: %08d, sent: %08d", sizeBitmapPkt, sentSize));
  667. //
  668. // We have sent the packet.
  669. //
  670. fPacketSent = TRUE;
  671. //
  672. // If it was lossy then we must accumulate the area for resend. We
  673. // accumulate it into the current SDA because we know this was cleared
  674. // before the transmission started. We will then move the accumulated
  675. // non-lossy rectangles to a save area before we return.
  676. //
  677. if (fLossy)
  678. {
  679. //
  680. // Convert the rect back into Virtual Desktop coords.
  681. //
  682. smallRect = *pRect;
  683. smallRect.right = smallRect.left + useWidth - 1;
  684. WARNING_OUT(( "Lossy send so add non-lossy area (%d,%d)(%d,%d)",
  685. smallRect.left,
  686. smallRect.top,
  687. smallRect.right,
  688. smallRect.bottom ));
  689. //
  690. // Add the rectangle into the bounds.
  691. //
  692. BA_AddRect(&(smallRect));
  693. }
  694. //
  695. // Now we modify the supplied rectangle to exclude the area just sent
  696. //
  697. pRect->left = pRect->left + useWidth;
  698. TRACE_OUT(("Rect now {%d, %d, %d, %d}", pRect->left, pRect->top,
  699. pRect->right,
  700. pRect->bottom ));
  701. DC_EXIT_POINT:
  702. if (hdcDesktop != NULL)
  703. {
  704. ReleaseDC(NULL, hdcDesktop);
  705. }
  706. DebugExitBOOL(ASHost::SDGSmallBltToNetwork, fPacketSent);
  707. return(fPacketSent);
  708. }