WindowsXP/Source/XPSP1/NT/enduser/netmeeting/as/cpi32/ssi.cpp
2024-08-03 16:30:48 +02:00

451 lines
13 KiB
C++

#include "precomp.h"
//
// SSI.CPP
// Save Screenbits Interceptor
//
// Copyright(c) Microsoft 1997-
//
#define MLZ_FILE_ZONE ZONE_CORE
//
// SSI_HostStarting()
//
// Called when we start to host, figures out the max save bitmap bits size
// etc.
//
BOOL ASHost::SSI_HostStarting(void)
{
DebugEntry(ASHost::SSI_HostStarting);
m_pShare->SSI_RecalcCaps(TRUE);
DebugExitBOOL(ASHost::SSI_HostStarting, TRUE);
return(TRUE);
}
//
// SSI_ViewStarted()
//
// Called when someone we are viewing has started to host. Creates save bits
// bitmap for them.
//
BOOL ASShare::SSI_ViewStarting(ASPerson * pasPerson)
{
BOOL rc = FALSE;
HDC hdcScreen = NULL;
DebugEntry(ASShare::SSI_ViewStarting);
ValidateView(pasPerson);
//
// ASSERT that this persons' variables are clear.
//
ASSERT(pasPerson->m_pView->m_ssiBitmapHeight == 0);
ASSERT(pasPerson->m_pView->m_ssiBitmap == NULL);
ASSERT(pasPerson->m_pView->m_ssiOldBitmap == NULL);
//
// Does this person support savebits?
//
if (!pasPerson->cpcCaps.orders.capsSendSaveBitmapSize)
{
// No receive SSI capability, bail out now.
rc = TRUE;
DC_QUIT;
}
//
// Store the height of this host's bitmap.
//
pasPerson->m_pView->m_ssiBitmapHeight = (int)
(pasPerson->cpcCaps.orders.capsSendSaveBitmapSize / TSHR_SSI_BITMAP_WIDTH);
//
// If the calculated bitmap size is not exactly divisible by the bitmap
// width increase the bitmap height to fit in the partial row.
//
if (pasPerson->cpcCaps.orders.capsSendSaveBitmapSize % TSHR_SSI_BITMAP_WIDTH)
{
pasPerson->m_pView->m_ssiBitmapHeight += pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity;
}
TRACE_OUT(("Person [%d] SSI Bitmap height %d",
pasPerson->mcsID,
pasPerson->m_pView->m_ssiBitmapHeight));
//
// Create this host's save screen bitmap.
//
hdcScreen = GetDC(NULL);
if (hdcScreen == NULL)
{
ERROR_OUT(( "Failed to get screen surface"));
DC_QUIT;
}
//
// Create the save screen bitmap DC.
//
ASSERT(pasPerson->m_pView->m_ssiDC == NULL);
pasPerson->m_pView->m_ssiDC = CreateCompatibleDC(hdcScreen);
if (!pasPerson->m_pView->m_ssiDC)
{
ERROR_OUT(("Failed to create SSI DC"));
DC_QUIT;
}
//
// Create the save screen bitmap.
//
ASSERT(pasPerson->m_pView->m_ssiBitmap == NULL);
pasPerson->m_pView->m_ssiBitmap = CreateCompatibleBitmap(hdcScreen,
TSHR_SSI_BITMAP_WIDTH, pasPerson->m_pView->m_ssiBitmapHeight);
if (!pasPerson->m_pView->m_ssiBitmap)
{
ERROR_OUT(("SSI_ViewStarting: can't create bitmap for person %x",
pasPerson->mcsID));
DC_QUIT;
}
//
// Select the save screen bitmap into the DC
//
ASSERT(pasPerson->m_pView->m_ssiOldBitmap == NULL);
pasPerson->m_pView->m_ssiOldBitmap = SelectBitmap(pasPerson->m_pView->m_ssiDC,
pasPerson->m_pView->m_ssiBitmap);
rc = TRUE;
DC_EXIT_POINT:
if (hdcScreen != NULL)
{
ReleaseDC(NULL, hdcScreen);
}
DebugExitBOOL(ASShare::SSI_ViewStarting, rc);
return(rc);
}
//
// SSI_ViewEnded()
//
// Called when someone we are viewing has stopped hosting, so we can clean
// up our view data for them.
//
void ASShare::SSI_ViewEnded(ASPerson * pasPerson)
{
DebugEntry(ASShare::SSI_ViewEnded);
ValidateView(pasPerson);
//
// Deselect the save screen bitmap if there is one
//
if (pasPerson->m_pView->m_ssiOldBitmap != NULL)
{
SelectBitmap(pasPerson->m_pView->m_ssiDC, pasPerson->m_pView->m_ssiOldBitmap);
pasPerson->m_pView->m_ssiOldBitmap = NULL;
}
//
// Delete the save screen bitmap
//
if (pasPerson->m_pView->m_ssiBitmap != NULL)
{
DeleteBitmap(pasPerson->m_pView->m_ssiBitmap);
pasPerson->m_pView->m_ssiBitmap = NULL;
}
//
// Delete the save screen DC
//
if (pasPerson->m_pView->m_ssiDC != NULL)
{
DeleteDC(pasPerson->m_pView->m_ssiDC);
pasPerson->m_pView->m_ssiDC = NULL;
}
DebugExitVOID(ASShare::SSI_ViewEnded);
}
//
// SSI_SyncOutgoing()
// Called when NEW (3.0) dude starts to share, a share is created, or
// someone new joins the share.
// Resets save state for OUTGOING save/restore orders.
//
void ASHost::SSI_SyncOutgoing(void)
{
OSI_ESCAPE_HEADER request;
DebugEntry(ASHost::SSI_SyncOutgoing);
//
// Discard any saved bitmaps. This ensures that the subsequent
// datastream will not refer to any previously sent data.
//
//
// Make sure the display driver resets the save level. Note we don't
// really care what happens in the display driver, so don't bother with
// a special request block - use a standard request header.
//
OSI_FunctionRequest(SSI_ESC_RESET_LEVEL, &request, sizeof(request));
DebugExitVOID(ASHost::SSI_SyncOutgoing);
}
//
// FUNCTION: SSI_SaveBitmap
//
// DESCRIPTION:
// Replays a SaveBitmap order by saving or restoring a specified area of
// the user's desktop bitmap.
//
//
void ASShare::SSI_SaveBitmap
(
ASPerson * pasPerson,
LPSAVEBITMAP_ORDER pSaveBitmap
)
{
RECT screenBitmapRect;
RECT saveBitmapRect;
int xSaveBitmap;
int ySaveBitmap;
int xScreenBitmap;
int yScreenBitmap;
int cxTile;
int cyTile;
DebugEntry(ASShare::SSI_SaveBitmap);
ValidateView(pasPerson);
if ((pSaveBitmap->Operation != SV_SAVEBITS) &&
(pSaveBitmap->Operation != SV_RESTOREBITS))
{
ERROR_OUT(("SSI_SaveBitmap: unrecognized SV_ value %d",
pSaveBitmap->Operation));
DC_QUIT;
}
//
// Calculate the (x,y) start position from the pel start position
// given in the order.
//
ySaveBitmap = (pSaveBitmap->SavedBitmapPosition /
(TSHR_SSI_BITMAP_WIDTH *
(UINT)pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity)) *
pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity;
xSaveBitmap = (pSaveBitmap->SavedBitmapPosition -
(ySaveBitmap *
(UINT)TSHR_SSI_BITMAP_WIDTH)) /
pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity;
screenBitmapRect.left = pSaveBitmap->nLeftRect
- pasPerson->m_pView->m_dsScreenOrigin.x;
screenBitmapRect.top = pSaveBitmap->nTopRect
- pasPerson->m_pView->m_dsScreenOrigin.y;
screenBitmapRect.right = pSaveBitmap->nRightRect + 1
- pasPerson->m_pView->m_dsScreenOrigin.x;
screenBitmapRect.bottom = pSaveBitmap->nBottomRect + 1
- pasPerson->m_pView->m_dsScreenOrigin.y;
saveBitmapRect.left = 0;
saveBitmapRect.top = 0;
saveBitmapRect.right = TSHR_SSI_BITMAP_WIDTH;
saveBitmapRect.bottom = pasPerson->m_pView->m_ssiBitmapHeight;
//
// Start tiling in the top left corner of the Screen Bitmap rectangle.
//
xScreenBitmap = screenBitmapRect.left;
yScreenBitmap = screenBitmapRect.top;
//
// The height of the tile is the vertical granularity (or less - if
// the Screen Bitmap rect is thinner than the granularity).
//
cyTile = min(screenBitmapRect.bottom - yScreenBitmap,
(int)pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity );
//
// Repeat while there are more tiles in the Screen Bitmap rect to
// process.
//
while (yScreenBitmap < screenBitmapRect.bottom)
{
//
// The width of the tile is the minimum of:
//
// - the width of the remaining rectangle in the current strip of
// the Screen Bitmap rectangle
//
// - the width of the remaining empty space in the current strip of
// the Save Bitmap
//
//
cxTile = min( saveBitmapRect.right - xSaveBitmap,
screenBitmapRect.right - xScreenBitmap );
TRACE_OUT(( "screen(%d,%d) save(%d,%d) cx(%d) cy(%d)",
xScreenBitmap,
yScreenBitmap,
xSaveBitmap,
ySaveBitmap,
cxTile,
cyTile ));
//
// Save or Restore this tile
//
if (pSaveBitmap->Operation == SV_SAVEBITS)
{
//
// Save user's desktop area to SSI bitmap
//
BitBlt(pasPerson->m_pView->m_ssiDC,
xSaveBitmap, ySaveBitmap, cxTile, cyTile,
pasPerson->m_pView->m_usrDC,
xScreenBitmap, yScreenBitmap, SRCCOPY);
}
else
{
//
// Restore user's desktop area from SSI bitmap
//
BitBlt(pasPerson->m_pView->m_usrDC,
xScreenBitmap, yScreenBitmap, cxTile, cyTile,
pasPerson->m_pView->m_ssiDC,
xSaveBitmap, ySaveBitmap, SRCCOPY);
}
//
// Move to the next tile in the Screen Bitmap rectangle.
//
xScreenBitmap += cxTile;
if (xScreenBitmap >= screenBitmapRect.right)
{
xScreenBitmap = screenBitmapRect.left;
yScreenBitmap += cyTile;
cyTile = min( screenBitmapRect.bottom - yScreenBitmap,
(int)pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity );
}
//
// Move to the next free space in the Save Bitmap.
//
xSaveBitmap += ROUNDUP(cxTile, pasPerson->cpcCaps.orders.capsSaveBitmapXGranularity);
if (xSaveBitmap >= saveBitmapRect.right)
{
xSaveBitmap = saveBitmapRect.left;
ySaveBitmap += ROUNDUP(cyTile, pasPerson->cpcCaps.orders.capsSaveBitmapYGranularity);
}
}
DC_EXIT_POINT:
DebugExitVOID(ASShare::SSI_SaveBitmap);
}
//
// SSI_RecalcCaps()
//
// Called when we are hosting and someone joins/leaves the share.
//
// When 2.x COMPAT IS GONE, THIS IS OBSOLETE
//
void ASShare::SSI_RecalcCaps(BOOL fJoiner)
{
ASPerson * pasT;
SSI_NEW_CAPABILITIES newCapabilities;
DebugEntry(ASShare::SSI_RecalcCaps);
if (!m_pHost)
{
//
// Nothing to do. Note that we recalc when someone joins AND
// when someone leaves, like SBC.
//
DC_QUIT;
}
ValidatePerson(m_pasLocal);
//
// Enumerate all the save screen bitmap receive capabilities of the
// parties in the share. The usable size of the send save screen
// bitmap is then the minimum of all the remote receive sizes and the
// local send size.
//
//
// Copy the locally registered send save screen bitmap size capability
// to our global variable used to communicate with the enumeration
// function SSIEnumBitmapCacheCaps().
//
m_pHost->m_ssiSaveBitmapSize = m_pasLocal->cpcCaps.orders.capsReceiveSaveBitmapSize;
//
// Now enumerate all the parties in the share and set our send bitmap
// size appropriately.
//
if (m_scShareVersion < CAPS_VERSION_30)
{
TRACE_OUT(("In share with 2.x nodes; must recalc SSI caps"));
for (pasT = m_pasLocal->pasNext; pasT != NULL; pasT = pasT->pasNext)
{
//
// Set the size of the local send save screen bitmap to the minimum of
// its current size and this party's receive save screen bitmap size.
//
m_pHost->m_ssiSaveBitmapSize = min(m_pHost->m_ssiSaveBitmapSize,
pasT->cpcCaps.orders.capsReceiveSaveBitmapSize);
}
TRACE_OUT(("Recalced SSI caps: SS bitmap size 0x%08x",
m_pHost->m_ssiSaveBitmapSize));
}
//
// Set up the new capabilities structure...
//
newCapabilities.sendSaveBitmapSize = m_pHost->m_ssiSaveBitmapSize;
newCapabilities.xGranularity = TSHR_SSI_BITMAP_X_GRANULARITY;
newCapabilities.yGranularity = TSHR_SSI_BITMAP_Y_GRANULARITY;
//
// ... and pass it through to the driver.
//
if (!OSI_FunctionRequest(SSI_ESC_NEW_CAPABILITIES, (LPOSI_ESCAPE_HEADER)&newCapabilities,
sizeof(newCapabilities)))
{
ERROR_OUT(("SSI_ESC_NEW_CAPABILITIES failed"));
}
DC_EXIT_POINT:
DebugExitVOID(ASHost::SSI_RecalcCaps);
}