#include "precomp.h" #include "fsdiag.h" DEBUG_FILEZONE(ZONE_T120_GCCNC); /* * userdata.cpp * * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY * * Abstract: * This is the implementation file for the class CUserDataListContainer. CUserDataListContainer * objects are used to maintain user data elements. A user data element * consists of an Object Key and an optional octet string. The Object * Key data is maintained internally by this class by using an * CObjectKeyContainer container. The optional octet string data is maintained * internally through the use of a Rogue Wave string container. * * Protected Instance Variables: * m_UserDataItemList * List of structures used to hold the user data internally. * m_pSetOfUserDataPDU * Storage for the "PDU" form of the user data. * m_cbDataSize * Variable holding the size of the memory which will be required to * hold any data referenced by the "API" GCCUserData structure. * * Caveats: * None. * * Author: * jbo */ #include "userdata.h" #include "clists.h" USER_DATA::~USER_DATA(void) { if (NULL != key) { key->Release(); } delete poszOctetString; } /* * CUserDataListContainer() * * Public Function Description * This CUserDataListContainer constructor is used to create a CUserDataListContainer object * from "API" data. The constructor immediately copies the user data * passed in as a list of "GCCUserData" structures into it's internal form * where a Rogue Wave container holds the data in the form of * USER_DATA structures. */ CUserDataListContainer:: CUserDataListContainer(UINT cMembers, PGCCUserData *user_data_list, PGCCError pRetCode) : CRefCount(MAKE_STAMP_ID('U','r','D','L')), m_UserDataItemList(DESIRED_MAX_USER_DATA_ITEMS), m_cbDataSize(0), m_pSetOfUserDataPDU(NULL) { /* * Copy the user data into the internal structures. */ *pRetCode = CopyUserDataList(cMembers, user_data_list); } /* * CUserDataListContainer() * * Public Function Description * This CUserDataListContainer constructor is used to create a CUserDataListContainer object * from data passed in as a "PDU" SetOfUserData structure. The user * data is copied into it's internal form where a Rogue Wave container * holds the data in the form of USER_DATA structures. */ CUserDataListContainer:: CUserDataListContainer(PSetOfUserData set_of_user_data, PGCCError pRetCode) : CRefCount(MAKE_STAMP_ID('U','r','D','L')), m_UserDataItemList(DESIRED_MAX_USER_DATA_ITEMS), m_cbDataSize(0), m_pSetOfUserDataPDU(NULL) { /* * Copy the user data into the internal structures. */ *pRetCode = UnPackUserDataFromPDU(set_of_user_data); } /* * CUserDataListContainer() * * Public Function Description * This CUserDataListContainer copy constructor is used to create a CUserDataListContainer * object from another CUserDataListContainer object. The constructor immediately * copies the user data passed in into it's internal form where a Rogue * Wave list holds the data in the form of USER_DATA structures. */ CUserDataListContainer:: CUserDataListContainer(CUserDataListContainer *user_data_list, PGCCError pRetCode) : CRefCount(MAKE_STAMP_ID('U','r','D','L')), m_UserDataItemList(DESIRED_MAX_USER_DATA_ITEMS), m_cbDataSize(0), m_pSetOfUserDataPDU(NULL) { GCCError rc; USER_DATA *user_data_info_ptr; USER_DATA *lpUsrDataInfo; /* * Set up an iterator for the internal list of "info" structures in the * CUserDataListContainer object to be copied. */ user_data_list->m_UserDataItemList.Reset(); /* * Copy each USER_DATA structure contained in the CUserDataListContainer object to * be copied. */ while (NULL != (lpUsrDataInfo = user_data_list->m_UserDataItemList.Iterate())) { /* * Create a new USER_DATA structure to hold each element of the new * CUserDataListContainer object. Report an error if creation of this structure * fails. */ DBG_SAVE_FILE_LINE user_data_info_ptr = new USER_DATA; if (user_data_info_ptr != NULL) { user_data_info_ptr->poszOctetString = NULL; /* * Go ahead and insert the pointer to the USER_DATA structure * into the internal Rogue Wave list. */ m_UserDataItemList.Append(user_data_info_ptr); /* * Create a new CObjectKeyContainer object to hold the "key" using the * copy constructor for the CObjectKeyContainer class. Check to be sure * construction of the object is successful. Note that validation * of the object key data is not done here since this would be done * when the original CUserDataListContainer object was created. */ DBG_SAVE_FILE_LINE user_data_info_ptr->key = new CObjectKeyContainer(lpUsrDataInfo->key, &rc); if ((NULL != user_data_info_ptr->key) && (GCC_NO_ERROR == rc)) { /* * If an octet string exists, create a new Rogue Wave string to hold * the octet string portion of the "key" and copy the octet string * from the old CUserDataListContainer object into the new USER_DATA * structure. */ if (lpUsrDataInfo->poszOctetString != NULL) { if (NULL == (user_data_info_ptr->poszOctetString = ::My_strdupO(lpUsrDataInfo->poszOctetString))) { ERROR_OUT(("UserData::UserData: can't create octet string")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } else { ASSERT(NULL == user_data_info_ptr->poszOctetString); } } else { ERROR_OUT(("UserData::UserData: Error creating new ObjectKeyData")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } else { ERROR_OUT(("UserData::UserData: can't create USER_DATA")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } rc = GCC_NO_ERROR; MyExit: *pRetCode = rc; } /* * ~CUserDataListContainer() * * Public Function Description * This is the destructor for the CUserDataListContainer class. It is used to * clean up any memory allocated during the life of this object. */ CUserDataListContainer:: ~CUserDataListContainer(void) { /* * Free any PDU data which may have not been freed. */ if (m_pSetOfUserDataPDU) { FreeUserDataListPDU(); } /* * Set up an iterator to use for iterating through the internal Rogue * Wave list of USER_DATA structures. */ USER_DATA *pUserDataItem; m_UserDataItemList.Reset(); while (NULL != (pUserDataItem = m_UserDataItemList.Iterate())) { /* * Delete any memory being referenced in the USER_DATA structure. */ delete pUserDataItem; } } /* * LockUserDataList () * * Public Function Description: * This routine locks the user data list and determines the amount of * memory referenced by the "API" user data list structures. */ UINT CUserDataListContainer:: LockUserDataList(void) { /* * If this is the first time this routine is called, determine the size of * the memory required to hold the data. Otherwise, just increment the * lock count. */ if (Lock() == 1) { USER_DATA *lpUsrDataInfo; /* * Set aside memory to hold the pointers to the GCCUserData structures * as well as the structures themselves. The "sizeof" the structure * must be rounded to an even four-byte boundary. */ m_cbDataSize = m_UserDataItemList.GetCount() * (sizeof(PGCCUserData) + ROUNDTOBOUNDARY(sizeof(GCCUserData)) ); m_UserDataItemList.Reset(); while (NULL != (lpUsrDataInfo = m_UserDataItemList.Iterate())) { /* * Lock the data for the object keys, adding the amount of memory * necessary to hold the object key data to the total memory size. */ m_cbDataSize += lpUsrDataInfo->key->LockObjectKeyData(); /* * Check to see if this user data element contains the optional * user data octet string. Add the space to hold it if it exists. */ if (lpUsrDataInfo->poszOctetString != NULL) { /* * Since the user data structure contains a pointer to a * OSTR structure, we must add the amount of memory * needed to hold the structure as well as the string data. */ m_cbDataSize += ROUNDTOBOUNDARY(sizeof(OSTR)); /* * The data referenced by the octet string is just the byte * length of the octet string. */ m_cbDataSize += ROUNDTOBOUNDARY(lpUsrDataInfo->poszOctetString->length); } } } return m_cbDataSize; } /* * GetUserDataList () * * Public Function Description: * This routine retrieves user data elements contained in the user data * object and returns them in the "API" form of a list of pointers to * "GCCUserData" structures. The number of user data elements contained * in this object is also returned. */ UINT CUserDataListContainer:: GetUserDataList(USHORT *number_of_members, PGCCUserData **user_data_list, LPBYTE memory) { UINT cbDataSizeToRet = 0; UINT data_length = 0; Int user_data_counter = 0; PGCCUserData user_data_ptr; /* * If the user data has been locked, fill in the output parameters and * the data referenced by the pointers. Otherwise, report that the object * has yet to be locked into the "API" form. */ if (GetLockCount() > 0) { USER_DATA *lpUsrDataInfo; /* * Fill in the output length parameter which indicates how much data * referenced outside the structure will be written. */ cbDataSizeToRet = m_cbDataSize; /* * Fill in the number of user data entities and save a pointer to the * memory location passed in. This is where the pointers to the * GCCUserData structures will be written. The actual structures will * be written into memory immediately following the list of pointers. */ *number_of_members = (USHORT) m_UserDataItemList.GetCount(); *user_data_list = (PGCCUserData *)memory; /* * Save the amount of memory needed to hold the list of pointers * as well as the actual user data structures. */ data_length = m_UserDataItemList.GetCount() * sizeof(PGCCUserData); /* * Move the memory pointer past the list of user data pointers. This * is where the first user data structure will be written. */ memory += data_length; /* * Iterate through the internal list of USER_DATA structures, * building "API" GCCUserData structures in memory. */ m_UserDataItemList.Reset(); while (NULL != (lpUsrDataInfo = m_UserDataItemList.Iterate())) { /* * Save the pointer to the user data structure in the list * of pointers. */ user_data_ptr = (PGCCUserData)memory; (*user_data_list)[user_data_counter++] = user_data_ptr; /* * Move the memory pointer past the user data structure. This is * where the object key data and octet string data will be written. */ memory += ROUNDTOBOUNDARY(sizeof(GCCUserData)); /* * Fill in the user data structure starting with the object key. */ data_length = lpUsrDataInfo->key->GetGCCObjectKeyData(&user_data_ptr->key, memory); /* * Move the memory pointer past the object key data. This is * where the octet string structure will be written, if it exists. * If the octet string does exist, save the memory pointer in the * user data structure's octet string pointer and fill in the * elements of the octet string structure. Otherwise, set the * octet string pointer to NULL. */ memory += data_length; if (lpUsrDataInfo->poszOctetString == NULL) { user_data_ptr->octet_string = NULL; } else { user_data_ptr->octet_string = (LPOSTR) memory; /* * Move the memory pointer past the octet string structure. * This is where the actual string data for the octet string * will be written. */ memory += ROUNDTOBOUNDARY(sizeof(OSTR)); /* * Write the octet string data into memory and set the octet * string structure pointer and length. */ user_data_ptr->octet_string->length = lpUsrDataInfo->poszOctetString->length; user_data_ptr->octet_string->value = (LPBYTE)memory; /* * Now copy the octet string data from the internal Rogue Wave * string into the object key structure held in memory. */ ::CopyMemory(memory, lpUsrDataInfo->poszOctetString->value, lpUsrDataInfo->poszOctetString->length); /* * Move the memory pointer past the octet string data. */ memory += ROUNDTOBOUNDARY(user_data_ptr->octet_string->length); } } } else { *user_data_list = NULL; *number_of_members = 0; ERROR_OUT(("CUserDataListContainer::GetUserDataList: Error Data Not Locked")); } return cbDataSizeToRet; } /* * UnLockUserDataList () * * 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 * FreeUserDataList. If so, the object will automatically delete * itself. */ void CUserDataListContainer:: UnLockUserDataList(void) { USER_DATA *user_data_info_ptr; if (Unlock(FALSE) == 0) { /* * Unlock any memory locked for the CObjectKeyContainer objects in the * internal USER_DATA structures. */ m_UserDataItemList.Reset(); while (NULL != (user_data_info_ptr = m_UserDataItemList.Iterate())) { /* * Unlock any CObjectKeyContainer memory being referenced in the * USER_DATA structure. */ if (user_data_info_ptr->key != NULL) { user_data_info_ptr->key->UnLockObjectKeyData (); } } } // we have to call Release() because we used Unlock(FALSE) Release(); } /* * GetUserDataPDU () * * Public Function Description: * This routine converts the user data from it's internal form of a list * of USER_DATA structures into the "PDU" form which can be passed in * to the ASN.1 encoder. A pointer to a "PDU" "SetOfUserData" structure is * returned. */ GCCError CUserDataListContainer:: GetUserDataPDU(PSetOfUserData *set_of_user_data) { GCCError rc = GCC_NO_ERROR; PSetOfUserData new_pdu_user_data_ptr; PSetOfUserData old_pdu_user_data_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 output parameter. On subsequent calls to "GetPDU" we can just * copy the internal PDU structure into the structure pointed to by the * output parameter. */ if (NULL == m_pSetOfUserDataPDU) { USER_DATA *lpUsrDataInfo; /* * Iterate through the list of USER_DATA structures, converting * each into "PDU" form and saving the pointers in the linked list of * "SetsOfUserData". */ m_UserDataItemList.Reset(); while (NULL != (lpUsrDataInfo = m_UserDataItemList.Iterate())) { DBG_SAVE_FILE_LINE new_pdu_user_data_ptr = new SetOfUserData; /* * If an allocation failure occurs, call the routine which will * iterate through the list freeing any data which had been * allocated. */ if (new_pdu_user_data_ptr == NULL) { ERROR_OUT(("CUserDataListContainer::GetUserDataPDU: Allocation error, cleaning up")); rc = GCC_ALLOCATION_FAILURE; break; } // // Ensure everything is clean. // ::ZeroMemory(new_pdu_user_data_ptr, sizeof(SetOfUserData)); /* * The first time through, set the PDU structure pointer equal * to the first SetOfUserData created. On subsequent loops, set * the structure's "next" pointer equal to the new structure. */ if (m_pSetOfUserDataPDU == NULL) { m_pSetOfUserDataPDU = new_pdu_user_data_ptr; } else { old_pdu_user_data_ptr->next = new_pdu_user_data_ptr; } old_pdu_user_data_ptr = new_pdu_user_data_ptr; /* * Initialize the new "next" pointer to NULL and convert the * user data element. */ new_pdu_user_data_ptr->next = NULL; if (ConvertUserDataInfoToPDUUserData(lpUsrDataInfo, new_pdu_user_data_ptr) != GCC_NO_ERROR) { ERROR_OUT(("UserData::GetUserDataPDU: can't convert USER_DATA to PDU")); rc = GCC_ALLOCATION_FAILURE; break; } } if (GCC_NO_ERROR != rc) { FreeUserDataListPDU(); ASSERT(NULL == m_pSetOfUserDataPDU); } } /* * Copy the internal PDU structure into the structure pointed to by the * output parameter. */ *set_of_user_data = m_pSetOfUserDataPDU; return rc; } /* * FreeUserDataListPDU () * * Public Function Description: * This routine frees any data which was allocated as a result of a call * to "GetUserDataPDU" which was called in order to build up a "PDU" * structure holding the user data. */ void CUserDataListContainer:: FreeUserDataListPDU(void) { PSetOfUserData pdu_user_data_set; PSetOfUserData next_pdu_user_data_set; USER_DATA *lpUsrDataInfo; /* * Check to make sure "PDU" data has been allocated for this object. */ if (NULL != m_pSetOfUserDataPDU) { pdu_user_data_set = m_pSetOfUserDataPDU; m_pSetOfUserDataPDU = NULL; // so no one can use it now. /* * Loop through the list, freeing the user data associated with * each structure contained in the list. */ while (pdu_user_data_set != NULL) { next_pdu_user_data_set = pdu_user_data_set->next; delete pdu_user_data_set; pdu_user_data_set = next_pdu_user_data_set; } } else { TRACE_OUT(("CUserDataListContainer::FreeUserDataListPDU: Error PDU data not allocated")); } /* * Iterate through the internal list, telling each CObjectKeyContainer object * to free any PDU data which it has allocated. */ m_UserDataItemList.Reset(); while (NULL != (lpUsrDataInfo = m_UserDataItemList.Iterate())) { if (lpUsrDataInfo->key != NULL) { lpUsrDataInfo->key->FreeObjectKeyDataPDU(); } } } /* * GCCError CopyUserDataList ( UINT number_of_members, * PGCCUserData * user_data_list) * * Private member function of CUserDataListContainer. * * Function Description: * This routine copies the user data passed in as "API" data into it's * internal form where the Rogue Wave m_UserDataItemList holds the data * in the form of USER_DATA structures. * * Formal Parameters: * number_of_members (i) The number of elements in the user data list. * user_datalist (i) The list holding the user data to store. * * Return Value: * GCC_NO_ERROR - No error. * GCC_ALLOCATION_FAILURE - Error creating an object using the * "new" operator. * GCC_BAD_USER_DATA - The user data passed in contained * an invalid object key. * * Side Effects: * None. * * Caveats: * None. */ GCCError CUserDataListContainer:: CopyUserDataList(UINT number_of_members, PGCCUserData *user_data_list) { GCCError rc = GCC_NO_ERROR; USER_DATA *user_data_info_ptr; UINT i; LPOSTR octet_string_ptr; /* * Return an error if no user data is passed in. */ if (number_of_members == 0) return (GCC_BAD_USER_DATA); for (i = 0; i < number_of_members; i++) { /* * Create a new "info" structure to hold the user data internally. */ DBG_SAVE_FILE_LINE user_data_info_ptr = new USER_DATA; if (user_data_info_ptr != NULL) { user_data_info_ptr->poszOctetString = NULL; /* * Create a new CObjectKeyContainer object which will be used to store * the "key" portion of the object data internally. */ DBG_SAVE_FILE_LINE user_data_info_ptr->key = new CObjectKeyContainer(&user_data_list[i]->key, &rc); if (user_data_info_ptr->key == NULL) { ERROR_OUT(("UserData::CopyUserDataList: Error creating new CObjectKeyContainer")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } else if (rc != GCC_NO_ERROR) { ERROR_OUT(("UserData::CopyUserDataList: Error creating new CObjectKeyContainer - bad data")); goto MyExit; } /* * Store the optional user data octet string in the list. */ octet_string_ptr = user_data_list[i]->octet_string; if ((octet_string_ptr != NULL) && (rc == GCC_NO_ERROR)) { /* * Create a new Rogue Wave string container to hold the * octet string. */ if (NULL == (user_data_info_ptr->poszOctetString = ::My_strdupO2( octet_string_ptr->value, octet_string_ptr->length))) { ERROR_OUT(("UserData::CopyUserDataList: can't create octet string")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } else { ASSERT(NULL == user_data_info_ptr->poszOctetString); } } else { ERROR_OUT(("UserData::CopyUserDataList: can't create USER_DATA")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } /* * Insert the pointer to the USER_DATA structure into the Rogue Wave list. */ m_UserDataItemList.Append(user_data_info_ptr); } MyExit: if (GCC_NO_ERROR != rc) { delete user_data_info_ptr; } return rc; } /* * GCCError UnPackUserDataFromPDU (PSetOfUserData set_of_user_data) * * Private member function of CUserDataListContainer. * * Function Description: * This routine unpacks the user data from the "PDU" form into the * internal form which is maintained as a Rogue Wave list of USER_DATA * structures. * * Formal Parameters: * set_of_user_data (i) The "PDU" user data list to copy. * * Return Value: * GCC_NO_ERROR - No error. * GCC_ALLOCATION_FAILURE - Error creating an object using the * "new" operator. * * Side Effects: * None. * * Caveats: * None. */ GCCError CUserDataListContainer:: UnPackUserDataFromPDU(PSetOfUserData set_of_user_data) { PSetOfUserData pUserData; GCCError rc = GCC_NO_ERROR; for (pUserData = set_of_user_data; NULL != pUserData; pUserData = pUserData->next) { /* * Convert the user data elements into the internal format which * is a USER_DATA structure and insert the pointers to the * USER_DATA structures into the m_UserDataItemList. */ if (ConvertPDUDataToInternal(pUserData) != GCC_NO_ERROR) { ERROR_OUT(("CUserDataListContainer::UnPackUserDataFromPDU: Error converting PDU data to internal")); rc = GCC_ALLOCATION_FAILURE; break; } } return rc; } /* * GCCError ConvertPDUDataToInternal ( PSetOfUserData user_data_ptr) * * Private member function of CUserDataListContainer. * * Function Description: * This routine converts an individual user data element from the "PDU" * structure form into the internal form which is a USER_DATA * structure. * * Formal Parameters: * user_data_ptr (i) The "PDU" user data list to copy. * * Return Value: * GCC_NO_ERROR - No error. * GCC_ALLOCATION_FAILURE - Error creating an object using the * "new" operator. * * Side Effects: * None. * * Caveats: * None. */ GCCError CUserDataListContainer:: ConvertPDUDataToInternal(PSetOfUserData user_data_ptr) { USER_DATA *user_data_info_ptr; GCCError rc = GCC_NO_ERROR; DBG_SAVE_FILE_LINE user_data_info_ptr = new USER_DATA; if (user_data_info_ptr != NULL) { user_data_info_ptr->poszOctetString = NULL; /* * Create a new CObjectKeyContainer object which will be used to store the * "key" portion of the user data internally. If an error occurs * constructing the key report it. Otherwise, check for any user data * which may need to be stored. Note that any error in creating the * CObjectKeyContainer object is reported as an allocation failure. An error * could occur if a bad object key was received as PDU data but this * would have originated from some other provider since we validate all * object keys created locally. We therefore report it as an allocation * failure. */ DBG_SAVE_FILE_LINE user_data_info_ptr->key = new CObjectKeyContainer(&user_data_ptr->user_data_element.key, &rc); if ((user_data_info_ptr->key == NULL) || (rc != GCC_NO_ERROR)) { ERROR_OUT(("UserData::ConvertPDUDataToInternal: Error creating new CObjectKeyContainer")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } else { /* * The object key was successfully saved so store any actual user * data in the list if it is present. */ if (user_data_ptr->user_data_element.bit_mask & USER_DATA_FIELD_PRESENT) { if (NULL == (user_data_info_ptr->poszOctetString = ::My_strdupO2( user_data_ptr->user_data_element.user_data_field.value, user_data_ptr->user_data_element.user_data_field.length))) { ERROR_OUT(("UserData::ConvertPDUDataToInternal: can't create octet string")); rc = GCC_ALLOCATION_FAILURE; goto MyExit; } } else { ASSERT(NULL == user_data_info_ptr->poszOctetString); } } /* * Initialize the structure pointers to NULL and insert the pointer * to the USER_DATA structure into the Rogue Wave list. */ m_UserDataItemList.Append(user_data_info_ptr); } else { ERROR_OUT(("UserData::ConvertPDUDataToInternal: can't create USER_DATA")); rc = GCC_ALLOCATION_FAILURE; // goto MyExit; } MyExit: if (GCC_NO_ERROR != rc) { delete user_data_info_ptr; } return rc; } /* * GCCError ConvertUserDataInfoToPDUUserData ( * USER_DATA *user_data_info_ptr, * PSetOfUserData pdu_user_data_ptr) * * Private member function of CUserDataListContainer. * * Function Description: * This routine converts the user data from the internal form which is a * USER_DATA structure into the "PDU" structure form "SetOfUserData". * * Formal Parameters: * user_data_info_ptr (i) The internal user data structure to convert. * pdu_user_data_ptr (o) The structure to hold the PDU data after * conversion. * * Return Value: * GCC_NO_ERROR - No error. * GCC_ALLOCATION_FAILURE - Error creating an object using the * "new" operator. * GCC_INVALID_PARAMETER - The internal key pointer was * corrupted. * * Side Effects: * None. * * Caveats: * None. */ GCCError CUserDataListContainer:: ConvertUserDataInfoToPDUUserData(USER_DATA *user_data_info_ptr, PSetOfUserData pdu_user_data_ptr) { GCCError rc = GCC_NO_ERROR; /* * Initialize the user data bit mask to zero. */ pdu_user_data_ptr->user_data_element.bit_mask = 0; /* * Fill in the octet string pointer and length if the octet string * exists. Set the bit mask indicating that the string exists. */ if (user_data_info_ptr->poszOctetString != NULL) { pdu_user_data_ptr->user_data_element.user_data_field.value = user_data_info_ptr->poszOctetString->value; pdu_user_data_ptr->user_data_element.user_data_field.length = user_data_info_ptr->poszOctetString->length; pdu_user_data_ptr->user_data_element.bit_mask |= USER_DATA_FIELD_PRESENT; } /* * Fill in the object key data. */ if (user_data_info_ptr->key != NULL) { /* * Retrieve the "PDU" object key data from the internal CObjectKeyContainer * object. */ if (user_data_info_ptr->key->GetObjectKeyDataPDU ( &pdu_user_data_ptr->user_data_element.key) != GCC_NO_ERROR) { rc = GCC_ALLOCATION_FAILURE; } } else { ERROR_OUT(("UserData::ConvertUserDataInfoToPDUUserData: no valid UserDataInfo key")); rc = GCC_INVALID_PARAMETER; } return rc; }