#include "precomp.h" DEBUG_FILEZONE(ZONE_T120_GCCNC); /* * invoklst.cpp * * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY * * Abstract: * This is the implementation file for the class * CInvokeSpecifierListContainer. This class manages the data associated * with an Application Invoke Request or Indication. This includes a list * of applications to be invoked. The CInvokeSpecifierListContainer data * container utilizes a CSessKeyContainer container to buffer part of the data * associated with each application invoke specifier. Each application * invoke specifier also includes a capability ID whose data is buffered * internally by the using a CCapIDContainer container. The list * of application invoke specifiers is maintained internally by the class * through the use of a Rogue Wave list container. * * Protected Instance Variables: * m_InvokeSpecifierList * List of structures used to hold the container data internally. * m_pAPEListPDU * Storage for the "PDU" form of the invoke data. * m_fValidAPEListPDU * Flag indicating that memory has been allocated to hold the internal * "PDU" invoke data. * m_cbDataSize * Variable holding the size of the memory which will be required to * hold any data referenced by the "API" structure. * * Caveats: * None. * * Author: * blp/jbo */ #include "ms_util.h" #include "invoklst.h" /* * CInvokeSpecifierListContainer () * * Public Function Description: * This constructor is used to create an CInvokeSpecifierListContainer * object from a list of "API" application protocol entities. */ CInvokeSpecifierListContainer::CInvokeSpecifierListContainer( UINT number_of_protocol_entities, PGCCAppProtocolEntity * app_protocol_entity_list, PGCCError pRetCode) : CRefCount(MAKE_STAMP_ID('I','S','L','C')), m_fValidAPEListPDU(FALSE), m_cbDataSize(0) { UINT i; PGCCAppProtocolEntity ape; INVOKE_SPECIFIER *specifier_info; /* * Initialize instance variables. */ GCCError rc = GCC_NO_ERROR; /* * Go through the list of application protocol entities (APE's), saving the * necessary information in the internal list of info. structures. */ for (i = 0; i < number_of_protocol_entities; i++) { /* * Create a new INVOKE_SPECIFIER structure to hold the data for this * APE. Check to make sure it was successfully created. */ DBG_SAVE_FILE_LINE specifier_info = new INVOKE_SPECIFIER; if (specifier_info != NULL) { /* * Get the APE from the list. */ ape = app_protocol_entity_list[i]; /* * Create a new CSessKeyContainer object to hold the session key. * Check to make sure construction was successful. */ DBG_SAVE_FILE_LINE specifier_info->session_key = new CSessKeyContainer(&ape->session_key, &rc); if ((specifier_info->session_key != NULL) && (rc == GCC_NO_ERROR)) { /* * Save the startup channel type and "invoke" flag. */ specifier_info->startup_channel_type =ape->startup_channel_type; specifier_info->must_be_invoked = ape->must_be_invoked; /* * Save the capabilities list for this APE in the internal info. * structure. */ rc = SaveAPICapabilities(specifier_info, ape->number_of_expected_capabilities, ape->expected_capabilities_list); /* * Insert the new invoke specifier info structure pointer into * the internal list if no error condition exists. */ if (rc == GCC_NO_ERROR) { m_InvokeSpecifierList.Append(specifier_info); } else { ERROR_OUT(("CInvokeSpecifierListContainer::Construc1: Error saving caps")); break; } } else if (specifier_info->session_key == NULL) { ERROR_OUT(("CInvokeSpecifierListContainer::Construc1: Error creating CSessKeyContainer")); rc = GCC_ALLOCATION_FAILURE; break; } else { break; } } else { ERROR_OUT(("CInvokeSpecifierListContainer::Construc1: Error creating INVOKE_SPECIFIER")); break; } } if(rc != GCC_NO_ERROR) { if(specifier_info) { ERROR_OUT(("CInvokeSpecifierListContainer::Construc1: Error creating CSessKeyContainer")); if(specifier_info->session_key) { specifier_info->session_key->Release(); } delete specifier_info; } } *pRetCode = rc; } /* * CInvokeSpecifierListContainer () * * Public Function Description: * This constructor is used to create an CInvokeSpecifierListContainer * object from a "PDU" ApplicationProtocolEntityList. */ CInvokeSpecifierListContainer::CInvokeSpecifierListContainer ( PApplicationProtocolEntityList protocol_entity_list, PGCCError pRetCode) : CRefCount(MAKE_STAMP_ID('I','S','L','C')), m_fValidAPEListPDU(FALSE), m_cbDataSize(0) { ApplicationInvokeSpecifier specifier; INVOKE_SPECIFIER *specifier_info; GCCError rc = GCC_NO_ERROR; while (protocol_entity_list != NULL) { /* * Create a new INVOKE_SPECIFIER structure to hold the data for this * APE. Check to make sure it was successfully created. */ DBG_SAVE_FILE_LINE specifier_info = new INVOKE_SPECIFIER; if (specifier_info != NULL) { specifier = protocol_entity_list->value; /* * Create a CSessKeyContainer object to hold the session key * internally. Check to make sure the object is successfully * created. */ DBG_SAVE_FILE_LINE specifier_info->session_key = new CSessKeyContainer(&specifier.session_key, &rc); if ((specifier_info->session_key != NULL) && (rc == GCC_NO_ERROR)) { /* * The session key was saved correctly so check to see if a list * of expected capabilities is present and save them if so. */ if (specifier.bit_mask & EXPECTED_CAPABILITY_SET_PRESENT) { rc = SavePDUCapabilities(specifier_info, specifier.expected_capability_set); if (rc != GCC_NO_ERROR) { specifier_info->session_key->Release(); specifier_info->ExpectedCapItemList.DeleteList(); delete specifier_info; break; } } /* * Save the startup channel type. If the channel type is not * present in the PDU then set the channel type in the info * strucuture equal to MCS_NO_CHANNEL_TYPE_SPECIFIED; */ if (specifier.bit_mask & INVOKE_STARTUP_CHANNEL_PRESENT) { switch (specifier.invoke_startup_channel) { case CHANNEL_TYPE_STATIC: specifier_info->startup_channel_type = MCS_STATIC_CHANNEL; break; case DYNAMIC_MULTICAST: specifier_info->startup_channel_type = MCS_DYNAMIC_MULTICAST_CHANNEL; break; case DYNAMIC_PRIVATE: specifier_info->startup_channel_type = MCS_DYNAMIC_PRIVATE_CHANNEL; break; case DYNAMIC_USER_ID: specifier_info->startup_channel_type = MCS_DYNAMIC_USER_ID_CHANNEL; break; } } else { specifier_info->startup_channel_type = MCS_NO_CHANNEL_TYPE_SPECIFIED; } /* * Insert the new invoke specifier info structure pointer into * the internal list if no error condition exists. */ m_InvokeSpecifierList.Append(specifier_info); } else if (specifier_info->session_key == NULL) { ERROR_OUT(("CInvokeSpecifierListContainer::Construc2: Error creating CSessKeyContainer")); rc = GCC_ALLOCATION_FAILURE; break; } else { ERROR_OUT(("CInvokeSpecifierListContainer::Construc2: Error creating CSessKeyContainer")); break; } /* * Retrieve the next APE in the list. */ protocol_entity_list = protocol_entity_list->next; } else { ERROR_OUT(("CInvokeSpecifierListContainer::Construc2: Error creating INVOKE_SPECIFIER")); break; } } if(rc != GCC_NO_ERROR && specifier_info != NULL) { if(specifier_info->session_key != NULL) { specifier_info->session_key->Release(); } specifier_info->ExpectedCapItemList.DeleteList(); delete specifier_info; } *pRetCode = rc; } /* * ~CInvokeSpecifierListContainer () * * Public Function Description * The CInvokeSpecifierListContainer destructor is responsible for * freeing any memory allocated to hold the invoke data. * */ CInvokeSpecifierListContainer::~CInvokeSpecifierListContainer(void) { INVOKE_SPECIFIER *lpInvSpecInfo; /* * If "PDU" data has been allocated for this object, free it now. */ if (m_fValidAPEListPDU) FreeApplicationInvokeSpecifierListPDU (); /* * Delete any data containers held internally in the list of info. * structures by iterating through the internal list. */ m_InvokeSpecifierList.Reset(); while (NULL != (lpInvSpecInfo = m_InvokeSpecifierList.Iterate())) { /* * Delete any CSessKeyContainer objects in the INVOKE_SPECIFIER list. */ if (NULL != lpInvSpecInfo->session_key) { lpInvSpecInfo->session_key->Release(); } /* * Iterate through the capabilities list held in the INVOKE_SPECIFIER * structure. */ lpInvSpecInfo->ExpectedCapItemList.DeleteList(); /* * Delete the INVOKE_SPECIFIER structure. */ delete lpInvSpecInfo; } } /* * LockApplicationInvokeSpecifierList () * * Public Function Description: * This routine locks the invoke specifier data and determines the amount * of memory necessary to hold the associated data. */ UINT CInvokeSpecifierListContainer::LockApplicationInvokeSpecifierList(void) { /* * If this is the first time this routine is called, determine the size of * the memory required to hold the data for the application invoke * specifier. Otherwise, just increment the lock count. */ if (Lock() == 1) { INVOKE_SPECIFIER *lpInvSpecInfo; APP_CAP_ITEM *pExpCapData; /* * Set aside memory to hold the pointers to the GCCAppProtocolEntity * structures as well as the structures themselves. The "sizeof" the * structure must be rounded to an even four-byte boundary. */ m_cbDataSize = m_InvokeSpecifierList.GetCount() * (sizeof(PGCCAppProtocolEntity) + ROUNDTOBOUNDARY(sizeof(GCCAppProtocolEntity))); m_InvokeSpecifierList.Reset(); while (NULL != (lpInvSpecInfo = m_InvokeSpecifierList.Iterate())) { /* * Lock the data for the session keys, adding the amount of memory * necessary to hold the session key data to the total memory size. */ m_cbDataSize += lpInvSpecInfo->session_key->LockSessionKeyData(); lpInvSpecInfo->ExpectedCapItemList.Reset(); /* * Set aside memory to hold the pointers to the * GCCApplicationCabability structures as well as the structures * themselves. The "sizeof" the structure must be rounded to an * even four-byte boundary. */ m_cbDataSize += lpInvSpecInfo->ExpectedCapItemList.GetCount() * ( sizeof(PGCCApplicationCapability) + ROUNDTOBOUNDARY (sizeof(GCCApplicationCapability)) ); /* * Lock the data for the capability ID's, adding the amount of * memory necessary to hold the capability ID data to the total * memory size. */ while (NULL != (pExpCapData = lpInvSpecInfo->ExpectedCapItemList.Iterate())) { m_cbDataSize += pExpCapData->pCapID->LockCapabilityIdentifierData(); } } } return m_cbDataSize; } /* * GetApplicationInvokeSpecifierList () * * Public Function Description: * This routine retrieves the invoke specifier data in the form of a * list of application protocol entities which are written into the memory * provided. This routine is called after "locking" the data. */ UINT CInvokeSpecifierListContainer::GetApplicationInvokeSpecifierList( USHORT *number_of_protocol_entities, LPBYTE memory) { PGCCAppProtocolEntity * ape_list_ptr; PGCCAppProtocolEntity ape_ptr; PGCCApplicationCapability capability_ptr; UINT data_length = 0; Int ape_counter = 0; Int capability_counter = 0; UINT cbDataSizeToRet = 0; INVOKE_SPECIFIER *lpInvSpecInfo; APP_CAP_ITEM *pExpCapData; /* * If the object has been locked, fill in the output structure and * the data referenced by the structure. Otherwise, report that the object * key has yet to be locked into the "API" form. */ if (GetLockCount() > 0) { /* * Fill in the output length parameter which indicates how much data * referenced outside the structure will be written. This value was * calculated on the call to "Lock". */ cbDataSizeToRet = m_cbDataSize; /* * Fill in the number of protocol entities and save a pointer to * the memory location passed in. This is where the pointers to * the GCCAppProtocolEntity structures will be written. The actual * structures will be written into memory immediately following the list * of pointers. */ *number_of_protocol_entities = (USHORT) m_InvokeSpecifierList.GetCount(); ape_list_ptr = (PGCCAppProtocolEntity *)memory; /* * Save the amount of memory needed to hold the list of structure * pointers. */ data_length = m_InvokeSpecifierList.GetCount() * sizeof(PGCCAppProtocolEntity); /* * Move the memory pointer past the list of APE pointers. This is where * thefirst APE structure will be written. */ memory += data_length; /* * Iterate through the internal list of INVOKE_SPECIFIER structures, * building "API" GCCAppProtocolEntity structures in memory. */ m_InvokeSpecifierList.Reset(); while (NULL != (lpInvSpecInfo = m_InvokeSpecifierList.Iterate())) { /* * Save the pointer to the APE structure in the list of pointers. */ ape_ptr = (PGCCAppProtocolEntity)memory; ape_list_ptr[ape_counter++] = ape_ptr; /* * Move the memory pointer past the APE structure. This is where * thesession key data will be written. */ memory += ROUNDTOBOUNDARY(sizeof(GCCAppProtocolEntity)); /* * Fill in the APE structure starting with the session key. */ data_length = lpInvSpecInfo->session_key->GetGCCSessionKeyData(&ape_ptr->session_key, memory); /* * Move the memory pointer past the session key data. This is * where the list of pointers to the GCCApplicationCapability * structures will be written so save the pointer in the APE * structure's capabilities list pointer. */ memory += data_length; ape_ptr->expected_capabilities_list = (PGCCApplicationCapability *)memory; /* * Go ahead and fill in the APE's channel type and invoke flag. */ ape_ptr->must_be_invoked = lpInvSpecInfo->must_be_invoked; ape_ptr->startup_channel_type = lpInvSpecInfo->startup_channel_type; ape_ptr->number_of_expected_capabilities = (USHORT) lpInvSpecInfo->ExpectedCapItemList.GetCount(); /* * Move the memory pointer past the list of GCCApplicationCapability * pointers. This is where the first GCCApplicationCapability * structure will be written. */ memory += (lpInvSpecInfo->ExpectedCapItemList.GetCount() * sizeof(PGCCApplicationCapability)); /* * Iterate through the list of capabilities, writing the * GCCApplicationCapability structures into memory. */ capability_counter = 0; lpInvSpecInfo->ExpectedCapItemList.Reset(); while (NULL != (pExpCapData = lpInvSpecInfo->ExpectedCapItemList.Iterate())) { /* * Save the pointer to the capability structure in the list of * pointers. Move the memory pointer past the capability * structure. This is where the data associated with the * capability ID will be written. */ capability_ptr = (PGCCApplicationCapability)memory; ape_ptr->expected_capabilities_list[capability_counter++] = capability_ptr; memory += ROUNDTOBOUNDARY(sizeof(GCCApplicationCapability)); /* * Fill in the capability structure and add the amount of data * written into memory to the total data length. */ data_length = GetApplicationCapability(pExpCapData, capability_ptr, memory); /* * Move the memory pointer past the capability data. */ memory += data_length; } } } else { number_of_protocol_entities = 0; ERROR_OUT(("CInvokeSpecifierListContainer::GetAppInvokeSpecList: Error Data Not Locked")); } return cbDataSizeToRet; } /* * UnLockApplicationInvokeSpecifierList () * * Public Function Description: * This routine decrements the lock count and frees the memory associated * with the "API" invoke specifier list once the lock count reaches zero. */ void CInvokeSpecifierListContainer::UnLockApplicationInvokeSpecifierList(void) { if (Unlock(FALSE) == 0) { INVOKE_SPECIFIER *lpInvSpecInfo; APP_CAP_ITEM *pExpCapData; /* * Unlock any container data held internally in the list of info. * structures by iterating through the internal list. */ m_InvokeSpecifierList.Reset(); while (NULL != (lpInvSpecInfo = m_InvokeSpecifierList.Iterate())) { /* * Unlock any CSessKeyContainer objects. */ lpInvSpecInfo->session_key->UnLockSessionKeyData(); /* * Iterate through the capabilities list held in the * INVOKE_SPECIFIER structure. */ lpInvSpecInfo->ExpectedCapItemList.Reset(); while (NULL != (pExpCapData = lpInvSpecInfo->ExpectedCapItemList.Iterate())) { /* * Unlock the CCapIDContainer objects. */ pExpCapData->pCapID->UnLockCapabilityIdentifierData(); } } } // we have to call Release() because we used Unlock(FALSE) Release(); } /* * GetApplicationInvokeSpecifierListPDU () * * Public Function Description: * This routine retrieves the "PDU" form of an * ApplicationProtocolEntityList. */ GCCError CInvokeSpecifierListContainer::GetApplicationInvokeSpecifierListPDU( PApplicationProtocolEntityList *protocol_entity_list) { GCCError rc = GCC_NO_ERROR; PApplicationProtocolEntityList new_pdu_ape_list_ptr; PApplicationProtocolEntityList old_pdu_ape_list_ptr = NULL; /* * If this is the first time that PDU data has been requested then we must * fill in the internal PDU structure and copy it into the structure pointed * to by the input parameter. On subsequent calls to "GetPDU" we can just * copy the internal PDU structure into the structure pointed to by the * input parameter. */ if (m_fValidAPEListPDU == FALSE) { INVOKE_SPECIFIER *lpInvSpecInfo; m_fValidAPEListPDU = TRUE; /* * Initialize the output parameter to NULL so that the first time * through the loop it will be set equal to the first new APE list * created in the iterator loop. */ m_pAPEListPDU = NULL; /* * Iterate through the list of "INVOKE_SPECIFIER" structures, * converting each into "PDU" form and saving the pointers in the * "ApplicationProtocolEntityList" which is a linked list of * "ApplicationInvokeSpecifiers". */ m_InvokeSpecifierList.Reset(); while (NULL != (lpInvSpecInfo = m_InvokeSpecifierList.Iterate())) { DBG_SAVE_FILE_LINE new_pdu_ape_list_ptr = new ApplicationProtocolEntityList; /* * If an allocation failure occurs, call the routine which will * iterate through the list freeing any data which had been * allocated. */ if (new_pdu_ape_list_ptr == NULL) { ERROR_OUT(("CInvokeSpecifierListContainer::GetApplicationInvokeSpecifierListPDU: can't allocate ApplicationProtocolEntityList")); rc = GCC_ALLOCATION_FAILURE; FreeApplicationInvokeSpecifierListPDU (); break; } /* * The first time through, set the PDU structure pointer equal * to the first ApplicationProtocolEntityList created. On * subsequent loops, set the structure's "next" pointer equal to * the new structure. */ if (m_pAPEListPDU == NULL) { m_pAPEListPDU = new_pdu_ape_list_ptr; } else { old_pdu_ape_list_ptr->next = new_pdu_ape_list_ptr; } old_pdu_ape_list_ptr = new_pdu_ape_list_ptr; /* * Initialize the new "next" pointer to NULL. */ new_pdu_ape_list_ptr->next = NULL; if (ConvertInvokeSpecifierInfoToPDU (lpInvSpecInfo, new_pdu_ape_list_ptr) != GCC_NO_ERROR) { ERROR_OUT(("CInvokeSpecifierListContainer::GetApplicationInvokeSpecifierListPDU: can't convert UserDataInfo to PDU")); rc = GCC_ALLOCATION_FAILURE; break; } } } /* * Copy the internal PDU structure into the structure pointed to by the * input parameter. */ *protocol_entity_list = m_pAPEListPDU; return rc; } /* * FreeApplicationInvokeSpecifierListPDU () * * Public Function Description: * This routine is used to free the invoke specifier data held internally * in the "PDU" form of a "ApplicationProtocolEntityList". */ void CInvokeSpecifierListContainer::FreeApplicationInvokeSpecifierListPDU(void) { PApplicationProtocolEntityList pCurr, pNext; INVOKE_SPECIFIER *lpInvSpecInfo; APP_CAP_ITEM *pExpCapData; if (m_pAPEListPDU != NULL) { m_fValidAPEListPDU = FALSE; /* * Loop through the list, freeing the data associated with * each structure contained in the list. */ for (pCurr = m_pAPEListPDU; NULL != pCurr; pCurr = pNext) { pNext = pCurr->next; delete pCurr; } } /* * Iterate through the internal list, telling each data container object * to free any PDU data which it has allocated. */ m_InvokeSpecifierList.Reset(); while (NULL != (lpInvSpecInfo = m_InvokeSpecifierList.Iterate())) { if (lpInvSpecInfo->session_key != NULL) { lpInvSpecInfo->session_key->FreeSessionKeyDataPDU(); } /* * Iterate through the * list, freeing the PDU data for the capability ID's. */ lpInvSpecInfo->ExpectedCapItemList.Reset(); while (NULL != (pExpCapData = lpInvSpecInfo->ExpectedCapItemList.Iterate())) { pExpCapData->pCapID->FreeCapabilityIdentifierDataPDU(); } } } /* * GCCError CInvokeSpecifierListContainer::SaveAPICapabilities ( * INVOKE_SPECIFIER *invoke_specifier, * UINT number_of_capabilities, * PGCCApplicationCapability * capabilities_list) * * Private member function of CInvokeSpecifierListContainer. * * Function Description: * This routine is used to save the list of application capabilities passed * in as "API" data in the internal list of expected capability data * which is held in the internal info structure. * * Formal Parameters: * invoke_specifier (i) Internal structure used to hold invoke data. * number_of_capabilities (i) Number of capabilities in list. * capabilities_list (i) List of API capabilities to save. * * Return Value: * None. * * Side Effects: * None. * * Caveats: * None. */ GCCError CInvokeSpecifierListContainer::SaveAPICapabilities( INVOKE_SPECIFIER *invoke_specifier, UINT number_of_capabilities, PGCCApplicationCapability * capabilities_list) { GCCError rc = GCC_NO_ERROR; APP_CAP_ITEM *pExpCapData; UINT i; for (i = 0; i < number_of_capabilities; i++) { /* * For each capability, create an APP_CAP_ITEM structure * to hold all the necessary data. This structure will be inserted into * the list held by the internal info. structure. */ DBG_SAVE_FILE_LINE pExpCapData = new APP_CAP_ITEM((GCCCapabilityType) capabilities_list[i]->capability_class.eType); if (pExpCapData != NULL) { /* * Create a new CCapIDContainer object to hold the * identifier data. */ DBG_SAVE_FILE_LINE pExpCapData->pCapID = new CCapIDContainer(&capabilities_list[i]->capability_id, &rc); if ((pExpCapData->pCapID != NULL) && (rc == GCC_NO_ERROR)) { /* * The identifier object was successfully created so fill in the * rest of the ApplicationCapabilityData structure. */ switch (pExpCapData->eCapType) { case GCC_UNSIGNED_MINIMUM_CAPABILITY: pExpCapData->nUnsignedMinimum = capabilities_list[i]->capability_class.nMinOrMax; break; case GCC_UNSIGNED_MAXIMUM_CAPABILITY: pExpCapData->nUnsignedMaximum = capabilities_list[i]->capability_class.nMinOrMax; break; } /* * Add this expected capability to the list. */ invoke_specifier->ExpectedCapItemList.Append(pExpCapData); } else { delete pExpCapData; rc = GCC_ALLOCATION_FAILURE; break; } } else { rc = GCC_ALLOCATION_FAILURE; break; } } return rc; } /* * GCCError CInvokeSpecifierListContainer::SavePDUCapabilities ( * INVOKE_SPECIFIER *invoke_specifier, * PSetOfExpectedCapabilities capabilities_set) * * Private member function of CInvokeSpecifierListContainer. * * Function Description: * This routine is used to save the list of application capabilities passed * in as "PDU" data in the internal list of expected capability data * which is held in the internal info. structure. * * Formal Parameters: * invoke_specifier (i) Internal structure used to hold invoke data. * capabilities_set (i) List of PDU capabilities to save. * * Return Value: * None. * * Side Effects: * None. * * Caveats: * None. */ GCCError CInvokeSpecifierListContainer::SavePDUCapabilities( INVOKE_SPECIFIER *invoke_specifier, PSetOfExpectedCapabilities capabilities_set) { GCCError rc = GCC_NO_ERROR; APP_CAP_ITEM *pExpCapData; while ((capabilities_set != NULL) && (rc == GCC_NO_ERROR)) { /* * Create and fill in the new expected capability. */ DBG_SAVE_FILE_LINE pExpCapData = new APP_CAP_ITEM((GCCCapabilityType) capabilities_set->value.capability_class.choice); if (pExpCapData != NULL) { /* * Create the CCapIDContainer object used to hold the * capability ID data internally. Make sure creation is successful. */ DBG_SAVE_FILE_LINE pExpCapData->pCapID = new CCapIDContainer(&capabilities_set->value.capability_id, &rc); if (pExpCapData->pCapID == NULL || rc != GCC_NO_ERROR) { rc = GCC_ALLOCATION_FAILURE; delete pExpCapData; } } else { rc = GCC_ALLOCATION_FAILURE; } /* * The capability ID was saved successfully, so go ahead and insert * the expected capability data structure into the internal list. * Fill in the capability class data. */ if (rc == GCC_NO_ERROR) { invoke_specifier->ExpectedCapItemList.Append(pExpCapData); /* * Save the capability type and value. */ switch (capabilities_set->value.capability_class.choice) { case UNSIGNED_MINIMUM_CHOSEN: pExpCapData->nUnsignedMinimum = capabilities_set->value.capability_class.u.unsigned_minimum; break; case UNSIGNED_MAXIMUM_CHOSEN: pExpCapData->nUnsignedMaximum = capabilities_set->value.capability_class.u.unsigned_maximum; break; } } capabilities_set = capabilities_set->next; } return rc; } /* * UINT CInvokeSpecifierListContainer::GetApplicationCapability ( * APP_CAP_ITEM *capability_info_data, * PGCCApplicationCapability api_capability, * LPSTR memory) * * Private member function of CInvokeSpecifierListContainer. * * Function Description: * This routine is used to fill in an API GCCApplicationCapability * structure from an internal info structure. * * Formal Parameters: * capability_info_data (i) Internal capability data to convert into * API data. * api_capability (o) Structure to hold data in API form. * memory (o) Memory used to hold bulk data referenced by * the API structure. * * Return Value: * None. * * Side Effects: * None. * * Caveats: * None. */ UINT CInvokeSpecifierListContainer::GetApplicationCapability( APP_CAP_ITEM *pExpCapData, PGCCApplicationCapability api_capability, LPBYTE memory) { UINT data_length = 0; /* * Call the CapabilityID object to retrieve the capability ID data. */ data_length = pExpCapData->pCapID->GetGCCCapabilityIDData( &api_capability->capability_id, memory); /* * Fill in the remaining fields for the GCCApplicationCapability structure. */ api_capability->capability_class.eType = pExpCapData->eCapType; switch (pExpCapData->eCapType) { case GCC_UNSIGNED_MINIMUM_CAPABILITY: api_capability->capability_class.nMinOrMax = pExpCapData->nUnsignedMinimum; break; case GCC_UNSIGNED_MAXIMUM_CAPABILITY: api_capability->capability_class.nMinOrMax = pExpCapData->nUnsignedMaximum; break; } /* * Fill in the number of entities. Note, however, that this field will not * be used in this context. */ api_capability->number_of_entities = 0; return (data_length); } /* * GCCError CInvokeSpecifierListContainer::ConvertInvokeSpecifierInfoToPDU( * INVOKE_SPECIFIER *specifier_info_ptr, * PApplicationProtocolEntityList ape_list_ptr) * * Private member function of CInvokeSpecifierListContainer. * * Function Description: * This routine converts the invoke specifier from the internal form which * is an "INVOKE_SPECIFIER" structure into the "PDU" structure form of * a "ApplicationInvokeSpecifier". * * Formal Parameters: * specifier_info_ptr (i) Internal structure holding data to convert. * ape_list_ptr (o) PDU structure to hold converted data. * * Return Value: * None. * * Side Effects: * None. * * Caveats: * None. */ GCCError CInvokeSpecifierListContainer::ConvertInvokeSpecifierInfoToPDU ( INVOKE_SPECIFIER *specifier_info_ptr, PApplicationProtocolEntityList ape_list_ptr) { GCCError rc = GCC_NO_ERROR; PSetOfExpectedCapabilities new_capability_set_ptr; PSetOfExpectedCapabilities old_capability_set_ptr = NULL; /* * Initialize the invoke specifier bit mask to zero. */ ape_list_ptr->value.bit_mask = 0; /* * Fill in the session key PDU data using the CSessKeyContainer object. */ rc = specifier_info_ptr->session_key->GetSessionKeyDataPDU(&ape_list_ptr->value.session_key); /* * Fill in the capabilities list if any exist. */ if ((rc == GCC_NO_ERROR) && (specifier_info_ptr->ExpectedCapItemList.GetCount() != 0)) { APP_CAP_ITEM *pExpCapData; ape_list_ptr->value.bit_mask |= EXPECTED_CAPABILITY_SET_PRESENT; /* * Set the pointer to the capability set to NULL so that it will be * set equal to the first SetOfExpectedCapabilities created inside the * iterator loop. */ ape_list_ptr->value.expected_capability_set = NULL; /* * Iterate through the list of APP_CAP_ITEM structures, * converting each into "PDU" form and saving the pointers in the * "SetOfExpectedCapabilities. */ specifier_info_ptr->ExpectedCapItemList.Reset(); while (NULL != (pExpCapData = specifier_info_ptr->ExpectedCapItemList.Iterate())) { DBG_SAVE_FILE_LINE new_capability_set_ptr = new SetOfExpectedCapabilities; /* * If an allocation failure occurs, call the routine which will * iterate through the list freeing any data which had been * allocated. */ if (new_capability_set_ptr == NULL) { ERROR_OUT(("CInvokeSpecifierListContainer::ConvertToPDU: alloc error, cleaning up")); rc = GCC_ALLOCATION_FAILURE; FreeApplicationInvokeSpecifierListPDU(); break; } /* * The first time through, set the PDU structure pointer equal * to the first SetOfExpectedCapabilities created. On * subsequent loops, set the structure's "next" pointer equal to * the new structure. */ if (ape_list_ptr->value.expected_capability_set == NULL) { ape_list_ptr->value.expected_capability_set = new_capability_set_ptr; } else { old_capability_set_ptr->next = new_capability_set_ptr; } old_capability_set_ptr = new_capability_set_ptr; /* * Initialize the new "next" pointer to NULL. */ new_capability_set_ptr->next = NULL; if (ConvertExpectedCapabilityDataToPDU(pExpCapData, new_capability_set_ptr) != GCC_NO_ERROR) { ERROR_OUT(("CInvokeSpecifierListContainer::ConvertToPDU: Error converting Capability to PDU")); rc = GCC_ALLOCATION_FAILURE; break; } } } /* * Fill in the channel type if one is specified. */ if (specifier_info_ptr->startup_channel_type != MCS_NO_CHANNEL_TYPE_SPECIFIED) { ape_list_ptr->value.bit_mask |= INVOKE_STARTUP_CHANNEL_PRESENT; switch (specifier_info_ptr->startup_channel_type) { case MCS_STATIC_CHANNEL: ape_list_ptr->value.invoke_startup_channel = CHANNEL_TYPE_STATIC; break; case MCS_DYNAMIC_MULTICAST_CHANNEL: ape_list_ptr->value.invoke_startup_channel = DYNAMIC_MULTICAST; break; case MCS_DYNAMIC_PRIVATE_CHANNEL: ape_list_ptr->value.invoke_startup_channel = DYNAMIC_PRIVATE; break; case MCS_DYNAMIC_USER_ID_CHANNEL: ape_list_ptr->value.invoke_startup_channel = DYNAMIC_USER_ID; break; } } /* * Fill in the invoke flag. */ ape_list_ptr->value.invoke_is_mandatory = (ASN1bool_t)specifier_info_ptr->must_be_invoked; return rc; } /* * GCCError CInvokeSpecifierListContainer::ConvertExpectedCapabilityDataToPDU( * APP_CAP_ITEM *info_ptr, * PSetOfExpectedCapabilities pdu_ptr) * * Private member function of CInvokeSpecifierListContainer. * * Function Description: * This routine converts the capability ID from the internal form which * is an APP_CAP_ITEM structure into the "PDU" structure form * of a "SetOfExpectedCapabilities". * * Formal Parameters: * info_ptr (i) Internal structure holding data to convert. * pdu_ptr (o) PDU structure to hold converted data. * * Return Value: * None. * * Side Effects: * None. * * Caveats: * None. */ GCCError CInvokeSpecifierListContainer::ConvertExpectedCapabilityDataToPDU ( APP_CAP_ITEM *pExpCapData, PSetOfExpectedCapabilities pdu_ptr) { GCCError rc = GCC_NO_ERROR; /* * Retrieve the capability ID data from the internal * CCapIDContainer object. */ rc = pExpCapData->pCapID->GetCapabilityIdentifierDataPDU(&pdu_ptr->value.capability_id); /* * Fill in the capability class. */ if (rc == GCC_NO_ERROR) { switch (pExpCapData->eCapType) { case GCC_LOGICAL_CAPABILITY: pdu_ptr->value.capability_class.choice = LOGICAL_CHOSEN; break; case GCC_UNSIGNED_MINIMUM_CAPABILITY: pdu_ptr->value.capability_class.choice = UNSIGNED_MINIMUM_CHOSEN; pdu_ptr->value.capability_class.u.unsigned_minimum = pExpCapData->nUnsignedMinimum; break; case GCC_UNSIGNED_MAXIMUM_CAPABILITY: pdu_ptr->value.capability_class.choice = UNSIGNED_MAXIMUM_CHOSEN; pdu_ptr->value.capability_class.u.unsigned_maximum = pExpCapData->nUnsignedMaximum; break; } } return rc; }