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);
|
|||
|
}
|
|||
|
|