#include "precomp.h" DEBUG_FILEZONE(ZONE_T120_GCCNC); /* * conflist.cpp * * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY * * Abstract: * This is the implementation file for the class CConfDescriptorListContainer. * Instances of this class represent the Conference Descriptor list that is * generated by a call to GCCConferenceQueryRequest. This class hides most * of the complexity associated with building this list. It also handles * building the set of conference descriptors used in the * ConferenceQueryResponse PDU and the conference descriptor list passed * to the GCC interface. This class is designed so that a CControlSAP * object can use it to create a GCC_CONFERENCE_QUERY_CONFIRM message by * requesting a pointer to a list of Conference Descriptor pointers from * it. Objects of this type only live long enough to service a particular * query request. After a message callback has returned or a PDU has been * sent to MCS, the CConfDescriptorListContainer object is deleted. * * Protected Instance Variables: * m_ppGCCConfDescriptorList * The list holding the conference descriptors in the API form. * m_pSetOfConfDescriptors * The list holding the conference descriptors in the PDU form. * m_cDescriptors * The number of descriptors in the list. * m_pDescriptorListMemory * The memory object used to hold the memory for the API list of * conference descriptors. * m_ConfDescriptorList * The Rogue Wave list used to hold the descriptor data in the * internal form. * m_pNetAddrListMemory * The memory object used to hold the memory for the network address * list part of the API conference descriptor list. * m_pNetAddrMemoryPointer * A pointer used to keep track of where the network addresses for * the API form of the descriptor list are written. * * Private Member Functions: * GetConferenceDescriptor * The routine used to fill in an API conference descriptor * structure from an internal descriptor data structure. * * Caveats: * The set of conference descriptors uses pointers owned by the conferences * pointed to by the passed in list. Therefore, it is important not to * use the set of descriptors held by this class after a conference is * deleted. At this point the set of descriptors is invalid. Ideally, * the decriptor set built by this class should be used immediately after * construction. * * Author: * blp */ #include "ms_util.h" #include "conflist.h" CONF_DESCRIPTOR::CONF_DESCRIPTOR(void) : pszNumericConfName(NULL), pwszTextConfName(NULL), pszConfModifier(NULL), pwszConfDescription(NULL), network_address_list(NULL) { } CONF_DESCRIPTOR::~CONF_DESCRIPTOR(void) { delete pszNumericConfName; delete pwszTextConfName; delete pszConfModifier; delete pwszConfDescription; if (NULL != network_address_list) { network_address_list->Release(); } } /* * CConfDescriptorListContainer () * * Public Function Description * This is a constructor for the CConfDescriptorListContainer class. It * saves the memory manager which is passed in and initializes instance * variables. */ CConfDescriptorListContainer::CConfDescriptorListContainer(void) : CRefCount(MAKE_STAMP_ID('C','D','L','C')), m_ppGCCConfDescriptorList(NULL), m_pSetOfConfDescriptors(NULL), m_pDescriptorListMemory(NULL), m_pNetAddrListMemory(NULL), m_pNetAddrMemoryPointer(NULL), m_cDescriptors(0) { } /* * CConfDescriptorListContainer () * * Public Function Description * This constructor builds a List of conference descriptors that can * be passed on to the GCC interface. This list is built from a set * of conference descriptors which is part of a query response PDU. */ CConfDescriptorListContainer::CConfDescriptorListContainer( PSetOfConferenceDescriptors conference_list, PGCCError gcc_error) : CRefCount(MAKE_STAMP_ID('C','D','L','C')), m_ppGCCConfDescriptorList(NULL), m_pSetOfConfDescriptors(NULL), m_pDescriptorListMemory(NULL), m_pNetAddrListMemory(NULL), m_pNetAddrMemoryPointer(NULL), m_cDescriptors(0) { PSetOfConferenceDescriptors descriptor_pdu; CONF_DESCRIPTOR *descriptor_data; GCCError error_value; /* * Initialize the return parameter and instance variables. */ *gcc_error = GCC_NO_ERROR; descriptor_pdu = conference_list; while (descriptor_pdu != NULL) { /* * Allocate the structure used to hold internal data. */ DBG_SAVE_FILE_LINE descriptor_data = new CONF_DESCRIPTOR; if (descriptor_data == NULL) { *gcc_error = GCC_ALLOCATION_FAILURE; break; } /* * Fill in the descriptor flags. */ descriptor_data->conference_is_locked = descriptor_pdu->value.conference_is_locked; descriptor_data->password_in_the_clear = descriptor_pdu->value.clear_password_required; /* * Copy the numeric portion of the conference name. */ descriptor_data->pszNumericConfName = ::My_strdupA(descriptor_pdu->value.conference_name.numeric); /* * Copy the text portion of the name if it exists. */ if (descriptor_pdu->value.conference_name.bit_mask & CONFERENCE_NAME_TEXT_PRESENT) { if (NULL == (descriptor_data->pwszTextConfName = ::My_strdupW2( descriptor_pdu->value.conference_name.conference_name_text.length, descriptor_pdu->value.conference_name.conference_name_text.value))) { *gcc_error = GCC_ALLOCATION_FAILURE; } } else { ASSERT(NULL == descriptor_data->pwszTextConfName); } /* * Next copy the conference name modifier if it exists. */ if (descriptor_pdu->value.bit_mask & CONFERENCE_NAME_MODIFIER_PRESENT) { if (NULL == (descriptor_data->pszConfModifier = ::My_strdupA( descriptor_pdu->value.conference_name_modifier))) { *gcc_error = GCC_ALLOCATION_FAILURE; } } else { ASSERT(NULL == descriptor_data->pszConfModifier); } /* * Next copy the conference description if it exists. */ if (descriptor_pdu->value.bit_mask & CONFERENCE_DESCRIPTION_PRESENT) { if (NULL == (descriptor_data->pwszConfDescription = ::My_strdupW2( descriptor_pdu->value.conference_description.length, descriptor_pdu->value.conference_description.value))) { *gcc_error = GCC_ALLOCATION_FAILURE; } } else { ASSERT(NULL == descriptor_data->pwszConfDescription); } /* * Next copy the network address list if it exists. */ if (descriptor_pdu->value.bit_mask & DESCRIPTOR_NET_ADDRESS_PRESENT) { DBG_SAVE_FILE_LINE descriptor_data->network_address_list = new CNetAddrListContainer( descriptor_pdu->value.descriptor_net_address, &error_value); if ((descriptor_data->network_address_list == NULL) || (error_value != GCC_NO_ERROR)) { *gcc_error = GCC_ALLOCATION_FAILURE; } } else { ASSERT(NULL == descriptor_data->network_address_list); } /* * If no error has occurred, set up the next pointer and add the data * structure to the list of conference descriptor data. */ if (*gcc_error == GCC_NO_ERROR) { descriptor_pdu = descriptor_pdu->next; m_ConfDescriptorList.Append(descriptor_data); } else { delete descriptor_data; break; } } } /* * ~CConfDescriptorListContainer () * * Public Function Description * This is the destructor for the CConfDescriptorListContainer class. It is * responsible for freeing up any resources allocated during the life of * this object. */ CConfDescriptorListContainer::~CConfDescriptorListContainer(void) { UINT i; CONF_DESCRIPTOR *lpConfDescData; if (m_pSetOfConfDescriptors != NULL) FreeConferenceDescriptorListPDU (); /* * Free all resources allocated by this object by iterating through the * internal list of decriptor data structures. */ m_ConfDescriptorList.Reset(); while (NULL != (lpConfDescData = m_ConfDescriptorList.Iterate())) { delete lpConfDescData; } /* * Free up any other allocated resources. */ if (m_pDescriptorListMemory != NULL) { for (i = 0; i < m_cDescriptors; i++) { delete m_ppGCCConfDescriptorList[i]; } delete m_pDescriptorListMemory; } delete m_pNetAddrListMemory; } /* * AddConferenceDescriptorToList () * * Public Function Description * This routine is used to add a single new conference descriptor to the * list of conference descriptors. */ GCCError CConfDescriptorListContainer::AddConferenceDescriptorToList( LPSTR pszNumericConfName, LPWSTR pwszConfTextName, LPSTR pszConfModifier, BOOL locked_conference, BOOL password_in_the_clear, LPWSTR pwszConfDescription, CNetAddrListContainer *network_address_list) { GCCError rc = GCC_NO_ERROR; CONF_DESCRIPTOR *descriptor_data; /* * If PDU data has been allocated, free it so that the next "GetPDU" call * will result in a rebuild of the PDU data and will therefore include the * data being added in this routine. */ if (m_pSetOfConfDescriptors != NULL) FreeConferenceDescriptorListPDU (); /* * Next allocate the structure used to hold the data internally. */ DBG_SAVE_FILE_LINE descriptor_data = new CONF_DESCRIPTOR; if (descriptor_data != NULL) { /* * Fill in the descriptor flags. */ descriptor_data->conference_is_locked = locked_conference; descriptor_data->password_in_the_clear = password_in_the_clear; /* * Copy the numeric portion of the conference name. */ if (pszNumericConfName != NULL) { descriptor_data->pszNumericConfName = ::My_strdupA(pszNumericConfName); } else { ASSERT(NULL == descriptor_data->pszNumericConfName); rc = GCC_ALLOCATION_FAILURE; } /* * Copy the text portion of the name if it exists */ if (pwszConfTextName != NULL) { if (NULL == (descriptor_data->pwszTextConfName = ::My_strdupW(pwszConfTextName))) { rc = GCC_ALLOCATION_FAILURE; } } else { ASSERT(NULL == descriptor_data->pwszTextConfName); } /* * Next copy the conference name modifier if it exists. */ if (pszConfModifier != NULL) { if (NULL == (descriptor_data->pszConfModifier = ::My_strdupA(pszConfModifier))) { rc = GCC_ALLOCATION_FAILURE; } } else { ASSERT(NULL == descriptor_data->pszConfModifier); } /* * Next copy the conference description if it exists. */ if (pwszConfDescription != NULL) { if (NULL == (descriptor_data->pwszConfDescription = ::My_strdupW(pwszConfDescription))) { rc = GCC_ALLOCATION_FAILURE; } } else { ASSERT(NULL == descriptor_data->pwszConfDescription); } /* * Next copy the network address list if it exists. */ if (network_address_list != NULL) { DBG_SAVE_FILE_LINE descriptor_data->network_address_list = new CNetAddrListContainer(network_address_list, &rc); if (descriptor_data->network_address_list == NULL) { rc = GCC_ALLOCATION_FAILURE; } } else { ASSERT(NULL == descriptor_data->network_address_list); } } else { rc = GCC_ALLOCATION_FAILURE; } if (GCC_NO_ERROR == rc) { /* * Add the structure to the descriptor list. */ m_ConfDescriptorList.Append(descriptor_data); } else { delete descriptor_data; } return rc; } /* * GetConferenceDescriptorListPDU () * * Public Function Description * This routine is used to retrieve the PDU form of the conference * descriptor list which is a list of "SetOfConferenceDescriptors" * structures. */ GCCError CConfDescriptorListContainer::GetConferenceDescriptorListPDU( PSetOfConferenceDescriptors * conference_list) { GCCError rc = GCC_NO_ERROR; PSetOfConferenceDescriptors last_descriptor = NULL; PSetOfConferenceDescriptors new_descriptor; CONF_DESCRIPTOR *descriptor_data; if (m_pSetOfConfDescriptors == NULL) { m_ConfDescriptorList.Reset(); while (NULL != (descriptor_data = m_ConfDescriptorList.Iterate())) { /* * First allocate the new descriptor. */ DBG_SAVE_FILE_LINE new_descriptor = new SetOfConferenceDescriptors; if (new_descriptor == NULL) { rc = GCC_ALLOCATION_FAILURE; break; } /* * Next we add the new descriptor to the list.. */ if (m_pSetOfConfDescriptors == NULL) m_pSetOfConfDescriptors = new_descriptor; else last_descriptor->next = new_descriptor; /* * Set up the previous descriptor pointer. */ last_descriptor = new_descriptor; /* * Now fill in the new descriptor with the passed in parameters. */ new_descriptor->next = NULL; new_descriptor->value.bit_mask = 0; new_descriptor->value.conference_is_locked = (ASN1bool_t)descriptor_data->conference_is_locked; new_descriptor->value.clear_password_required = (ASN1bool_t)descriptor_data->password_in_the_clear; /* * Get the numeric conference name. */ new_descriptor->value.conference_name.bit_mask = 0; ::lstrcpyA(new_descriptor->value.conference_name.numeric, descriptor_data->pszNumericConfName); /* * Get the text conference name, if it exists. */ if (descriptor_data->pwszTextConfName != NULL) { new_descriptor->value.conference_name.bit_mask |= CONFERENCE_NAME_TEXT_PRESENT; new_descriptor->value.conference_name.conference_name_text.value = descriptor_data->pwszTextConfName; new_descriptor->value.conference_name.conference_name_text.length = ::lstrlenW(descriptor_data->pwszTextConfName); } /* * Check for a conference name modifier. */ if (descriptor_data->pszConfModifier != NULL) { new_descriptor->value.bit_mask |= CONFERENCE_NAME_MODIFIER_PRESENT; ::lstrcpyA(new_descriptor->value.conference_name_modifier, descriptor_data->pszConfModifier); } /* * Get the conference description if one exists. */ if (descriptor_data->pwszConfDescription != NULL) { new_descriptor->value.bit_mask |=CONFERENCE_DESCRIPTION_PRESENT; new_descriptor->value.conference_description.value = descriptor_data->pwszConfDescription; new_descriptor->value.conference_description.length = ::lstrlenW(descriptor_data->pwszConfDescription); } /* * Get the Network Address list if it exists. */ if (descriptor_data->network_address_list != NULL) { new_descriptor->value.bit_mask |=DESCRIPTOR_NET_ADDRESS_PRESENT; descriptor_data->network_address_list-> GetNetworkAddressListPDU(&new_descriptor->value. descriptor_net_address); } } } *conference_list = (rc == GCC_NO_ERROR) ? m_pSetOfConfDescriptors : NULL; return rc; } /* * FreeConferenceDescriptorListPDU () * * Public Function Description * This routine is used to free up any resources allocated to hold the PDU * form of the conference descriptor list. */ void CConfDescriptorListContainer::FreeConferenceDescriptorListPDU(void) { PSetOfConferenceDescriptors pCurr, pNext; CONF_DESCRIPTOR *lpConfDescData; /* * Loop through the list of descriptors, deleting each element. */ for (pCurr = m_pSetOfConfDescriptors; NULL != pCurr; pCurr = pNext) { pNext = pCurr->next; delete pCurr; } /* * Free the PDU data for any network address lists which may exist. */ m_ConfDescriptorList.Reset(); while (NULL != (lpConfDescData = m_ConfDescriptorList.Iterate())) { if (NULL != lpConfDescData->network_address_list) { lpConfDescData->network_address_list->FreeNetworkAddressListPDU(); } } m_pSetOfConfDescriptors = NULL; } /* * LockConferenceDescriptorList () * * Public Function Description * This routine is used to "lock" the API form of the conference descriptor * list. The lock count is incremented and the API form of the list * created in preparation for a "GetConferenceDescriptorList" call used to * retrieve the API form of the list. The memory necessary to hold the * API list is allocated by this routine. */ GCCError CConfDescriptorListContainer::LockConferenceDescriptorList(void) { GCCError rc = GCC_NO_ERROR; UINT i; UINT network_address_data_length = 0; CONF_DESCRIPTOR *lpConfDescData; if (Lock() == 1) { m_cDescriptors = m_ConfDescriptorList.GetCount(); if (m_cDescriptors != 0) { /* * Allocate space to hold pointers to all descriptors in the * conference. */ DBG_SAVE_FILE_LINE m_pDescriptorListMemory = new BYTE[m_cDescriptors * sizeof(PGCCConferenceDescriptor)]; if (m_pDescriptorListMemory != NULL) { m_ppGCCConfDescriptorList = (PGCCConferenceDescriptor *) m_pDescriptorListMemory; /* * Set up an iterator for the internal descriptor list. Iterate * through the list, locking each network address list object * and adding up the amount of memory needed to hold all of the * data for the network address lists. Allocate the necessary * amount of memory and save a pointer to the memory. */ m_ConfDescriptorList.Reset(); while (NULL != (lpConfDescData = m_ConfDescriptorList.Iterate())) { if (lpConfDescData->network_address_list != NULL) { network_address_data_length += lpConfDescData->network_address_list->LockNetworkAddressList(); } } if (network_address_data_length != 0) { DBG_SAVE_FILE_LINE m_pNetAddrListMemory = new BYTE[network_address_data_length]; if (m_pNetAddrListMemory != NULL) { m_pNetAddrMemoryPointer = m_pNetAddrListMemory; } else { rc = GCC_ALLOCATION_FAILURE; } } if (rc == GCC_NO_ERROR) { m_ConfDescriptorList.Reset(); for (i = 0; i < m_cDescriptors; i++) { lpConfDescData = m_ConfDescriptorList.Iterate(); ASSERT(NULL != lpConfDescData); /* * Allocate the API structure used at the interface. * Call the routine which converts the descriptor data * from its internal form into API form. */ DBG_SAVE_FILE_LINE m_ppGCCConfDescriptorList[i] = new GCCConferenceDescriptor; if (m_ppGCCConfDescriptorList[i] != NULL) { GetConferenceDescriptor(m_ppGCCConfDescriptorList[i], lpConfDescData); } else { rc = GCC_ALLOCATION_FAILURE; } } } } else { rc = GCC_ALLOCATION_FAILURE; } } if (rc != GCC_NO_ERROR) { Unlock(); } } return rc; } /* * GetConferenceDescriptorList () * * Public Function Description * This routine is used to retrieve the API form of the conference * descriptor list. */ void CConfDescriptorListContainer::GetConferenceDescriptorList( PGCCConferenceDescriptor ** conference_list, UINT * number_of_descriptors) { /* * Check to see if the object has been locked. Fill in the API descriptor * list if it has, report an error if it has not. */ if (GetLockCount() > 0) { *conference_list = m_ppGCCConfDescriptorList; *number_of_descriptors = (USHORT) m_cDescriptors; } else { ERROR_OUT(("CConfDescriptorListContainer::GetConferenceDescriptorList: Error, data not locked")); *conference_list = NULL; *number_of_descriptors = 0; } } /* * UnLockConferenceDescriptorList () * * Public Function Description * This routine is used to "unlock" the "API" data for this object. This * results in the lock count for this object being decremented. When the * lock count transitions from 1 to 0, a check is made to determine * whether the object has been freed through a call to * FreeConferenceDescriptorList. If so, the object will automatically * delete itself. If not, any resources allocated to hold the API form * of the decriptor list are freed. */ void CConfDescriptorListContainer::UnLockConferenceDescriptorList(void) { UINT i; /* * If the lock count is zero, delete the object if it is "freed". If the * lock count is zero but the obect is not "freed", free any resources * allocated to hold the API data. */ if (Unlock(FALSE) == 0) { CONF_DESCRIPTOR *lpConfDescData; if (m_pDescriptorListMemory != NULL) { for (i = 0; i < m_cDescriptors; i++) { delete m_ppGCCConfDescriptorList[i]; } delete m_pDescriptorListMemory; m_pDescriptorListMemory = NULL; m_ppGCCConfDescriptorList = NULL; } /* * Free the memory for the network address lists if it exists. * Iterate through the internal descriptor list, unlocking any * network address list objects which exist. */ if (m_pNetAddrListMemory != NULL) { delete m_pNetAddrListMemory; m_pNetAddrListMemory = NULL; m_pNetAddrMemoryPointer = NULL; } m_ConfDescriptorList.Reset(); while (NULL != (lpConfDescData = m_ConfDescriptorList.Iterate())) { if (lpConfDescData->network_address_list != NULL) { lpConfDescData->network_address_list->UnLockNetworkAddressList (); } } } // we have to call Release() because we used Unlock(FALSE) Release(); } /* * void GetConferenceDescriptor ( * PGCCConferenceDescriptor gcc_descriptor, * CONF_DESCRIPTOR *descriptor_data) * * Private member function of CConfDescriptorListContainer. * * Function Description: * This routine is used to fill in an API conference descriptor structure * from an internal descriptor data structure. * * Formal Parameters: * gcc_descriptor (o) The API descriptor structure to fill in. * descriptor_data (i) The internal structure holding the data which is * to be copied into the API structure. * * Return Value: * None. * * Side Effects: * None. * * Caveats: * None. */ void CConfDescriptorListContainer::GetConferenceDescriptor( PGCCConferenceDescriptor gcc_descriptor, CONF_DESCRIPTOR *descriptor_data) { UINT network_address_data_length; /* * Fill in the descriptor flags. */ gcc_descriptor->conference_is_locked = descriptor_data->conference_is_locked; gcc_descriptor->password_in_the_clear_required = descriptor_data->password_in_the_clear; /* * Get the numeric portion of the conference name. */ gcc_descriptor->conference_name.numeric_string = (GCCNumericString) descriptor_data->pszNumericConfName; /* * Get the text portion of the conference name, if it exists. */ gcc_descriptor->conference_name.text_string = descriptor_data->pwszTextConfName; /* * Get the conference modifier. */ if (descriptor_data->pszConfModifier != NULL) { gcc_descriptor->conference_name_modifier = (GCCNumericString) descriptor_data->pszConfModifier; } else gcc_descriptor->conference_name_modifier = NULL; /* * Get the conference description. */ gcc_descriptor->conference_descriptor = descriptor_data->pwszConfDescription; /* * Fill in the network address list if it exists. Otherwise, set the * number of address to zero and the structure pointer to NULL. */ if (descriptor_data->network_address_list != NULL) { network_address_data_length = descriptor_data->network_address_list-> GetNetworkAddressListAPI( &gcc_descriptor->number_of_network_addresses, &gcc_descriptor->network_address_list, m_pNetAddrMemoryPointer); /* * Move the network address list memory pointer past the data written * into memory by the "Get" call. The data for the next network address * list will then be written there on subsequent "Get" calls. */ m_pNetAddrMemoryPointer += network_address_data_length; } else { gcc_descriptor->number_of_network_addresses = 0; gcc_descriptor->network_address_list = NULL; } }