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.
644 lines
31 KiB
644 lines
31 KiB
/****************************************************************************/
|
|
// acpcapi.cpp
|
|
//
|
|
// Capabilities Coordinator API functions.
|
|
//
|
|
// Copyright(c) Microsoft, PictureTel 1992-1996
|
|
// (C) 1997-1999 Microsoft Corp.
|
|
/****************************************************************************/
|
|
|
|
#include <precomp.h>
|
|
#pragma hdrstop
|
|
|
|
#define TRC_FILE "acpcapi"
|
|
#include <as_conf.hpp>
|
|
|
|
/****************************************************************************/
|
|
/* API FUNCTION: CPC_Init */
|
|
/* */
|
|
/* Initializes the Capabilities Coordinator. */
|
|
/****************************************************************************/
|
|
void RDPCALL SHCLASS CPC_Init(void)
|
|
{
|
|
DC_BEGIN_FN("CPC_Init");
|
|
|
|
/************************************************************************/
|
|
/* This initializes all the global data for this component */
|
|
/************************************************************************/
|
|
#define DC_INIT_DATA
|
|
#include <acpcdata.c>
|
|
#undef DC_INIT_DATA
|
|
|
|
// Set up pointer to presized memory buffer and set initial size value
|
|
// since the presized buffer is uninitialized.
|
|
cpcLocalCombinedCaps = (PTS_COMBINED_CAPABILITIES)cpcLocalCaps;
|
|
cpcLocalCombinedCaps->numberCapabilities = 0;
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* API FUNCTION: CPC_Term */
|
|
/* */
|
|
/* Terminates the Capabilities Coordinator. */
|
|
/****************************************************************************/
|
|
void RDPCALL SHCLASS CPC_Term(void)
|
|
{
|
|
unsigned i;
|
|
|
|
DC_BEGIN_FN("CPC_Term");
|
|
|
|
/************************************************************************/
|
|
/* Free capabilities for each party */
|
|
/************************************************************************/
|
|
for (i = 0; i < SC_DEF_MAX_PARTIES; i++) {
|
|
TRC_NRM((TB, "Free data for party %d", i));
|
|
if (cpcRemoteCombinedCaps[i] != NULL)
|
|
COM_Free(cpcRemoteCombinedCaps[i]);
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* API FUNCTION: CPC_RegisterCapabilities */
|
|
/* */
|
|
/* Called at initialisation time by each component that has capabilities */
|
|
/* which need to be negotiated across the share. This is used to register */
|
|
/* all capabilities. */
|
|
/* */
|
|
/* PARAMETERS: */
|
|
/* pCapabilities - pointer to a structure containing the capabilities ID */
|
|
/* and any number of capability fields. */
|
|
/* The values used in these fields should be non-zero. A */
|
|
/* zero in any capability field is used to indicate that */
|
|
/* the capability is either unknown or undefined by the */
|
|
/* remote. */
|
|
/* */
|
|
/* sizeOfCaps - the size of the total capabilities. The limit on the */
|
|
/* total size of all secondary capabilities is 300 bytes, */
|
|
/* but this is imposed locally and could be increased */
|
|
/* without harming interoperability. */
|
|
/****************************************************************************/
|
|
void RDPCALL SHCLASS CPC_RegisterCapabilities(
|
|
PTS_CAPABILITYHEADER pCapabilities,
|
|
UINT16 sizeOfCaps)
|
|
{
|
|
unsigned i;
|
|
PTS_CAPABILITYHEADER pNextCaps;
|
|
|
|
DC_BEGIN_FN("CPC_RegisterCapabilities");
|
|
|
|
TRC_NRM((TB, "Registering capabilities ID %hd, size %hd",
|
|
pCapabilities->capabilitySetType, sizeOfCaps));
|
|
|
|
#ifdef DC_DEBUG
|
|
/************************************************************************/
|
|
/* Check that CPC_GetCombinedCapabilities has not already been called. */
|
|
/************************************************************************/
|
|
if (cpcLocalCombinedCapsQueried)
|
|
{
|
|
TRC_ERR((TB, "CPC_GetCombinedCapabilities has already been called"));
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/* Register capabilities (if any) */
|
|
/************************************************************************/
|
|
if (sizeOfCaps != 0) {
|
|
pCapabilities->lengthCapability = sizeOfCaps;
|
|
|
|
// Search for the end of the capabilities structure.
|
|
pNextCaps = (PTS_CAPABILITYHEADER)&(cpcLocalCombinedCaps->data[0]);
|
|
for (i = 0; i < cpcLocalCombinedCaps->numberCapabilities; i++)
|
|
pNextCaps = (PTS_CAPABILITYHEADER)((PBYTE)pNextCaps +
|
|
pNextCaps->lengthCapability);
|
|
|
|
// Check that we have enough room in our combined capabilities
|
|
// structure to add the new capabilities.
|
|
if (((PBYTE)pNextCaps - (PBYTE)cpcLocalCombinedCaps +
|
|
pCapabilities->lengthCapability) <= CPC_MAX_LOCAL_CAPS_SIZE) {
|
|
// Copy across the new capabilities into our combined capabilities
|
|
// structure.
|
|
memcpy(pNextCaps, pCapabilities, pCapabilities->lengthCapability);
|
|
|
|
// Update the number of capabilities in our combined capabilities
|
|
// structure.
|
|
cpcLocalCombinedCaps->numberCapabilities++;
|
|
|
|
TRC_DBG((TB, "Added %d bytes to capabilities for ID %d",
|
|
pCapabilities->lengthCapability,
|
|
pCapabilities->capabilitySetType));
|
|
}
|
|
else {
|
|
// We do not have enough room to add the capabilities so return.
|
|
// Any system communicating with us will think we do not support
|
|
// these capabilities. The size of the capabilities structure
|
|
// can be increased (it is not limited as part of the protocol).
|
|
// The value of CPC_MAX_LOCAL_CAPS_SIZE should be increased.
|
|
TRC_ERR((TB,"Out of combined capabilities space ID %d; size %d",
|
|
pCapabilities->capabilitySetType,
|
|
pCapabilities->lengthCapability));
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* API FUNCTION: CPC_EnumerateCapabilities */
|
|
/* */
|
|
/* Enumerates the capabilities for each node in the share (not including */
|
|
/* local). */
|
|
/* */
|
|
/* PARAMETERS: */
|
|
/* capabilitiesID - the ID of the capabilities (group structure) to be */
|
|
/* enumerated. */
|
|
/* UserData - Private caller data to be passed to each call of the enum */
|
|
/* func. */
|
|
/* pCapsEnumerateFN - function to be called for each person in the share */
|
|
/* with the persons capabilities structure. */
|
|
/****************************************************************************/
|
|
void RDPCALL SHCLASS CPC_EnumerateCapabilities(
|
|
unsigned capabilitiesID,
|
|
UINT_PTR UserData,
|
|
PCAPSENUMERATEFN pCapsEnumerateFN)
|
|
{
|
|
LOCALPERSONID localID;
|
|
unsigned i;
|
|
BOOL foundCapabilities;
|
|
PTS_CAPABILITYHEADER pCaps;
|
|
TS_CAPABILITYHEADER emptyCaps;
|
|
|
|
DC_BEGIN_FN("CPC_EnumerateCapabilities");
|
|
|
|
/************************************************************************/
|
|
/* Search for the capabilities ID within the remote party's section of */
|
|
/* the combined capabilities structure. */
|
|
/************************************************************************/
|
|
for (localID = SC_DEF_MAX_PARTIES - 1; localID >= 1; localID--) {
|
|
if (cpcRemoteCombinedCaps[localID-1] != NULL) {
|
|
pCaps = (PTS_CAPABILITYHEADER)
|
|
&(cpcRemoteCombinedCaps[localID-1]->data[0]);
|
|
|
|
for (i = 0, foundCapabilities = FALSE;
|
|
i < cpcRemoteCombinedCaps[localID-1]->numberCapabilities;
|
|
i++) {
|
|
if (pCaps->capabilitySetType == capabilitiesID) {
|
|
/********************************************************/
|
|
/* We have found the capabilities structure requested. */
|
|
/* Make the call to the enumeration callback function. */
|
|
/********************************************************/
|
|
foundCapabilities = TRUE;
|
|
(this->*pCapsEnumerateFN)(localID, UserData, pCaps);
|
|
|
|
/********************************************************/
|
|
/* Go onto the next person. */
|
|
/********************************************************/
|
|
break;
|
|
}
|
|
pCaps = (PTS_CAPABILITYHEADER)((PBYTE)pCaps +
|
|
pCaps->lengthCapability);
|
|
}
|
|
|
|
if (!foundCapabilities) {
|
|
/************************************************************/
|
|
/* We did not find the requested capability structure for */
|
|
/* this party so we must return an empty one. */
|
|
/************************************************************/
|
|
emptyCaps.capabilitySetType = (UINT16)capabilitiesID;
|
|
emptyCaps.lengthCapability = 0;
|
|
|
|
/************************************************************/
|
|
/* Call the enumeration function callback with the empty */
|
|
/* capabilities for this personID. */
|
|
/************************************************************/
|
|
(this->*pCapsEnumerateFN)(localID, UserData, &emptyCaps);
|
|
}
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* API FUNCTION: CPC_GetCombinedCapabilities */
|
|
/* */
|
|
/* Called by the Share Controller (SC). Returns a pointers to structures */
|
|
/* containing the combined capabilities of all the registered capabilities. */
|
|
/* */
|
|
/* Note that this relies on the initialisation order of the components. */
|
|
/* The CPC must be initialized before any components with capabilities. */
|
|
/* Any components with capabilities must register them at initialisation */
|
|
/* time. The SC must be initialized after any components with */
|
|
/* capabilities. */
|
|
/* */
|
|
/* PARAMETERS: */
|
|
/* localID - local ID of the person we are interested in. */
|
|
/* pSizeOfCaps - pointer to variable to be filled in with the size of the */
|
|
/* combined capabilities structure returned as ppCaps. */
|
|
/* */
|
|
/* ppCaps - pointer to variable to be filled in with the pointer to the */
|
|
/* combined capabilities structure containing capabilities passed to */
|
|
/* CPC_RegisterCapabilities. */
|
|
/****************************************************************************/
|
|
void RDPCALL SHCLASS CPC_GetCombinedCapabilities(
|
|
LOCALPERSONID localID,
|
|
PUINT pSizeOfCaps,
|
|
PTS_COMBINED_CAPABILITIES *ppCaps)
|
|
{
|
|
unsigned i;
|
|
PTS_CAPABILITYHEADER pNextCaps;
|
|
PTS_COMBINED_CAPABILITIES pCaps;
|
|
unsigned numCaps;
|
|
|
|
DC_BEGIN_FN("CPC_GetCombinedCapabilities");
|
|
|
|
/************************************************************************/
|
|
/* Try to find the requested capabilitiesID for this person. */
|
|
/* */
|
|
/* If the localID refers to the local system then search the combined */
|
|
/* capabilities structure (ie all capabilities registered with */
|
|
/* CPC_RegisterCapabilities). Otherwise search the structure we */
|
|
/* received from the remote person. */
|
|
/************************************************************************/
|
|
if (localID == SC_LOCAL_PERSON_ID) {
|
|
pCaps = cpcLocalCombinedCaps;
|
|
numCaps = cpcLocalCombinedCaps->numberCapabilities;
|
|
|
|
#ifdef DC_DEBUG
|
|
/************************************************************************/
|
|
/* Set our flag we use to check that CPC_Register is not called after */
|
|
/* this function has been called. */
|
|
/************************************************************************/
|
|
cpcLocalCombinedCapsQueried = TRUE;
|
|
#endif
|
|
|
|
}
|
|
else {
|
|
if (cpcRemoteCombinedCaps[localID - 1] != NULL) {
|
|
pCaps = cpcRemoteCombinedCaps[localID - 1];
|
|
numCaps = cpcRemoteCombinedCaps[localID - 1]->numberCapabilities;
|
|
}
|
|
else {
|
|
TRC_ERR((TB, "Capabilities pointer is NULL"));
|
|
|
|
*pSizeOfCaps = 0;
|
|
*ppCaps = NULL;
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Search for the end of the capabilities structure for the local */
|
|
/* party. */
|
|
/************************************************************************/
|
|
TRC_DBG((TB, "Caps:"));
|
|
pNextCaps = (PTS_CAPABILITYHEADER)&(pCaps->data[0]);
|
|
|
|
for (i = 0; i < numCaps; i++) {
|
|
TRC_DBG((TB, "caps size %hd", pNextCaps->lengthCapability));
|
|
TRC_DBG((TB, "caps ID %hd", pNextCaps->capabilitySetType));
|
|
|
|
pNextCaps = (PTS_CAPABILITYHEADER)( (PBYTE)pNextCaps
|
|
+ pNextCaps->lengthCapability );
|
|
}
|
|
|
|
*pSizeOfCaps = (unsigned)((PBYTE)pNextCaps - (PBYTE)pCaps);
|
|
*ppCaps = pCaps;
|
|
TRC_NRM((TB, "Total size %d", *pSizeOfCaps));
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* CPC_SetCombinedCapabilities(..) */
|
|
/* */
|
|
/* Used by a shadow stack to initialize the combined capabilities to the */
|
|
/* values negotiated so far by its predecessors. */
|
|
/****************************************************************************/
|
|
void RDPCALL SHCLASS CPC_SetCombinedCapabilities(
|
|
UINT cbSizeOfCaps,
|
|
PTS_COMBINED_CAPABILITIES pCaps)
|
|
{
|
|
unsigned i;
|
|
PTS_CAPABILITYHEADER pNextCaps;
|
|
|
|
DC_BEGIN_FN("CPC_SetCombinedCapabilities");
|
|
|
|
/************************************************************************/
|
|
/* Replace the existing capability set with the new values */
|
|
/************************************************************************/
|
|
cpcLocalCombinedCaps->numberCapabilities = 0;
|
|
pNextCaps = (PTS_CAPABILITYHEADER)&(pCaps->data[0]);
|
|
|
|
TRC_NRM((TB, "Caps:"));
|
|
for (i = 0; i < pCaps->numberCapabilities; i++) {
|
|
CPC_RegisterCapabilities(pNextCaps, pNextCaps->lengthCapability);
|
|
|
|
pNextCaps = (PTS_CAPABILITYHEADER)( (PBYTE)pNextCaps
|
|
+ pNextCaps->lengthCapability );
|
|
}
|
|
|
|
TRC_ALT((TB, "Capability bytes accepted: %ld / %ld",
|
|
(unsigned)((PBYTE)pNextCaps - (PBYTE)cpcLocalCombinedCaps),
|
|
cbSizeOfCaps));
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* API FUNCTION: CPC_PartyJoiningShare() */
|
|
/* */
|
|
/* Capabilities Coordinator function called when a new party is joining the */
|
|
/* share. */
|
|
/* */
|
|
/* Note that the capabilities data <pCapsData> is still in wire format */
|
|
/* (Intel byte order) when CPC_PartyJoiningShare is called. */
|
|
/* */
|
|
/* PARAMETERS: */
|
|
/* */
|
|
/* personID - local person ID of remote person joining the share. */
|
|
/* */
|
|
/* oldShareSize - the number of the parties which were in the share (ie */
|
|
/* excludes the joining party). */
|
|
/* */
|
|
/* sizeOfCapsData - size of the data pointed to by pCapsData. */
|
|
/* */
|
|
/* pCapsData - pointer to capabilities (returned by the person's */
|
|
/* CPC_GetCombinedCapabilities) data for NET_EV_PERSON_ADDs. For the other */
|
|
/* events this is NULL. */
|
|
/* */
|
|
/* RETURNS: TRUE if the party can join the share. */
|
|
/* FALSE if the party can NOT join the share. */
|
|
/****************************************************************************/
|
|
BOOL RDPCALL SHCLASS CPC_PartyJoiningShare(
|
|
LOCALPERSONID personID,
|
|
unsigned oldShareSize,
|
|
unsigned sizeOfCapsData,
|
|
PVOID pCapsData)
|
|
{
|
|
PTS_COMBINED_CAPABILITIES pCombinedCaps;
|
|
PBYTE pCaps;
|
|
PBYTE pSavedCaps;
|
|
BOOL rc = TRUE;
|
|
int i;
|
|
UINT32 sizeOfCaps = FIELDOFFSET(TS_COMBINED_CAPABILITIES, data);
|
|
UINT32 work;
|
|
|
|
DC_BEGIN_FN("CPC_PartyJoiningShare");
|
|
DC_IGNORE_PARAMETER(oldShareSize)
|
|
|
|
/************************************************************************/
|
|
/* Allow ourself to be added to the share, but do nothing else. */
|
|
/************************************************************************/
|
|
if (personID == SC_LOCAL_PERSON_ID) {
|
|
TRC_DBG((TB, "Ignore adding self to share"));
|
|
DC_QUIT;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Calculate actual space required to save capabilities */
|
|
/************************************************************************/
|
|
// First we check if actually can deref the numberCapabilities member.
|
|
// We should have enough bytes till up to the data meber.
|
|
if(sizeOfCapsData < FIELDOFFSET(TS_COMBINED_CAPABILITIES, data)){
|
|
TRC_ERR((TB, "Buffer too small to fit a combined caps structure: %d", sizeOfCapsData));
|
|
WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_CapabilitySetTooSmall,
|
|
(PBYTE)pCapsData, sizeOfCapsData);
|
|
rc = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
|
|
pCombinedCaps = (PTS_COMBINED_CAPABILITIES)pCapsData;
|
|
pCaps = (PBYTE)pCombinedCaps->data;
|
|
|
|
for (i = 0; i < pCombinedCaps->numberCapabilities; i++) {
|
|
// here we check if we still have left TS_CAPABILITYHEADER length worth of data
|
|
// we can't just deref the length member without checking that we actually have
|
|
// enough buffer for a TS_CAPABILITYHEADER
|
|
if ((PBYTE)pCaps + sizeof(TS_CAPABILITYHEADER) >
|
|
(PBYTE)pCapsData + sizeOfCapsData) {
|
|
TRC_ERR((TB, "Not enough space left for a capability header: %d",
|
|
sizeOfCapsData-(pCaps-(PBYTE)pCapsData) ));
|
|
WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_CapabilitySetTooSmall,
|
|
(PBYTE)pCapsData, sizeOfCapsData);
|
|
rc = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
|
|
work = (UINT32)(((PTS_CAPABILITYHEADER)pCaps)->lengthCapability);
|
|
|
|
/********************************************************************/
|
|
/* Reject capability sets whose length is too small to contain any */
|
|
/* data */
|
|
/********************************************************************/
|
|
if (work <= sizeof(TS_CAPABILITYHEADER)) {
|
|
TRC_ERR((TB, "Capability set too small: %d", work));
|
|
WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_CapabilitySetTooSmall,
|
|
(PBYTE)pCapsData, sizeOfCapsData);
|
|
rc = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* Reject capability sets whose length would overrun the end of the */
|
|
/* packet. */
|
|
/********************************************************************/
|
|
if ((pCaps+work> (PBYTE)pCapsData + sizeOfCapsData) ||
|
|
(pCaps+work < (PBYTE)pCaps)) {
|
|
TRC_ERR((TB, "Capability set too large: %d", work));
|
|
WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_CapabilitySetTooLarge,
|
|
(PBYTE)pCapsData, sizeOfCapsData);
|
|
rc = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
|
|
pCaps += work;
|
|
|
|
work = (UINT32)DC_ROUND_UP_4(work);
|
|
sizeOfCaps += work;
|
|
}
|
|
|
|
TRC_NRM((TB, "Caps size: passed %d, actual %d", sizeOfCapsData,
|
|
sizeOfCaps));
|
|
|
|
/************************************************************************/
|
|
/* Allocate the space for this person's capabilities. */
|
|
/************************************************************************/
|
|
cpcRemoteCombinedCaps[personID - 1] =
|
|
(PTS_COMBINED_CAPABILITIES)COM_Malloc(sizeOfCaps);
|
|
if (cpcRemoteCombinedCaps[personID - 1] == NULL) {
|
|
/********************************************************************/
|
|
/* This party cannot join the share. */
|
|
/********************************************************************/
|
|
TRC_NRM((TB, "Failed to get %d bytes for personID %d caps",
|
|
sizeOfCapsData,
|
|
personID));
|
|
|
|
rc = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
TRC_DBG((TB, "Allocated %d bytes for personID %d caps",
|
|
sizeOfCapsData,
|
|
personID));
|
|
|
|
/************************************************************************/
|
|
/* Initialize the memory to zero. Otherwise we can get little gaps of */
|
|
/* garbage - which can be interpreted as valid capabilities - when */
|
|
/* copying non-end-padded capability entries from the remote party's */
|
|
/* data. */
|
|
/************************************************************************/
|
|
memset(cpcRemoteCombinedCaps[personID-1], 0, sizeOfCaps);
|
|
|
|
/************************************************************************/
|
|
/* Copy the combined capabilities data. */
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* Copy the combined capabilities header */
|
|
/************************************************************************/
|
|
memcpy( cpcRemoteCombinedCaps[personID-1],
|
|
pCapsData, FIELDOFFSET(TS_COMBINED_CAPABILITIES, data));
|
|
|
|
/************************************************************************/
|
|
/* Loop through capabilities, copying them to 4-byte aligned positions */
|
|
/************************************************************************/
|
|
pSavedCaps = (PBYTE)(cpcRemoteCombinedCaps[personID-1]->data);
|
|
pCaps = (PBYTE)((PBYTE)pCapsData +
|
|
FIELDOFFSET(TS_COMBINED_CAPABILITIES, data));
|
|
for (i = 0; i < pCombinedCaps->numberCapabilities; i++) {
|
|
work = (UINT32)(((PTS_CAPABILITYHEADER)pCaps)->lengthCapability);
|
|
memcpy( pSavedCaps, pCaps, work);
|
|
pCaps += work;
|
|
work = (UINT32)DC_ROUND_UP_4(work);
|
|
((PTS_CAPABILITYHEADER)pSavedCaps)->lengthCapability = (UINT16)work;
|
|
pSavedCaps += work;
|
|
}
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return rc;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* API FUNCTION: CPC_PartyLeftShare() */
|
|
/* */
|
|
/* Capabilities Coordinator function called when a party has left the */
|
|
/* share. */
|
|
/* */
|
|
/* PARAMETERS: */
|
|
/* personID - local person ID of remote person leaving the share. */
|
|
/* */
|
|
/* newShareSize - the number of the parties now in the share (ie excludes */
|
|
/* the leaving party). */
|
|
/****************************************************************************/
|
|
void RDPCALL SHCLASS CPC_PartyLeftShare(LOCALPERSONID locPersonID,
|
|
unsigned newShareSize)
|
|
{
|
|
DC_BEGIN_FN("CPC_PartyLeftShare");
|
|
|
|
DC_IGNORE_PARAMETER(newShareSize)
|
|
|
|
/************************************************************************/
|
|
/* If this is ourself leaving the share do nothing. */
|
|
/************************************************************************/
|
|
if (locPersonID != SC_LOCAL_PERSON_ID) {
|
|
// Free this party's capabilities from the array and mark the entry
|
|
// as invalid.
|
|
if (cpcRemoteCombinedCaps[locPersonID - 1] != NULL) {
|
|
COM_Free((PVOID)cpcRemoteCombinedCaps[locPersonID-1]);
|
|
cpcRemoteCombinedCaps[locPersonID - 1] = NULL;
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* FUNCTION: CPCGetCapabilities */
|
|
/* */
|
|
/* Returns the capabilities for one person. */
|
|
/* */
|
|
/* PARAMETERS: */
|
|
/* localID - local ID of person (0 == local person) */
|
|
/* capabilitiesID - the ID of the capabilities (group structure) to be */
|
|
/* queried. */
|
|
/* */
|
|
/* RETURNS: */
|
|
/* Pointer to a structure containing the capabilities ID, the size of the */
|
|
/* capabilities, and any number of capability fields. */
|
|
/* */
|
|
/* If the person has no capabilities with capabilitiesID, a NULL pointer is */
|
|
/* returned. */
|
|
/****************************************************************************/
|
|
PTS_CAPABILITYHEADER RDPCALL SHCLASS CPCGetCapabilities(
|
|
LOCALPERSONID localID,
|
|
unsigned capabilitiesID)
|
|
{
|
|
unsigned i;
|
|
unsigned numCaps;
|
|
PTS_CAPABILITYHEADER pCaps;
|
|
PTS_CAPABILITYHEADER rc = NULL;
|
|
|
|
DC_BEGIN_FN("CPCGetCapabilities");
|
|
|
|
/************************************************************************/
|
|
/* Try to find the requested capabilitiesID for this person. */
|
|
/* */
|
|
/* If the localID refers to the local system then search the combined */
|
|
/* capabilities structure (ie all capabilities registered with */
|
|
/* CPC_RegisterCapabilities). Otherwise search the structure we */
|
|
/* received from the remote person. */
|
|
/************************************************************************/
|
|
if (localID == 0) {
|
|
pCaps = (PTS_CAPABILITYHEADER)&(cpcLocalCombinedCaps->data[0]);
|
|
numCaps = cpcLocalCombinedCaps->numberCapabilities;
|
|
}
|
|
else {
|
|
if (cpcRemoteCombinedCaps[localID-1] == NULL)
|
|
{
|
|
TRC_ERR((TB, "Capabilities pointer is NULL"));
|
|
DC_QUIT;
|
|
}
|
|
pCaps = (PTS_CAPABILITYHEADER)
|
|
&(cpcRemoteCombinedCaps[localID-1]->data[0]);
|
|
numCaps = cpcRemoteCombinedCaps[localID-1]->numberCapabilities;
|
|
}
|
|
|
|
for (i = 0; i < numCaps; i++) {
|
|
if (pCaps->capabilitySetType == capabilitiesID) {
|
|
/****************************************************************/
|
|
/* We have found the capabilities structure requested. Return */
|
|
/* the address of the capabilities. */
|
|
/****************************************************************/
|
|
TRC_DBG((TB, "Found %d bytes of caps ID %d localID %d",
|
|
pCaps->lengthCapability,
|
|
capabilitiesID,
|
|
localID));
|
|
rc = pCaps;
|
|
break;
|
|
}
|
|
pCaps = (PTS_CAPABILITYHEADER)( (PBYTE)pCaps +
|
|
pCaps->lengthCapability );
|
|
}
|
|
|
|
if (rc == NULL) {
|
|
TRC_NRM((TB, " local ID = %u : No caps found for ID %d",
|
|
(unsigned)localID,
|
|
capabilitiesID));
|
|
}
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return rc;
|
|
}
|
|
|