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