#include "precomp.h" #include "fsdiag.h" DEBUG_FILEZONE(ZONE_T120_UTILITY); /* * appcap.cpp * * Copyright (c) 1994 by DataBeam Corporation, Lexington, KY * * Abstract: * This is the implementation file for the class CAppCap. * * Caveats: * None. * * Author: * jbo */ #include "appcap.h" #include "clists.h" /* * CAppCap () * * Public Function Description: * This constructor is used to create a AppCapabilityData object * from an "API" GCCApplicationCapability list. */ CAppCap::CAppCap(UINT number_of_capabilities, PGCCApplicationCapability * capabilities_list, PGCCError pRetCode) : CRefCount(MAKE_STAMP_ID('A','C','a','p')), m_AppCapItemList(DESIRED_MAX_CAPS), m_cbDataSize(0) { APP_CAP_ITEM *pAppCapItem; UINT i; GCCError rc; rc = GCC_NO_ERROR; for (i = 0; i < number_of_capabilities; i++) { DBG_SAVE_FILE_LINE pAppCapItem = new APP_CAP_ITEM((GCCCapabilityType) capabilities_list[i]->capability_class.eType); if (pAppCapItem != NULL) { DBG_SAVE_FILE_LINE pAppCapItem->pCapID = new CCapIDContainer( &capabilities_list[i]->capability_id, &rc); if ((pAppCapItem->pCapID != NULL) && (rc == GCC_NO_ERROR)) { if (capabilities_list[i]->capability_class.eType == GCC_UNSIGNED_MINIMUM_CAPABILITY) { pAppCapItem->nUnsignedMinimum = capabilities_list[i]->capability_class.nMinOrMax; } else if (capabilities_list[i]->capability_class.eType == GCC_UNSIGNED_MAXIMUM_CAPABILITY) { pAppCapItem->nUnsignedMaximum = capabilities_list[i]->capability_class.nMinOrMax; } pAppCapItem->cEntries = 1; /* * Add this capability to the list. */ m_AppCapItemList.Append(pAppCapItem); } else if (pAppCapItem->pCapID == NULL) { rc = GCC_ALLOCATION_FAILURE; } else { delete pAppCapItem; } } else { rc = GCC_ALLOCATION_FAILURE; } if (rc != GCC_NO_ERROR) break; } *pRetCode = rc; } /* * ~CAppCap() * * Public Function Description * The CAppCap destructor is responsible for freeing * any memory allocated to hold the capability data. * */ CAppCap::~CAppCap(void) { m_AppCapItemList.DeleteList(); } /* * LockCapabilityData () * * Public Function Description: * This routine locks the capability data and determines the amount of * memory referenced by the "API" non-collapsing capability data structure. */ UINT CAppCap::LockCapabilityData(void) { /* * If this is the first time this routine is called, determine the size of * the memory required to hold the data referenced by the list of * capabilities. Otherwise, just increment the lock count. */ if (Lock() == 1) { APP_CAP_ITEM *pAppCapItem; /* * Add the amount of memory necessary to hold the string data associated * with each capability ID. */ m_AppCapItemList.Reset(); /* * Lock the data for each capability ID. The lock call returns the * length of the data referenced by each capability ID rounded to occupy * an even multiple of four-bytes. */ while (NULL != (pAppCapItem = m_AppCapItemList.Iterate())) { m_cbDataSize += pAppCapItem->pCapID->LockCapabilityIdentifierData(); } /* * Add the memory to hold the application capability pointers * and structures. */ m_cbDataSize += m_AppCapItemList.GetCount() * (sizeof (PGCCApplicationCapability) + ROUNDTOBOUNDARY( sizeof(GCCApplicationCapability)) ); } return m_cbDataSize; } /* * GetGCCApplicationCapabilityList () * * Public Function Description: * This routine retrieves the application capabilities list in the form of * a list of PGCCApplicationCapability's. This routine is called after * "locking" the capability data. */ UINT CAppCap::GetGCCApplicationCapabilityList( PUShort number_of_capabilities, PGCCApplicationCapability * * capabilities_list, LPBYTE memory) { UINT cbDataSizeToRet = 0; /* * If the capability data has been locked, fill in the output structure and * the data referenced by the structure. */ if (GetLockCount() > 0) { UINT data_length = 0; UINT capability_id_data_length = 0; USHORT capability_count; PGCCApplicationCapability gcc_capability; PGCCApplicationCapability * gcc_capability_list; APP_CAP_ITEM *pAppCapItem; /* * Fill in the output length parameter which indicates how much data * referenced outside the structure will be written. */ cbDataSizeToRet = m_cbDataSize; /* * Retrieve the number of capabilities and fill in any that are present. */ *number_of_capabilities = (USHORT) m_AppCapItemList.GetCount(); if (*number_of_capabilities != 0) { /* * Fill in the pointer to the list of application capability * pointers. The pointer list will begin at the memory location * passed into this routine. Save the list pointer in a local * variable for convenience. */ *capabilities_list = (PGCCApplicationCapability *)memory; gcc_capability_list = *capabilities_list; /* * Move the memory pointer past the list of capability pointers. * This is where the first application capability structure will be * written. */ memory += (*number_of_capabilities * sizeof(PGCCApplicationCapability)); /* * Add to the data length the amount of memory necessary to hold the * application capability pointers. Go ahead and add the amount of * memory necessary to hold all of the GCCApplicationCapability * structures. */ data_length += *number_of_capabilities * (sizeof(PGCCApplicationCapability) + ROUNDTOBOUNDARY ( sizeof(GCCApplicationCapability)) ); /* * Iterate through the capabilities list, building an "API" * capability for each capability in the list. */ capability_count = 0; m_AppCapItemList.Reset(); while (NULL != (pAppCapItem = m_AppCapItemList.Iterate())) { /* * Set the application capability pointer equal to the * location in memory where it will be written. */ gcc_capability = (PGCCApplicationCapability)memory; /* * Save the pointer to the application capability in the * list of application capability pointers. */ gcc_capability_list[capability_count] = gcc_capability; /* * Advance the memory pointer past the application capability * structure. This is where the string data for the capability * ID will be written. Ensure that the memory pointer falls on * an even four-byte boundary. */ memory += ROUNDTOBOUNDARY(sizeof(GCCApplicationCapability)); /* * Retrieve the capability ID information from the internal * CapabilityIDData object. The length returned by this call * will have already been rounded to an even multiple of four * bytes. */ capability_id_data_length = pAppCapItem->pCapID-> GetGCCCapabilityIDData(&gcc_capability->capability_id, memory); /* * Advance the memory pointer past the string data written into * memory by the capability ID object. Add the length of the * string data to the overall capability length. */ memory += capability_id_data_length; data_length += capability_id_data_length; /* * Now fill in the rest of the capability. */ gcc_capability->capability_class.eType = pAppCapItem->eCapType; if (gcc_capability->capability_class.eType == GCC_UNSIGNED_MINIMUM_CAPABILITY) { gcc_capability->capability_class.nMinOrMax = pAppCapItem->nUnsignedMinimum; } else if (gcc_capability->capability_class.eType == GCC_UNSIGNED_MAXIMUM_CAPABILITY) { gcc_capability->capability_class.nMinOrMax = pAppCapItem->nUnsignedMaximum; } gcc_capability->number_of_entities = pAppCapItem->cEntries; /* * Increment the capability array counter. */ capability_count++; } } else { cbDataSizeToRet = 0; capabilities_list = NULL; } } else { ERROR_OUT(("CAppCap::GetData: Error: data not locked")); } return (cbDataSizeToRet); } /* * UnLockCapabilityData () * * Public Function Description: * This routine decrements the lock count and frees the memory associated * with the "API" capability once the lock count reaches zero. */ void CAppCap::UnLockCapabilityData(void) { if (Unlock(FALSE) == 0) { APP_CAP_ITEM *pAppCapItem; /* * Iterate through the list of collapsed capabilities, unlocking the * data for each CapabilityIDData object associated with each * capability. */ m_AppCapItemList.Reset(); while (NULL != (pAppCapItem = m_AppCapItemList.Iterate())) { pAppCapItem->pCapID->UnLockCapabilityIdentifierData(); } } // we have to call Release() because we used Unlock(FALSE) Release(); } APP_CAP_ITEM::APP_CAP_ITEM(GCCCapabilityType eCapType) : pCapID(NULL), eCapType(eCapType), cEntries(0), poszAppData(NULL) { } APP_CAP_ITEM::APP_CAP_ITEM(APP_CAP_ITEM *p, PGCCError pError) : poszAppData(NULL) { // First set up the capability id DBG_SAVE_FILE_LINE pCapID = new CCapIDContainer(p->pCapID, pError); if (NULL != pCapID) { // Initialize the new capability to default values. eCapType = p->eCapType; if (p->eCapType == GCC_UNSIGNED_MINIMUM_CAPABILITY) { nUnsignedMinimum = (UINT) -1; } else if (p->eCapType == GCC_UNSIGNED_MAXIMUM_CAPABILITY) { nUnsignedMaximum = 0; } cEntries = p->cEntries; // // LONCHANC: We do not copy the entries in application data??? // *pError = GCC_NO_ERROR; } else { *pError = GCC_ALLOCATION_FAILURE; } } APP_CAP_ITEM::~APP_CAP_ITEM(void) { if (NULL != pCapID) { pCapID->Release(); } delete poszAppData; } void CAppCapItemList::DeleteList(void) { APP_CAP_ITEM *pAppCapItem; while (NULL != (pAppCapItem = Get())) { delete pAppCapItem; } }