315 lines
7.9 KiB
C++
315 lines
7.9 KiB
C++
#include "precomp.h"
|
||
|
||
|
||
//
|
||
// CPC.CPP
|
||
// Capabilities Coordinator
|
||
//
|
||
// Copyright(c) Microsoft 1997-
|
||
//
|
||
|
||
#define MLZ_FILE_ZONE ZONE_CORE
|
||
|
||
|
||
|
||
|
||
//
|
||
// CPC_PartyJoiningShare()
|
||
//
|
||
BOOL ASShare::CPC_PartyJoiningShare
|
||
(
|
||
ASPerson * pasPerson,
|
||
UINT cbCaps,
|
||
LPVOID pCapsData
|
||
)
|
||
{
|
||
PPROTCOMBINEDCAPS pCombinedCaps;
|
||
LPBYTE pCapsSrc;
|
||
PPROTCAPS pCapsDst;
|
||
UINT sizeSrc;
|
||
UINT sizeDst;
|
||
BOOL rc = FALSE;
|
||
int i;
|
||
PPROTCAPS pCapCheck;
|
||
|
||
DebugEntry(ASShare::CPC_PartyJoiningShare);
|
||
|
||
//
|
||
// Set up caps
|
||
//
|
||
if (pasPerson == m_pasLocal)
|
||
{
|
||
// Copy the global variable caps
|
||
memcpy(&pasPerson->cpcCaps, pCapsData, cbCaps);
|
||
pasPerson->cpcCaps.share.gccID = g_asSession.gccID;
|
||
}
|
||
else
|
||
{
|
||
// When the person is created, it is zeroed out, so cpcCaps is too
|
||
pCombinedCaps = (PPROTCOMBINEDCAPS)pCapsData;
|
||
|
||
memcpy(&(pasPerson->cpcCaps.header), &(pCombinedCaps->header),
|
||
sizeof(pCombinedCaps->header));
|
||
|
||
//
|
||
// Save the caps we care about in a simple easy structure
|
||
//
|
||
pCapsSrc = (LPBYTE)pCombinedCaps->capabilities;
|
||
|
||
for (i = 0; i < pCombinedCaps->header.numCapabilities; i++)
|
||
{
|
||
sizeSrc = (UINT)(((PPROTCAPS)pCapsSrc)->header.capSize);
|
||
|
||
switch (((PPROTCAPS)pCapsSrc)->header.capID)
|
||
{
|
||
case CAPS_ID_GENERAL:
|
||
pCapsDst = (PPROTCAPS)&(pasPerson->cpcCaps.general);
|
||
sizeDst = sizeof(PROTCAPS_GENERAL);
|
||
break;
|
||
|
||
case CAPS_ID_SCREEN:
|
||
pCapsDst = (PPROTCAPS)&(pasPerson->cpcCaps.screen);
|
||
sizeDst = sizeof(PROTCAPS_SCREEN);
|
||
break;
|
||
|
||
case CAPS_ID_ORDERS:
|
||
pCapsDst = (PPROTCAPS)&(pasPerson->cpcCaps.orders);
|
||
sizeDst = sizeof(PROTCAPS_ORDERS);
|
||
break;
|
||
|
||
case CAPS_ID_BITMAPCACHE:
|
||
pCapsDst = (PPROTCAPS)&(pasPerson->cpcCaps.bitmaps);
|
||
sizeDst = sizeof(PROTCAPS_BITMAPCACHE);
|
||
break;
|
||
|
||
case CAPS_ID_CM:
|
||
pCapsDst = (PPROTCAPS)&(pasPerson->cpcCaps.cursor);
|
||
sizeDst = sizeof(PROTCAPS_CM);
|
||
break;
|
||
|
||
case CAPS_ID_PM:
|
||
pCapsDst = (PPROTCAPS)&(pasPerson->cpcCaps.palette);
|
||
sizeDst = sizeof(PROTCAPS_PM);
|
||
break;
|
||
|
||
case CAPS_ID_SC:
|
||
pCapsDst = (PPROTCAPS)&(pasPerson->cpcCaps.share);
|
||
sizeDst = sizeof(PROTCAPS_SC);
|
||
break;
|
||
|
||
default:
|
||
// Skip caps we don't recognize
|
||
WARNING_OUT(("Ignoring unrecognized cap ID %d, size %d from person [%d]",
|
||
((PPROTCAPS)pCapsSrc)->header.capID, sizeSrc,
|
||
pasPerson->mcsID));
|
||
pCapsDst = NULL;
|
||
break;
|
||
}
|
||
|
||
if (pCapsDst)
|
||
{
|
||
//
|
||
// Only copy the amount given, but keep the size of the
|
||
// structure in the header the right one.
|
||
//
|
||
CopyMemory(pCapsDst, pCapsSrc, min(sizeSrc, sizeDst));
|
||
pCapsDst->header.capSize = (TSHR_UINT16)sizeDst;
|
||
}
|
||
|
||
pCapsSrc += sizeSrc;
|
||
}
|
||
}
|
||
|
||
|
||
//
|
||
// Check that we have the basic 7 caps
|
||
//
|
||
if (!pasPerson->cpcCaps.general.header.capID)
|
||
{
|
||
ERROR_OUT(("Bogus GENERAL caps for person [%d]", pasPerson->mcsID));
|
||
DC_QUIT;
|
||
}
|
||
if (!pasPerson->cpcCaps.screen.header.capID)
|
||
{
|
||
ERROR_OUT(("Bogus SCREEN caps for person [%d]", pasPerson->mcsID));
|
||
DC_QUIT;
|
||
}
|
||
if (!pasPerson->cpcCaps.orders.header.capID)
|
||
{
|
||
ERROR_OUT(("Bogus ORDERS caps for person [%d]", pasPerson->mcsID));
|
||
DC_QUIT;
|
||
}
|
||
if (!pasPerson->cpcCaps.bitmaps.header.capID)
|
||
{
|
||
ERROR_OUT(("Bogus BITMAPS caps for person [%d]", pasPerson->mcsID));
|
||
DC_QUIT;
|
||
}
|
||
if (!pasPerson->cpcCaps.cursor.header.capID)
|
||
{
|
||
ERROR_OUT(("Bogus CURSOR caps for person [%d]", pasPerson->mcsID));
|
||
DC_QUIT;
|
||
}
|
||
if (!pasPerson->cpcCaps.palette.header.capID)
|
||
{
|
||
ERROR_OUT(("Bogus PALETTE caps for person [%d]", pasPerson->mcsID));
|
||
DC_QUIT;
|
||
}
|
||
if (!pasPerson->cpcCaps.share.header.capID)
|
||
{
|
||
ERROR_OUT(("Bogus SHARE caps for person [%d]", pasPerson->mcsID));
|
||
DC_QUIT;
|
||
}
|
||
|
||
// SUCCESS!
|
||
|
||
rc = TRUE;
|
||
|
||
DC_EXIT_POINT:
|
||
DebugExitBOOL(ASShare::CPC_PartyJoiningShare, rc);
|
||
return(rc);
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// CPC_UpdatedCaps()
|
||
//
|
||
void ASShare::CPC_UpdatedCaps(PPROTCAPS pCaps)
|
||
{
|
||
ASPerson * pasT;
|
||
PCPCPACKET pCPCPacket;
|
||
UINT packetSize;
|
||
#ifdef _DEBUG
|
||
UINT sentSize;
|
||
#endif
|
||
|
||
DebugEntry(ASShare::CPC_UpdatedCaps);
|
||
|
||
//
|
||
// Only allow screen size change!
|
||
//
|
||
ASSERT(pCaps->header.capID == CAPS_ID_SCREEN);
|
||
|
||
//
|
||
// Only send change if all support it
|
||
//
|
||
for (pasT = m_pasLocal; pasT != NULL; pasT = pasT->pasNext)
|
||
{
|
||
if (pasT->cpcCaps.general.supportsCapsUpdate != CAPS_SUPPORTED)
|
||
{
|
||
WARNING_OUT(("Not sending caps update; person [%d] doesn't support it",
|
||
pasT->mcsID));
|
||
DC_QUIT;
|
||
}
|
||
}
|
||
|
||
// Everybody supports a caps change. Try to send the changed packet
|
||
|
||
//
|
||
// Allocate a DT_CPC packet and send it to the remote site
|
||
//
|
||
packetSize = sizeof(CPCPACKET) + pCaps->header.capSize - sizeof(PROTCAPS);
|
||
pCPCPacket = (PCPCPACKET)SC_AllocPkt(PROT_STR_MISC, g_s20BroadcastID, packetSize);
|
||
if (!pCPCPacket)
|
||
{
|
||
WARNING_OUT(("Failed to alloc CPC packet, size %u", packetSize));
|
||
DC_QUIT;
|
||
}
|
||
|
||
//
|
||
// Fill in the capabilities that have changed
|
||
//
|
||
pCPCPacket->header.data.dataType = DT_CPC;
|
||
|
||
memcpy(&pCPCPacket->caps, pCaps, pCaps->header.capSize);
|
||
|
||
//
|
||
// Compress and send the packet
|
||
//
|
||
#ifdef _DEBUG
|
||
sentSize =
|
||
#endif // _DEBUG
|
||
DCS_CompressAndSendPacket(PROT_STR_MISC, g_s20BroadcastID,
|
||
&(pCPCPacket->header), packetSize);
|
||
|
||
TRACE_OUT(("CPC packet size: %08d, sent %08d", packetSize, sentSize));
|
||
|
||
// Handle change
|
||
CPCCapabilitiesChange(m_pasLocal, pCaps);
|
||
|
||
DC_EXIT_POINT:
|
||
DebugExitVOID(ASShare::CPC_UpdatedCaps);
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// CPC_ReceivedPacket()
|
||
//
|
||
void ASShare::CPC_ReceivedPacket
|
||
(
|
||
ASPerson * pasPerson,
|
||
PS20DATAPACKET pPacket
|
||
)
|
||
{
|
||
PCPCPACKET pCPCPacket;
|
||
|
||
DebugEntry(ASShare::CPC_ReceivedPacket);
|
||
|
||
ValidatePerson(pasPerson);
|
||
|
||
pCPCPacket = (PCPCPACKET)pPacket;
|
||
|
||
//
|
||
// Capabilities have changed - update the local copy and inform all
|
||
// components
|
||
//
|
||
TRACE_OUT(( "Capabilities changing for person [%d]", pasPerson->mcsID));
|
||
|
||
TRACE_OUT(("Size of new capabilities 0x%08x", pCPCPacket->caps.header.capSize));
|
||
CPCCapabilitiesChange(pasPerson, &(pCPCPacket->caps));
|
||
|
||
DebugExitVOID(ASShare::CPC_ReceivedPacket);
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// CPCCapabilitiesChange()
|
||
//
|
||
BOOL ASShare::CPCCapabilitiesChange
|
||
(
|
||
ASPerson * pasPerson,
|
||
PPROTCAPS pCaps
|
||
)
|
||
{
|
||
BOOL changed;
|
||
|
||
DebugEntry(ASShare::CPCCapabilitiesChange);
|
||
|
||
ValidatePerson(pasPerson);
|
||
|
||
//
|
||
// Get pointer to the caps we're changing (SHOULD ONLY BE SCREEN!)
|
||
//
|
||
if (pCaps->header.capID != CAPS_ID_SCREEN)
|
||
{
|
||
ERROR_OUT(("Received caps change from [%d] for cap ID %d we can't handle",
|
||
pasPerson->mcsID, pCaps->header.capID));
|
||
changed = FALSE;
|
||
}
|
||
else
|
||
{
|
||
CopyMemory(&(pasPerson->cpcCaps.screen), pCaps,
|
||
min(sizeof(PROTCAPS_SCREEN), pCaps->header.capSize));
|
||
pasPerson->cpcCaps.screen.header.capSize = sizeof(PROTCAPS_SCREEN);
|
||
|
||
USR_ScreenChanged(pasPerson);
|
||
|
||
changed = TRUE;
|
||
}
|
||
|
||
DebugExitBOOL(ASShare::CPCCapabilitiesChange, changed);
|
||
return(changed);
|
||
}
|
||
|