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.

784 lines
21 KiB

  1. #include "precomp.h"
  2. //
  3. // SSI.C
  4. // Save Screenbits Interceptor, display driver side
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. //
  9. // SSI_DDProcessRequest - see ssi.h
  10. //
  11. BOOL SSI_DDProcessRequest
  12. (
  13. UINT fnEscape,
  14. LPOSI_ESCAPE_HEADER pRequest,
  15. DWORD cbRequest
  16. )
  17. {
  18. BOOL rc;
  19. DebugEntry(SSI_DDProcessRequest);
  20. switch (fnEscape)
  21. {
  22. case SSI_ESC_RESET_LEVEL:
  23. {
  24. if (cbRequest != sizeof(SSI_RESET_LEVEL))
  25. {
  26. ERROR_OUT(("SSI_DDProcessRequest: Invalid size %d for SSI_ESC_RESET_LEVEL",
  27. cbRequest));
  28. rc = FALSE;
  29. DC_QUIT;
  30. }
  31. SSIResetSaveScreenBitmap();
  32. rc = TRUE;
  33. }
  34. break;
  35. case SSI_ESC_NEW_CAPABILITIES:
  36. {
  37. if (cbRequest != sizeof(SSI_NEW_CAPABILITIES))
  38. {
  39. ERROR_OUT(("SSI_DDProcessRequest: Invalid size %d for SSI_ESC_NEW_CAPABILITIES",
  40. cbRequest));
  41. rc = FALSE;
  42. DC_QUIT;
  43. }
  44. SSISetNewCapabilities((LPSSI_NEW_CAPABILITIES)pRequest);
  45. rc = TRUE;
  46. }
  47. break;
  48. default:
  49. {
  50. ERROR_OUT(("Unrecognized SSI_ escape"));
  51. rc = FALSE;
  52. }
  53. break;
  54. }
  55. DC_EXIT_POINT:
  56. DebugExitBOOL(SSI_DDProcessRequest, rc);
  57. return(rc);
  58. }
  59. //
  60. // SSI_SaveScreenBitmap()
  61. //
  62. // see ssi.h for description.
  63. //
  64. BOOL SSI_SaveScreenBitmap(LPRECT lpRect, UINT wCommand)
  65. {
  66. BOOL rc;
  67. DebugEntry(SSI_SaveScreenBitmap);
  68. //
  69. // Decide whether we can transmit this particular SaveBitmap command as
  70. // an order.
  71. //
  72. switch (wCommand)
  73. {
  74. case ONBOARD_SAVE:
  75. {
  76. //
  77. // Save the bits.
  78. //
  79. rc = SSISaveBits(lpRect);
  80. }
  81. break;
  82. case ONBOARD_RESTORE:
  83. {
  84. //
  85. // Restore the bits.
  86. //
  87. rc = SSIRestoreBits(lpRect);
  88. }
  89. break;
  90. case ONBOARD_DISCARD:
  91. {
  92. //
  93. // Discard the saved bits.
  94. //
  95. rc = SSIDiscardBits(lpRect);
  96. }
  97. break;
  98. default:
  99. {
  100. ERROR_OUT(( "Unexpected wCommand(%d)", wCommand));
  101. rc = FALSE;
  102. }
  103. }
  104. if (g_ssiLocalSSBState.saveLevel == 0)
  105. {
  106. ASSERT(g_ssiRemoteSSBState.pelsSaved == 0);
  107. }
  108. DebugExitBOOL(SSI_SaveScreenBitmap, rc);
  109. return(rc);
  110. }
  111. //
  112. // FUNCTION: SSIResetSaveScreenBitmap.
  113. //
  114. // DESCRIPTION:
  115. //
  116. // Resets the SaveScreenBitmap state.
  117. //
  118. // PARAMETERS: None.
  119. //
  120. // RETURNS: Nothing.
  121. //
  122. //
  123. void SSIResetSaveScreenBitmap(void)
  124. {
  125. DebugEntry(SSIResetSaveScreenBitmap);
  126. //
  127. // Discard all currently saved bits.
  128. //
  129. g_ssiLocalSSBState.saveLevel = 0;
  130. //
  131. // Reset the number of remote pels saved.
  132. //
  133. g_ssiRemoteSSBState.pelsSaved = 0;
  134. DebugExitVOID(SSIResetSaveScreenBitmap);
  135. }
  136. //
  137. // FUNCTION: SSISendSaveBitmapOrder
  138. //
  139. // DESCRIPTION:
  140. //
  141. // Attempts to send a SaveBitmap order matching the supplied parameters.
  142. //
  143. //
  144. // PARAMETERS:
  145. //
  146. // lpRect - pointer to the rectangle coords (EXCLUSIVE screen coords)
  147. //
  148. // RETURNS:
  149. //
  150. // TRUE if order successfully sent FALSE if order not sent
  151. //
  152. //
  153. BOOL SSISendSaveBitmapOrder
  154. (
  155. LPRECT lpRect,
  156. UINT wCommand
  157. )
  158. {
  159. DWORD cRemotePelsRequired;
  160. LPSAVEBITMAP_ORDER pSaveBitmapOrder;
  161. LPINT_ORDER pOrder;
  162. BOOL rc = FALSE;
  163. DebugEntry(SSISendSaveBitmapOrder);
  164. //
  165. // If the SaveBitmap order is not supported then return FALSE
  166. // immediately.
  167. //
  168. if (!OE_SendAsOrder(ORD_SAVEBITMAP))
  169. {
  170. WARNING_OUT(("SSISendSaveBitmapOrder failing; save bits orders not supported"));
  171. DC_QUIT;
  172. }
  173. switch (wCommand)
  174. {
  175. case ONBOARD_DISCARD:
  176. //
  177. // We don't transmit DISCARD orders, there's no need since
  178. // saves/restores are paired.
  179. //
  180. g_ssiRemoteSSBState.pelsSaved -=
  181. CURRENT_LOCAL_SSB_STATE.remotePelsRequired;
  182. rc = TRUE;
  183. DC_QUIT;
  184. case ONBOARD_SAVE:
  185. //
  186. // Calculate the number of pels required in the remote Save
  187. // Bitmap to handle this rectangle.
  188. //
  189. cRemotePelsRequired = SSIRemotePelsRequired(lpRect);
  190. //
  191. // If there aren't enough pels in the remote Save Bitmap to
  192. // handle this rectangle then return immediately.
  193. //
  194. if ((g_ssiRemoteSSBState.pelsSaved + cRemotePelsRequired) >
  195. g_ssiSaveBitmapSize)
  196. {
  197. TRACE_OUT(("SSISendSaveBitmapOrder: ONBOARD_SAVE is failing; not enough space for %08d pels",
  198. cRemotePelsRequired));
  199. DC_QUIT;
  200. }
  201. //
  202. // Allocate memory for the order.
  203. //
  204. pOrder = OA_DDAllocOrderMem(sizeof(SAVEBITMAP_ORDER), 0);
  205. if (!pOrder)
  206. DC_QUIT;
  207. //
  208. // Store the drawing order data.
  209. //
  210. pSaveBitmapOrder = (LPSAVEBITMAP_ORDER)pOrder->abOrderData;
  211. pSaveBitmapOrder->type = LOWORD(ORD_SAVEBITMAP);
  212. pSaveBitmapOrder->Operation = SV_SAVEBITS;
  213. //
  214. // SAVEBITS is a BLOCKER order i.e. it prevents any earlier
  215. // orders from being spoilt by subsequent orders or Screen
  216. // Data.
  217. //
  218. pOrder->OrderHeader.Common.fOrderFlags = OF_BLOCKER;
  219. //
  220. // Copy the rect, converting to inclusive Virtual Desktop
  221. // coords.
  222. //
  223. pSaveBitmapOrder->nLeftRect = lpRect->left;
  224. pSaveBitmapOrder->nTopRect = lpRect->top;
  225. pSaveBitmapOrder->nRightRect = lpRect->right - 1;
  226. pSaveBitmapOrder->nBottomRect = lpRect->bottom - 1;
  227. pSaveBitmapOrder->SavedBitmapPosition = g_ssiRemoteSSBState.pelsSaved;
  228. //
  229. // Store the relevant details in the current entry of the
  230. // local SSB structure.
  231. //
  232. CURRENT_LOCAL_SSB_STATE.remoteSavedPosition =
  233. pSaveBitmapOrder->SavedBitmapPosition;
  234. CURRENT_LOCAL_SSB_STATE.remotePelsRequired = cRemotePelsRequired;
  235. //
  236. // Update the count of remote pels saved.
  237. //
  238. g_ssiRemoteSSBState.pelsSaved += cRemotePelsRequired;
  239. //
  240. // The operation rectangle is NULL.
  241. //
  242. pOrder->OrderHeader.Common.rcsDst.left = 1;
  243. pOrder->OrderHeader.Common.rcsDst.right = 0;
  244. pOrder->OrderHeader.Common.rcsDst.top = 1;
  245. pOrder->OrderHeader.Common.rcsDst.bottom = 0;
  246. break;
  247. case ONBOARD_RESTORE:
  248. //
  249. // Update the remote pel count first. Even if we fail to send
  250. // the order we want to free up the remote pels.
  251. //
  252. g_ssiRemoteSSBState.pelsSaved -=
  253. CURRENT_LOCAL_SSB_STATE.remotePelsRequired;
  254. //
  255. // Allocate memory for the order.
  256. //
  257. pOrder = OA_DDAllocOrderMem(sizeof(SAVEBITMAP_ORDER), 0);
  258. if (!pOrder)
  259. DC_QUIT;
  260. //
  261. // Store the drawing order data.
  262. //
  263. pSaveBitmapOrder = (LPSAVEBITMAP_ORDER)pOrder->abOrderData;
  264. pSaveBitmapOrder->type = LOWORD(ORD_SAVEBITMAP);
  265. pSaveBitmapOrder->Operation = SV_RESTOREBITS;
  266. //
  267. // The order can spoil others (it is opaque).
  268. // It is not SPOILABLE because we want to keep the remote
  269. // save level in a consistent state.
  270. //
  271. pOrder->OrderHeader.Common.fOrderFlags = OF_SPOILER;
  272. //
  273. // Copy the rect, converting to inclusive Virtual Desktop
  274. // coords.
  275. //
  276. pSaveBitmapOrder->nLeftRect = lpRect->left;
  277. pSaveBitmapOrder->nTopRect = lpRect->top;
  278. pSaveBitmapOrder->nRightRect = lpRect->right - 1;
  279. pSaveBitmapOrder->nBottomRect = lpRect->bottom - 1;
  280. pSaveBitmapOrder->SavedBitmapPosition =
  281. CURRENT_LOCAL_SSB_STATE.remoteSavedPosition;
  282. //
  283. // The operation rectangle is also the bounding rectangle of
  284. // the order.
  285. //
  286. pOrder->OrderHeader.Common.rcsDst.left =
  287. (TSHR_INT16)pSaveBitmapOrder->nLeftRect;
  288. pOrder->OrderHeader.Common.rcsDst.right =
  289. (TSHR_INT16)pSaveBitmapOrder->nRightRect;
  290. pOrder->OrderHeader.Common.rcsDst.top =
  291. (TSHR_INT16)pSaveBitmapOrder->nTopRect;
  292. pOrder->OrderHeader.Common.rcsDst.bottom =
  293. (TSHR_INT16)pSaveBitmapOrder->nBottomRect;
  294. break;
  295. default:
  296. ERROR_OUT(( "Unexpected wCommand(%d)", wCommand));
  297. DC_QUIT;
  298. }
  299. TRACE_OUT(( "SaveBitmap op %d pos %ld rect %d %d %d %d",
  300. pSaveBitmapOrder->Operation, pSaveBitmapOrder->SavedBitmapPosition,
  301. pSaveBitmapOrder->nLeftRect, pSaveBitmapOrder->nTopRect,
  302. pSaveBitmapOrder->nRightRect, pSaveBitmapOrder->nBottomRect ));
  303. //
  304. // Add the order to the order list.
  305. // We deliberately do not call OA_DDClipAndAddOrder() because the
  306. // SaveBitmap order is never clipped.
  307. //
  308. OA_DDAddOrder(pOrder, NULL);
  309. rc = TRUE;
  310. DC_EXIT_POINT:
  311. DebugExitBOOL(SSISendSaveBitmapOrder, rc);
  312. return(rc);
  313. }
  314. //
  315. // SSISaveBits()
  316. //
  317. // This attemps to save the SPB into our stack. If we can't save it, no
  318. // big deal--we'll fail the restore and that info will go as screen data.
  319. //
  320. // NOTE THAT THIS ROUTINE IS IN OPPOSITE FROM WIN95. In Win95, we always
  321. // return FALSE from save so that USER always uses bitmaps for save bits and
  322. // we can track them. In NT we always return TRUE from save because we
  323. // can't track USER bitmaps.
  324. //
  325. // ALWAYS RETURN TRUE FROM THIS FUNCTION
  326. //
  327. // If FALSE is returned on a Display Driver SaveBits operation then Windows
  328. // (USER) simulates the SaveBits call using BitBlts and DOES NOT make a
  329. // corresponding RestoreBits call. This makes it impossible for us to
  330. // correctly track the drawing operations (the restore operation is a
  331. // bitblt on a task that may not have been tracked) - and we can end up
  332. // with unrestored areas on the remote.
  333. //
  334. // Therefore this routine should always return TRUE (apart from when
  335. // something very very unexpected happens). In the cases where we haven't
  336. // saved the data we simply note the fact by storing ST_FAILED_TO_SAVE in
  337. // our local SSB state structure. Because we return TRUE, we get a
  338. // RestoreBits call and, seeing that the Save failed (by looking in the
  339. // local SSB state structure), we _then_ return FALSE to indicate that the
  340. // Restore failed which causes Windows to invalidate and repaint the
  341. // affected area.
  342. //
  343. //
  344. BOOL SSISaveBits(LPRECT lpRect)
  345. {
  346. DebugEntry(SSISaveBits);
  347. //
  348. // We should never have unbalanced save/restore operations
  349. //
  350. ASSERT(g_ssiLocalSSBState.saveLevel >= 0);
  351. //
  352. // Are we out of space?
  353. //
  354. if (g_ssiLocalSSBState.saveLevel >= SSB_MAX_SAVE_LEVEL)
  355. {
  356. TRACE_OUT(( "saveLevel(%d) exceeds maximum", g_ssiLocalSSBState.saveLevel));
  357. DC_QUIT;
  358. }
  359. //
  360. // If the rectangle to be saved intersects the current SDA then we will
  361. // have to force a repaint on the restore. This is because orders are
  362. // always sent before Screen Data, so if we sent a SAVEBITS order at
  363. // this point, we would not save the intersecting Screen Data.
  364. //
  365. // Otherwise mark the bits as saved (we don't have to do anything since
  366. // we are a chained display driver).
  367. //
  368. if (OE_RectIntersectsSDA(lpRect))
  369. {
  370. CURRENT_LOCAL_SSB_STATE.saveType = ST_FAILED_TO_SAVE;
  371. }
  372. else
  373. {
  374. CURRENT_LOCAL_SSB_STATE.saveType = ST_SAVED_BY_DISPLAY_DRIVER;
  375. }
  376. //
  377. // Store the rectangle saved
  378. //
  379. CURRENT_LOCAL_SSB_STATE.hbmpSave = NULL;
  380. CURRENT_LOCAL_SSB_STATE.rect = *lpRect;
  381. //
  382. // If the bits were successfully saved then we can try to send the
  383. // SaveBits command as an order.
  384. //
  385. if (CURRENT_LOCAL_SSB_STATE.saveType != ST_FAILED_TO_SAVE)
  386. {
  387. CURRENT_LOCAL_SSB_STATE.fSavedRemotely =
  388. SSISendSaveBitmapOrder(lpRect, ONBOARD_SAVE);
  389. }
  390. else
  391. {
  392. //
  393. // We didn't manage to save it. No point in trying to save the
  394. // bitmap remotely.
  395. //
  396. TRACE_OUT(( "Keep track of failed save for restore later"));
  397. CURRENT_LOCAL_SSB_STATE.fSavedRemotely = FALSE;
  398. }
  399. //
  400. // Update the save level
  401. // NOTE this now points to the NEXT free slot
  402. //
  403. g_ssiLocalSSBState.saveLevel++;
  404. TRACE_OUT(("SSISaveBits:"));
  405. TRACE_OUT((" saveLevel is %d", g_ssiLocalSSBState.saveLevel));
  406. TRACE_OUT((" pelsSaved is %d", g_ssiRemoteSSBState.pelsSaved));
  407. DC_EXIT_POINT:
  408. DebugExitBOOL(SSISaveBits, TRUE);
  409. return(TRUE);
  410. }
  411. //
  412. // FUNCTION: SSIFindSlotAndDiscardAbove
  413. //
  414. // DESCRIPTION:
  415. //
  416. // Finds the top slot in the SSB stack which matches lpRect and updates
  417. // g_ssiLocalSSBState.saveLevel to index it.
  418. //
  419. // PARAMETERS:
  420. //
  421. // lpRect - the SSB rectangle
  422. //
  423. // RETURNS: TRUE if a match was found, FALSE otherwise
  424. //
  425. //
  426. BOOL SSIFindSlotAndDiscardAbove(LPRECT lpRect)
  427. {
  428. int i;
  429. int iNewSaveLevel;
  430. BOOL rc = FALSE;
  431. DebugEntry(SSIFindSlotAndDiscardAbove);
  432. //
  433. // Look for this SPB. If we find it, then discard the entries after
  434. // it in our stack.
  435. //
  436. iNewSaveLevel = g_ssiLocalSSBState.saveLevel;
  437. //
  438. // Find the bits we are trying to restore
  439. //
  440. for (i = 0; i < g_ssiLocalSSBState.saveLevel; i++)
  441. {
  442. if (rc)
  443. {
  444. //
  445. // We found this SPB, so we are discarding all entries after
  446. // it in the stack. Subtract the saved pixels count for this
  447. // dude.
  448. //
  449. g_ssiRemoteSSBState.pelsSaved -=
  450. g_ssiLocalSSBState.saveState[i].remotePelsRequired;
  451. }
  452. else if ((g_ssiLocalSSBState.saveState[i].rect.left == lpRect->left) &&
  453. (g_ssiLocalSSBState.saveState[i].rect.right == lpRect->right) &&
  454. (g_ssiLocalSSBState.saveState[i].rect.top == lpRect->top) &&
  455. (g_ssiLocalSSBState.saveState[i].rect.bottom == lpRect->bottom) )
  456. {
  457. //
  458. // Found the one we were looking for
  459. //
  460. TRACE_OUT(("Found SPB at slot %d", i));
  461. iNewSaveLevel = i;
  462. rc = TRUE;
  463. }
  464. }
  465. g_ssiLocalSSBState.saveLevel = iNewSaveLevel;
  466. TRACE_OUT(("SSIFindSlotAndDiscardAbove:"));
  467. TRACE_OUT((" saveLevel is %d", iNewSaveLevel));
  468. TRACE_OUT((" pelsSaved is %d", g_ssiRemoteSSBState.pelsSaved));
  469. DebugExitBOOL(SSIFindSlotAndDiscardAbove, rc);
  470. return(rc);
  471. }
  472. //
  473. // FUNCTION: SSIRestoreBits
  474. //
  475. // DESCRIPTION:
  476. //
  477. // Attempts to restore the specified screen rectangle bits (using the same
  478. // scheme as we previously used to save the bits: either the Display Driver
  479. // our SaveBitmap simulation).
  480. //
  481. // If the bits were saved remotely then a RestoreBits order is sent to
  482. // restore the remote bits.
  483. //
  484. // PARAMETERS:
  485. //
  486. // lpRect - pointer to the rectangle coords (EXCLUSIVE screen coords).
  487. //
  488. // RETURNS:
  489. //
  490. // TRUE or FALSE - this will be returned to Windows as the return code of
  491. // the SaveScreenBitmap call.
  492. //
  493. // Note: if FALSE is returned on a RestoreBits operation then Windows will
  494. // restore the screen by invalidating the area to be restored.
  495. //
  496. //
  497. BOOL SSIRestoreBits(LPRECT lpRect)
  498. {
  499. BOOL rc = FALSE;
  500. DebugEntry(SSIRestoreBits);
  501. ASSERT(g_ssiLocalSSBState.saveLevel >= 0);
  502. //
  503. // Can we find the SPB?
  504. //
  505. if (SSIFindSlotAndDiscardAbove(lpRect))
  506. {
  507. if (CURRENT_LOCAL_SSB_STATE.fSavedRemotely)
  508. {
  509. //
  510. // The bits were saved remotely, so send and order.
  511. //
  512. rc = SSISendSaveBitmapOrder(lpRect, ONBOARD_RESTORE);
  513. }
  514. else
  515. {
  516. //
  517. // We failed to save the bitmap remotely originally, so now
  518. // we need to return FALSE so that BitBlt() will accumulate
  519. // screen data in the area.
  520. //
  521. TRACE_OUT(( "No remote save, force repaint"));
  522. }
  523. if (g_ssiLocalSSBState.saveLevel == 0)
  524. {
  525. g_ssiRemoteSSBState.pelsSaved = 0;
  526. }
  527. TRACE_OUT(("SSIRestoreBits:"));
  528. TRACE_OUT((" saveLevel is %d", g_ssiLocalSSBState.saveLevel));
  529. TRACE_OUT((" pelsSaved is %d", g_ssiRemoteSSBState.pelsSaved));
  530. }
  531. DebugExitBOOL(SSIRestoreBits, rc);
  532. return(rc);
  533. }
  534. //
  535. // FUNCTION: SSIDiscardBits
  536. //
  537. // DESCRIPTION:
  538. //
  539. // Attempts to discard the specified screen rectangle bits (using the same
  540. // scheme as we previously used to save the bits: either the Display Driver
  541. // our SaveBitmap simulation).
  542. //
  543. // PARAMETERS:
  544. //
  545. // lpRect - pointer to the rectangle coords (EXCLUSIVE screen coords).
  546. //
  547. // RETURNS:
  548. //
  549. // TRUE or FALSE - this will be returned to Windows as the return code of
  550. // the SaveScreenBitmap call.
  551. //
  552. //
  553. BOOL SSIDiscardBits(LPRECT lpRect)
  554. {
  555. BOOL rc = TRUE;
  556. DebugEntry(SSIDiscardBits);
  557. //
  558. // SS_FREE (discard) isn't called with a rectangle. It is used to
  559. // discard the most recent save.
  560. //
  561. if (g_ssiLocalSSBState.saveLevel > 0)
  562. {
  563. --g_ssiLocalSSBState.saveLevel;
  564. //
  565. // The save level is now the index to this entry. Since we are
  566. // about to free it, this will be the place the next SAVE goes
  567. // into.
  568. //
  569. //
  570. // If the bits were saved remotely then send a DISCARDBITS order.
  571. //
  572. if (CURRENT_LOCAL_SSB_STATE.fSavedRemotely)
  573. {
  574. //
  575. // NOTE that SSISendSaveBitmapOrder() for DISCARD doesn't have
  576. // a side effect, we can just pass in the address of the rect
  577. // of the SPB we stored.
  578. //
  579. SSISendSaveBitmapOrder(lpRect, ONBOARD_DISCARD);
  580. }
  581. if (g_ssiLocalSSBState.saveLevel == 0)
  582. {
  583. g_ssiRemoteSSBState.pelsSaved = 0;
  584. }
  585. TRACE_OUT(("SSIDiscardBits:"));
  586. TRACE_OUT((" saveLevel is %d", g_ssiLocalSSBState.saveLevel));
  587. TRACE_OUT((" pelsSaved is %d", g_ssiRemoteSSBState.pelsSaved));
  588. }
  589. DebugExitBOOL(SSIDiscardBits, rc);
  590. return(rc);
  591. }
  592. //
  593. // FUNCTION: SSIRemotePelsRequired
  594. //
  595. // DESCRIPTION:
  596. //
  597. // Returns the number of remote pels required to store the supplied
  598. // rectangle, taking account of the Save Bitmap granularity.
  599. //
  600. // PARAMETERS:
  601. //
  602. // lpRect - pointer to rectangle position in EXCLUSIVE screen coordinates.
  603. //
  604. // RETURNS: Number of remote pels required.
  605. //
  606. //
  607. DWORD SSIRemotePelsRequired(LPRECT lpRect)
  608. {
  609. UINT rectWidth = 0;
  610. UINT rectHeight = 0;
  611. UINT xGranularity = 1;
  612. UINT yGranularity = 1;
  613. DWORD rc;
  614. DebugEntry(SSIRemotePelsRequired);
  615. ASSERT(lpRect != NULL);
  616. //
  617. // Calculate the supplied rectangle size (it is in EXCLUSIVE coords).
  618. //
  619. rectWidth = lpRect->right - lpRect->left;
  620. rectHeight = lpRect->bottom - lpRect->top;
  621. xGranularity = g_ssiLocalSSBState.xGranularity;
  622. yGranularity = g_ssiLocalSSBState.yGranularity;
  623. rc =
  624. ((DWORD)(rectWidth + (xGranularity-1))/xGranularity * xGranularity) *
  625. ((DWORD)(rectHeight + (yGranularity-1))/yGranularity * yGranularity);
  626. //
  627. // Return the pels required in the remote SaveBits bitmap to handle
  628. // this rectangle, taking account of its granularity.
  629. //
  630. DebugExitDWORD(SSIRemotePelsRequired, rc);
  631. return(rc);
  632. }
  633. //
  634. // FUNCTION: SSISetNewCapabilities
  635. //
  636. // DESCRIPTION:
  637. //
  638. // Set the new SSI related capabilities
  639. //
  640. // RETURNS:
  641. //
  642. // NONE
  643. //
  644. // PARAMETERS:
  645. //
  646. // pDataIn - pointer to the input buffer
  647. //
  648. //
  649. void SSISetNewCapabilities(LPSSI_NEW_CAPABILITIES pCapabilities)
  650. {
  651. DebugEntry(SSISetNewCapabilities);
  652. //
  653. // Copy the data from the Share Core.
  654. //
  655. g_ssiSaveBitmapSize = pCapabilities->sendSaveBitmapSize;
  656. g_ssiLocalSSBState.xGranularity = pCapabilities->xGranularity;
  657. g_ssiLocalSSBState.yGranularity = pCapabilities->yGranularity;
  658. TRACE_OUT(( "SSI caps: Size %ld X gran %hd Y gran %hd",
  659. g_ssiSaveBitmapSize,
  660. g_ssiLocalSSBState.xGranularity,
  661. g_ssiLocalSSBState.yGranularity));
  662. DebugExitVOID(SSISetNewCapabilities);
  663. }