/* // ************************************************************************* // * * // * c Copyright 2005 Hewlett-Packard Development Company, L.P. * // * * // * Confidential computer software. Valid license from HP and/or * // * its subsidiaries required for possession, use, or copying. * // * * // * Consistent with FAR 12.211 and 12.212, Commercial Computer Software, * // * Computer Software Documentation, and Technical Data for Commercial * // * Items are licensed to the U.S. Government under vendor's standard * // * commercial license. * // * * // * Neither HP nor any of its subsidiaries shall be liable for technical * // * or editorial errors or omissions contained herein. The information * // * in this document is provided "as is" without warranty of any kind and * // * is subject to change without notice. The warranties for HP products * // * are set forth in the express limited warranty statements accompanying * // * such products. Nothing herein should be construed as constituting an * // * additional warranty. * // * * // ************************************************************************* // // // FACILITY: // // OpenVMS System C libraries // // // ABSTRACT: // // This module contains definitions used for Managed Objects written // in C. // // This module assumes that MGTHDR.H has already been included // in the C source module. // // // AUTHOR: // // Barry Kierstein Hewlett Packard // // // REVISION HISTORY: // // X-2 BK Barry Kierstein 06-Dec-2005 // Correct spelling of MGT$K_STS_CONT_DATA_CTX_NOT_FND. // // X-1 BK Barry Kierstein 30-Sep-2005 // Initial version. // */ /* // Macro definitions */ /* Define this macro if V2 MGT headers are used */ /* #define MGTV2_DEFS */ /* Define this macro if MGT header V1 behavior is needed */ /* #define MGT_V1_HDR_COMPATIBLE */ /* // Machine architecture settings */ #ifndef MGT_DEBUG_SETTINGS #ifdef __VMS #ifdef __ALPHA #ifndef MGT_NATIVE_INT64 #define MGT_NATIVE_INT64 /* Architecture has native 64 bit integers */ #endif #ifndef MGT_CALLS_64_BIT #define MGT_CALLS_64_BIT /* Architecture has native 64 bit calls */ #endif #elif __ia64 #ifndef MGT_NATIVE_INT64 #define MGT_NATIVE_INT64 /* Architecture has native 64 bit integers */ #endif #ifndef MGT_CALLS_64_BIT #define MGT_CALLS_64_BIT /* Architecture has native 64 bit calls */ #endif #else /* VAX */ #endif /* #ifdef __ALPHA */ #else /* #ifdef __VMS */ #ifndef MGT_NATIVE_INT64 #define MGT_NATIVE_INT64 /* Architecture has native 64 bit integers */ #endif #ifndef MGT_CALLS_64_BIT #define MGT_CALLS_64_BIT /* Architecture has native 64 bit calls */ #endif #endif /* #ifdef __VMS */ #endif /* #ifndef MGT_DEBUG_SETTINGS */ #ifdef MGT_VERBOSE_MSG #ifdef MGT_NATIVE_INT64 #pragma message ("MGT_NATIVE_INT64 is set") #else #pragma message ("MGT_NATIVE_INT64 is not set") #endif #ifdef MGT_CALLS_64_BIT #pragma message ("MGT_CALLS_64_BIT is set") #else #pragma message ("MGT_CALLS_64_BIT is not set") #endif #endif /* #ifdef MGT_VERBOSE_MSG */ /* // Type definitions */ typedef int MGT_I32; typedef unsigned int MGT_U32; #ifdef MGT_NATIVE_INT64 typedef __int64 MGT_I64; typedef unsigned __int64 MGT_U64; #endif /* // OpenVMS status testing macro */ #ifndef VMS_SUCCESS #define VMS_SUCCESS(status) (status & 0x01) #endif /* // C Macros for Managed Objects */ /* // Note: Since various macros define code blocks, // all variables local to the code blocks // must be unique to avoid variable scope // problems when various macros are nested. */ #define MGT_SUCCESS(status) \ ((status == MGT$K_STS_SUCCESS) || \ (status == MGT$K_STS_CONT_DATA_CTX_FOUND_W) || \ (status == MGT$K_STS_CONT_DATA_CTX_FOUND_E) || \ (status == MGT$K_STS_CONT_DATA_CTX_NOT_FND) \ ) /* List all "success" statuses. Shouldn't */ /* be very many. */ /* // Copy ASCIZ field to fixed-size field // // This macro will copy an ASCIZ string to a fixed-sized // field. If the ASCIZ field length is less than the // fixed-sized field, the fixed-sized field will be padded // with '\0' characters. If the ASCIZ field is larger // than the fixed-sized field, the copy will only copy // the characters that will fit in the fixed-sized field. // // Parameters: // // src Address of the character field for the // source ASCIZ string. // dest Address of the character field for the // destination (ASCIZ string, padded with // '\0' characters as needed). // len Length of the Dest character field. */ #define MGT_COPY_ASCIZ_TO_FIXED_FIELD(src, \ dest, \ len) \ { \ register int MGTAZindex; \ register int MGTAZslen = len; \ register int MGTAZlen = len; \ register char *MGTAZsrc = (char *)src; \ register char *MGTAZdest = (char *)dest; \ \ /* Copy string */ \ for (MGTAZindex = 0; \ MGTAZindex < MGTAZlen; \ MGTAZindex++) \ { \ MGTAZdest[MGTAZindex] = \ MGTAZsrc[MGTAZindex]; \ if (MGTAZsrc[MGTAZindex] == '\0') \ { \ MGTAZslen = MGTAZindex+1; \ break; \ } \ } \ \ /* Null out remain space */ \ for (MGTAZindex = MGTAZslen; \ MGTAZindex < MGTAZlen; \ MGTAZindex++) \ { \ MGTAZdest[MGTAZindex] = '\0'; \ } \ } /* // Copy Managed Object name macro // // This macro will make a copy of the Managed Object's // name. // // The correct format for the registration database // is an ASCIZ string, with all the bytes in the field // after the trailing null set to null. However, // a previous specification allowed input as ASCIC // string for V1.1 and V1.2 parameter section of // Management Registration Requests. For V2.1 and // above versions of the parameter section, this is // not supported. // By default, this macro treats the object name // as an ASCIZ field, in line with the V2.* // specification. // To support the V1.* specification, define // MGT_V1_HDR_COMPATIBLE. This will the ASCIC or ASCIZ // object names. This mode tests the first byte // of the object name. If it is less than 32, then // it is treated as the count byte in an ASCIC field. // // Parameters: // // src Address of the character field for the // source ASCIZ string (ASCIC string for // legacy Management Registration requests). // dest Address of the character field for the // destination (ASCIZ string, padded with // '\0' characters as needed). Character // field length must be at least // MGTRQV2$K_OBJ_NAME_LEN characters. */ #ifdef MGT_V1_HDR_COMPATIBLE /* // Make a basic assumption that if the first byte // is unprintable (less than a space), then the // name is in ASCIC format. */ #if MGTHDR$K_OBJ_NAME_LEN-1 >= 32 #error MGTHDR$K_OBJ_NAME_LEN is larger than 32 bytes #endif #if MGTKRGIN$K_OBJ_NAME_LEN != MGTHDR$K_OBJ_NAME_LEN #error MGTKRGIN$K_OBJ_NAME_LEN != MGTHDR$K_OBJ_NAME_LEN #endif #define MGT_COPY_OBJ_NAME(src,dest) \ { \ int MGTclen; \ char *MGTcsrc = (char *)src; \ char *MGTcdest = (char *)dest; \ \ if (MGTcsrc[0] <(MGTHDR$K_OBJ_NAME_LEN-1)) \ { \ MGTclen = MGTcsrc[0]; \ MGTcsrc++; \ } \ else \ { \ MGTclen = MGTHDR$K_OBJ_NAME_LEN; \ } \ \ /* Copy string */ \ MGT_COPY_ASCIZ_TO_FIXED_FIELD \ (MGTcsrc, MGTcdest, MGTclen); \ } #else #define MGT_COPY_OBJ_NAME(src,dest) \ { \ /* Copy string */ \ MGT_COPY_ASCIZ_TO_FIXED_FIELD \ (MGTcsrc, MGTcdest, \ MGTHDR$K_OBJ_NAME_LEN \ ); \ } #endif /* // Return the maximum packet data length that // the packet can describe // // Parameters: // // pMgtHdr Management Header address // */ #define MGT_GET_MGT_PACKET_DATA_LEN_MAX(pMgtHdr) \ (((MGTHDR *)pMgtHdr)->mgthdr$b_hdr_major == 1 ? \ 0xF8 : \ 0xFF * sizeof(MGT_U64) \ ) /* // Rounds up the data length to the next quadword // // Parameters: // // len Length to align // */ #define MGT_QW_ALIGN_LENGTH(len) \ ((len + 7) & ~0x07) \ /* // Find length of a Management header. // // Parameters: // // pMgtHdr Management Header address // */ #define MGT_GET_MGT_PACKET_HEADER_LEN(pMgtHdr) \ (((MGTHDR *)pMgtHdr)->mgthdr$b_hdr_len) /* // Find length of a Management packet data area. // This is the data only, and does not include // the area described by an EOD header. // // Parameters: // // pMgtHdr Management Header address // */ #define MGT_GET_MGT_PACKET_DATA_LEN(pMgtHdr) \ (((MGTHDR *)pMgtHdr)->mgthdr$b_hdr_major == 1 ? \ ((MGTHDR *)pMgtHdr)->mgthdr$w_par_len : \ ((MGTHDR *)pMgtHdr)->mgthdr$w_par_len * \ sizeof(MGT_U64) \ ) /* // Find length of a Management packet. // // This macro will return the length of the header // and its data. // // Parameters: // // pMgtHdr Management Header address // */ #define MGT_GET_MGT_PACKET_LEN(pMgtHdr) \ (MGT_GET_MGT_PACKET_HEADER_LEN(pMgtHdr) + \ MGT_GET_MGT_PACKET_DATA_LEN(pMgtHdr) \ ) /* // Set the length of a Management packet data section. // // This macro accepts the address of the initial // packet header and the length of the data in bytes. // The length will be aligned up to the next quadword // boundary. // // Parameters: // // pMgtHdr Management Header address // len Management Packet data length in bytes // */ #define MGT_SET_MGT_PACKET_DATA_LEN(pMgtHdr,len) \ { \ ((MGTHDR *)pMgtHdr)->mgthdr$w_par_len = \ (((MGTHDR *)pMgtHdr)-> \ mgthdr$b_hdr_major == 1 ? \ MGT_QW_ALIGN_LENGTH(len) : \ MGT_QW_ALIGN_LENGTH \ (len) / sizeof(MGT_U64) \ ); \ } /* // Set the length of a Management packet. A // packet consists of a Management header and // related data, if any. // // The length will be aligned up to the next quadword // boundary. // // Parameters: // // pMgtHdr Management Header address // len Management Packet length in bytes // */ #define MGT_SET_MGT_PACKET_LEN(pMgtHdr,len) \ { \ MGT_SET_MGT_PACKET_DATA_LEN \ (pMgtHdr, \ (len - \ ((MGTHDR *)pMgtHdr)-> \ mgthdr$b_hdr_len) \ ); \ } /* // Compute and set the length of a Management packet. // A packet consists of a Management header and // related data, if any. // // This macro accepts the address of the initial // packet header and the address of the next // available byte after the end of the packet. // It will compute the length of the packet, // and set the length of the packet data area // appropriately. // // The computed length will be aligned up to the // next quadword boundary. // // Parameters: // // pMgtHdr Management header address // pNextByte Next available byte after the // end of the Management packet // */ #define MGT_FIND_AND_SET_MGT_PACKET_LEN(pMgtHdr, \ pNextByte) \ { \ MGT_SET_MGT_PACKET_LEN \ (pMgtHdr, \ ((char *)pNextByte - (char *)pMgtHdr) \ ); \ } /* // Find address of Management parameter section // // This macro will return the address of the // parameter section for the Management packet. // // Parameters: // // pMgtHdr Management Header address // */ #define MGT_GET_MGT_PARAM_ADDR(pMgtHdr) \ ( \ (char *) \ ((char *)pMgtHdr + \ MGT_GET_MGT_PACKET_HEADER_LEN(pMgtHdr) \ ) \ ) /* // Find address of next Management header // // This macro will return the address of where the // next Management header would be. // It assumes that all Management packets // are adjacent to one another. // // Parameters: // // pMgtHdr Management Header address // */ #define MGT_GET_NEXT_MGT_HDR_ADDR(pMgtHdr) \ ( \ (void *) \ ((char *)pMgtHdr + \ MGT_GET_MGT_PACKET_LEN(pMgtHdr) \ ) \ ) /* // Find address of the EOD Management header // // This macro will return the address of the // EOD Management header or NULL. // // It assumes that all Management packets // are adjacent to one another. // // Parameters: // // pMgtHdr Management Header address of a // main Management packet // */ #define MGT_GET_MGT_EOD_ADDR(pMgtHdr) \ ( \ (((MGTHDR *)pMgtHdr)->mgthdr$b_hdr_major <= 2 ? \ ((void *) \ (((MGTHDRV2 *)pMgtHdr)->mgthdrv2$v_eod ? \ MGT_GET_NEXT_MGT_HDR_ADDR(pMgtHdr) : \ NULL \ ) \ ) : \ NULL \ ) \ ) /* // Find the length of the EOD Management packet // // This macro will return the length of the // EOD Management packet or 0 if the packet // doesn't exist. // // It assumes that all Management packet // sets are adjacent to one another. */ #define MGT_GET_MGT_EOD_PACKET_LEN(pMgtHdr) \ ( \ (((MGTHDR *)pMgtHdr)->mgthdr$b_hdr_major <= 2 ? \ (((MGTHDRV2 *)pMgtHdr)->mgthdrv2$v_eod ? \ MGT_GET_MGT_PACKET_LEN \ (MGT_GET_NEXT_MGT_HDR_ADDR(pMgtHdr)) : \ 0 \ ) : \ 0 \ ) \ ) /* // Get the length of the parameter buffer of the // MO header. If there is an EOD record, then the // parameter buffer length is the sum of the // parameter data length, the EOD header length, // and the parameter data length described by // the EOD header. */ #define MGT_GET_MGT_PACKET_PARAM_LEN(pMgtHdr) \ ( \ MGT_GET_MGT_PACKET_LEN(pMgtHdr) - \ MGT_GET_MGT_PACKET_HEADER_LEN(pMgtHdr) + \ MGT_GET_MGT_EOD_PACKET_LEN(pMgtHdr) \ ) /* // Find address of Management continuation header // // This macro will return the address of the continuation // header, else it will return NULL if it doesn't exist. */ #define MGT_GET_MGT_CONT_ADDR(pMgtHdr) \ ( \ (void *) \ (((MGTHDR *)pMgtHdr)->mgthdr$v_continuation ? \ MGT_GET_MGT_CONT_ADDR2 \ (MGT_GET_NEXT_MGT_HDR_ADDR(pMgtHdr) \ ) : \ NULL \ ) \ ) #define MGT_GET_MGT_CONT_ADDR2(pMgtHdr) \ ( \ (void *) \ (((MGTHDR *)pMgtHdr)->mgthdr$v_continuation ? \ MGT_GET_NEXT_MGT_HDR_ADDR(pMgtHdr) : \ pMgtHdr \ ) \ ) /* // Find the length of the Management continuation packet // // This macro will return the length of the continuation // header, else it will return 0 if it doesn't exist. */ #define MGT_GET_MGT_CONT_PACKET_LEN(pMgtHdr) \ ( \ (((MGTHDR *)pMgtHdr)->mgthdr$v_continuation ? \ MGT_GET_MGT_PACKET_LEN \ (MGT_GET_MGT_CONT_ADDR(pMgtHdr) \ ) : \ 0 \ ) \ ) /* // Find the length of a Management packet set // // This macro will return the length of a packet set. // This macro assumes that the header information // has been validated. */ #define MGT_GET_MGT_PACKET_SET_LEN(pMgtHdr) \ ( \ MGT_GET_MGT_PACKET_LEN(pMgtHdr) + \ MGT_GET_MGT_EOD_PACKET_LEN(pMgtHdr) + \ MGT_GET_MGT_CONT_PACKET_LEN(pMgtHdr) \ ) /* // Find address of next Management packet set // // This macro will return the address of where the // next Management packet set would be. // It assumes that all Management header and data // sets are adjacent to one another. */ #define MGT_GET_NEXT_MGT_PACKET_SET_ADDR(pMgtHdr) \ ( \ (void *) \ ((char *)pMgtHdr + \ MGT_GET_MGT_PACKET_SET_LEN(pMgtHdr) \ ) \ ) /* // Copy quadword block macro // // This will copy a block of quadwords. For // machine architectures that are longword // oriented, this will copy by longword instead. // // This macro assumes that the source and destination // are quadword aligned. */ #ifdef MGT_NATIVE_INT64 #define MGT_COPY_QW_BLOCK(pSrc,pDest,len) \ { \ register int MGTCQWindex; \ register __int64 *MGTCQWsrc = \ (__int64 *)pSrc; \ register __int64 *MGTCQWdest = \ (__int64 *)pDest; \ register int MGTCQWlen = len; \ \ for (MGTCQWindex = 0; \ MGTCQWindex < (MGTCQWlen>>3); \ MGTCQWindex++) \ { \ MGTCQWdest[MGTCQWindex] = \ MGTCQWsrc[MGTCQWindex]; \ } \ } #else #define MGT_COPY_QW_BLOCK(pSrc,pDest,len) \ { \ register int MGTCQWindex; \ register int *MGTCQWsrc = (int *)pSrc; \ register int *MGTCQWdest= (int *)pDest; \ register int MGTCQWlen = len; \ \ for (MGTCQWindex = 0; \ MGTCQWindex < (MGTCQWlen>>2); \ MGTCQWindex++) \ { \ MGTCQWdest[MGTCQWindex] = \ MGTCQWsrc[MGTCQWindex]; \ } \ } #endif /* // Copy MO header macro // // This will copy a Management header to // a destination. It is basically a memory copy, // but it is here for a number of reasons: // // 1) It obtains the length to copy from the // packet itself. // 2) This assumes that the buffers are aligned // on a quadword boundary, and is optimized // for that. // 3) Since this code is also used on VAX where // some of the standard C functions are not // available, this can be tailored for each // architecture on which OpenVMS runs. // // The next available byte parameter is the // address of the field that will receive the // address of the next available byte. If this // parameter is equal to NULL, // then this address is not returned. */ #define MGT_COPY_MGT_HEADER(pSrcHdr, \ pDestHdr, \ ppNextByte) \ { \ register int MGTCHDlen = \ MGT_GET_MGT_PACKET_HEADER_LEN(pSrcHdr); \ \ MGT_COPY_QW_BLOCK \ (pSrcHdr,pDestHdr,MGTCHDlen); \ \ if (ppNextByte != NULL) \ { \ char **MGTCHDptr = ppNextByte; \ *MGTCHDptr = \ (char *)(pDestHdr) + MGTCHDlen; \ } \ } /* // Copy MO header macro with check // // This macro will check to see if the length // of the MO header will fit in the buffer before // attempting the copy. The return status // determines whether the copy happened or not. // // The next available byte parameter is the // address of the field that will receive the // address of the next available byte. If this // parameter is equal to NULL, // then this address is not returned. */ #define MGT_COPY_MGT_HEADER_WITH_CHECK(pSrcHdr, \ pDestHdr, \ bufLen, \ retStatus, \ ppNextByte) \ { \ if (MGT_GET_MGT_PACKET_HEADER_LEN(pSrcHdr) <= \ bufLen) \ { \ MGT_COPY_MGT_HEADER \ (pSrcHdr,pDestHdr,ppNextByte); \ retStatus = MGT$K_STS_SUCCESS; \ } \ else \ { \ retStatus = MGT$K_STS_RSP_NO_ROOM; \ } \ } /* // Copy MO packet macro // // This will copy a Management packet to // a destination. It is basically a memory copy, // but it is here for a number of reasons: // // 1) It obtains the length to copy from the // packet itself. // 2) This assumes that the buffers are aligned // on a quadword boundary, and is optimized // for that. // 3) Since this code is also used on VAX where // some of the standard C functions are not // available, this can be tailored for each // architecture on which OpenVMS runs. // // The address for the next MGTHDR parameter is the // address of the field that will receive the // address for the next MGTHDR header. If this // parameter is equal to NULL, // then this address is not returned. */ #define MGT_COPY_MGT_PACKET(pSrcHdr, \ pDestHdr, \ ppNextHdr) \ { \ register int MGTCPKlen = \ MGT_GET_MGT_PACKET_LEN(pSrcHdr); \ \ MGT_COPY_QW_BLOCK \ (pSrcHdr,pDestHdr,MGTCPKlen); \ \ if (ppNextHdr != NULL) \ { \ MGTHDR **MGTCPKptr = ppNextHdr; \ *MGTCPKptr = \ (MGTHDR *) \ ((char *)(pDestHdr) +MGTCPKlen); \ } \ } /* // Copy MO packet macro with check // // This macro will check to see if the length // of the MO packet will fit in the buffer before // attempting the copy. The return status // determines whether the copy happened or not. // // The address for the next MGTHDR parameter is the // address of the field that will receive the // address for the next MGTHDR header. If this // parameter is equal to NULL, // then this address is not returned. */ #define MGT_COPY_MGT_PACKET_WITH_CHECK(pSrcHdr, \ pDestHdr, \ bufLen, \ retStatus, \ ppNextHdr) \ { \ if (MGT_GET_MGT_PACKET_LEN(pSrcHdr) <= \ bufLen) \ { \ MGT_COPY_MGT_PACKET \ (pSrcHdr,pDestHdr,ppNextHdr); \ retStatus = MGT$K_STS_SUCCESS; \ } \ else \ { \ retStatus = MGT$K_STS_RSP_NO_ROOM; \ } \ } /* // Replace MO packet macro // // This macro will check to see if the length // of the new MO packet will fit in the buffer // space of the old one before attempting the // replacement. The return status determines // whether the replacement happened or not. // // The address for the next MGTHDR parameter is the // address of the field that will receive the // address for the next MGTHDR header. If this // parameter is equal to NULL, // then this address is not returned. */ #define MGT_REPLACE_MGT_PACKET(pSrcHdr, \ pDestHdr, \ retStatus, \ ppNextHdr) \ { \ int srcLen = \ MGT_GET_MGT_PACKET_LEN(pSrcHdr); \ int destLen = \ MGT_GET_MGT_PACKET_LEN(pDestHdr); \ \ if (srcLen == destLen) \ { \ MGT_COPY_MGT_PACKET \ (pSrcHdr,pDestHdr,ppNextHdr); \ retStatus = MGT$K_STS_SUCCESS; \ } \ else \ { \ retStatus = MGT$K_STS_RSP_NO_ROOM; \ } \ } /* // Copy MO packet set macro // // This will copy a Management packet set to // a destination. It is basically a memory copy, // but it is here for a number of reasons: // // 1) It obtains the length to copy from the // packet set itself. // 2) This assumes that the buffers are aligned // on a quadword boundary, and is optimized // for that. // 3) Since this code is also used on VAX where // some of the standard C functions are not // available, this can be tailored for each // architecture on which OpenVMS runs. // // The address for the next MGTHDR parameter is the // address of the field that will receive the // address for the next MGTHDR header. If this // parameter is equal to NULL, // then this address is not returned. */ #define MGT_COPY_MGT_PACKET_SET(pSrcHdr, \ pDestHdr, \ ppNextHdr) \ { \ register int MGTCSTlen = \ MGT_GET_MGT_PACKET_SET_LEN(pSrcHdr); \ \ MGT_COPY_QW_BLOCK \ (pSrcHdr,pDestHdr,MGTCSTlen); \ \ if (ppNextByte != NULL) \ { \ char **MGTCSTptr = ppNextByte; \ *MGTCSTptr = \ (char *)(pDestHdr) + MGTCSTlen; \ } \ } /* // Copy MO packet set macro with check // // This macro will check to see if the length // of the MO packet set will fit in the buffer before // attempting the copy. The return status // determines whether the copy happened or not. // // The address for the next MGTHDR parameter is the // address of the field that will receive the // address for the next MGTHDR header. If this // parameter is equal to NULL, // then this address is not returned. */ #define MGT_COPY_MGT_PACKET_SET_WITH_CHECK(pSrcHdr, \ pDestHdr, \ bufLen, \ retStatus, \ ppNextHdr) \ { \ if (MGT_GET_MGT_PACKET_SET_LEN(pSrcHdr) <= \ bufLen) \ { \ MGT_COPY_MGT_PACKET_SET \ (pSrcHdr,pDestHdr,ppNextHdr); \ retStatus = MGT$K_STS_SUCCESS; \ } \ else \ { \ retStatus = MGT$K_STS_RSP_NO_ROOM; \ } \ } /* // Initialize V1.1 MO response from a V1.1 MO request header // // This macro will carry over the fields that need // to be copied from the MO request to the MO response. */ #define MGT_COPY_V1_1_MGT_REQUEST_INFO(pSrcHdr, \ pDestHdr) \ { \ MGTHDR *pCMRI11SrcHdr = (MGTHDR *)pSrcHdr; \ MGTHDR *pCMRI11DestHdr = (MGTHDR *)pDestHdr; \ \ pCMRI11DestHdr->mgthdr$l_obj_handle = \ pCMRI11SrcHdr->mgthdr$l_obj_handle; \ pCMRI11DestHdr->mgthdr$l_src_obj_handle = \ pCMRI11SrcHdr->mgthdr$l_src_obj_handle; \ pCMRI11DestHdr->mgthdr$l_action_seq = \ pCMRI11SrcHdr->mgthdr$l_action_seq; \ pCMRI11DestHdr->mgthdr$b_action = \ pCMRI11SrcHdr->mgthdr$b_action; \ } /* // Initialize V2.1 MO response from a V2.1 MO request header // // This macro will carry over the fields that need // to be copied from the MO request to the MO response. */ #define MGT_COPY_V2_1_MGT_REQUEST_INFO(pSrcHdr, \ pDestHdr) \ { \ MGTHDRV2 *pCMRI21SrcHdr = (MGTHDRV2 *)pSrcHdr; \ MGTHDRV2 *pCMRI21DestHdr= (MGTHDRV2 *)pDestHdr; \ \ pCMRI21DestHdr->mgthdrv2$l_obj_handle = \ pCMRI21SrcHdr->mgthdrv2$l_obj_handle; \ pCMRI21DestHdr->mgthdrv2$l_src_obj_handle = \ pCMRI21SrcHdr->mgthdrv2$l_src_obj_handle; \ pCMRI21DestHdr->mgthdrv2$l_action_seq = \ pCMRI21SrcHdr->mgthdrv2$l_action_seq; \ pCMRI21DestHdr->mgthdrv2$b_action = \ pCMRI21SrcHdr->mgthdrv2$b_action; \ } /* // Initialize MO response from MO request header // // This macro will carry over the fields that need // to be copied from the MO request to the MO response. */ #define MGT_COPY_MGT_REQUEST_INFO(pSrcHdr, \ pDestHdr) \ { \ MGTHDR *pCMRISrcHdr = (MGTHDR *)pSrcHdr; \ MGTHDR *pCMRIDestHdr = (MGTHDR *)pDestHdr; \ \ if (pCMRISrcHdr->mgthdr$b_hdr_major <= 2) \ { \ MGT_COPY_V2_1_MGT_REQUEST_INFO \ (pSrcHdr, pDestHdr); \ } \ else \ { \ MGT_COPY_V1_1_MGT_REQUEST_INFO \ (pSrcHdr, pDestHdr); \ } \ } /* // Create a MO V1.1 compliant header // // This macro will initialize a MO V1.1 compliant // header at the address specified. */ #ifdef MGT_NATIVE_INT64 #define MGT_CREATE_V1_1_MGT_HEADER(pMgtHdr, \ hdrType, \ destMOID, \ srcMOID, \ actionCode, \ paramMajVer, \ paramMinVer, \ actionCtx, \ ppNextByte) \ { \ MGT_U64 *pQWV11Hdr = (MGT_U64 *) pMgtHdr; \ \ pQWV11Hdr[0] = \ ((MGT_U64)(MGTHDR$K_ACT_HDR_V1_1_LEN)) + \ ((MGT_U64)(MGTHDR$M_V) << 8) + \ ((MGT_U64)(0x01) << 16) + \ ((MGT_U64)(0x01) << 24) + \ ((MGT_U64)(hdrType) << 32) + \ ((MGT_U64)(MGT$K_STS_RESERVED) << 40); \ pQWV11Hdr[1] = \ ((MGT_U64)(destMOID)) + \ ((MGT_U64)(srcMOID) << 32); \ pQWV11Hdr[2] = \ ((MGT_U64)(actionCode)) + \ ((MGT_U64)(paramMinVer) << 16) + \ ((MGT_U64)(paramMajVer) << 24) + \ ((MGT_U64)(actionCtx) << 32); \ \ if (ppNextByte != NULL) \ { \ char **MGTC11Hptr = ppNextByte; \ *MGTC11Hptr = \ (char *)&(pQWV11Hdr[3]); \ } \ } #else #define MGT_CREATE_V1_1_MGT_HEADER(pMgtHdr, \ hdrType, \ destMOID, \ srcMOID, \ actionCode, \ paramMajVer, \ paramMinVer, \ actionCtx, \ ppNextByte) \ { \ MGT_U32 *pLWV11Hdr = (MGT_U32 *) pMgtHdr; \ \ pLWV11Hdr[0] = \ ((MGTHDR$K_ACT_HDR_V1_1_LEN)) + \ ((MGTHDR$M_V) << 8) + \ ((0x01) << 16) + \ ((0x01) << 24); \ pLWV11Hdr[1] = \ ((hdrType)) + \ ((MGT$K_STS_RESERVED) << 8); \ pLWV11Hdr[2] = \ ((destMOID)); \ pLWV11Hdr[3] = \ ((srcMOID)); \ pLWV11Hdr[4] = \ ((actionCode)) + \ ((paramMinVer) << 16) + \ ((paramMajVer) << 24); \ pLWV11Hdr[5] = \ ((actionCtx)); \ \ if (ppNextByte != NULL) \ { \ char **MGTC11Hptr = ppNextByte; \ *MGTC11Hptr = \ (char *)&(pLWV11Hdr[6]); \ } \ } #endif /* // Create a MO V2.1 compliant header // // This macro will initialize a MO V2.1 compliant // header at the address specified. */ #ifdef MGT_NATIVE_INT64 #define MGT_CREATE_V2_1_MGT_HEADER(pMgtHdr, \ hdrType, \ destMOID, \ srcMOID, \ actionCode, \ paramMajVer, \ paramMinVer, \ actionCtx, \ ppNextByte) \ { \ MGT_U64 *pQWV21Hdr = (MGT_U64 *) pMgtHdr; \ \ pQWV21Hdr[0] = \ ((MGT_U64)(MGTHDRV2$K_ACT_HDR_V2_1_LEN))+ \ ((MGT_U64)(MGTHDR$M_V) << 8) + \ ((MGT_U64)(0x01) << 16) + \ ((MGT_U64)(0x02) << 24) + \ ((MGT_U64)(hdrType) << 32) + \ ((MGT_U64)(MGT$K_STS_RESERVED) << 40); \ pQWV21Hdr[1] = \ ((MGT_U64)(destMOID)) + \ ((MGT_U64)(srcMOID) << 32); \ pQWV21Hdr[2] = \ ((MGT_U64)(actionCode)) + \ ((MGT_U64)(paramMinVer) << 16) + \ ((MGT_U64)(paramMajVer) << 24) + \ ((MGT_U64)(actionCtx) << 32); \ \ if (ppNextByte != NULL) \ { \ char **MGTC21Hptr = ppNextByte; \ *MGTC21Hptr = \ (char *)&(pQWV21Hdr[3]); \ } \ } #else #define MGT_CREATE_V2_1_MGT_HEADER(pMgtHdr, \ hdrType, \ destMOID, \ srcMOID, \ actionCode, \ paramMajVer, \ paramMinVer, \ actionCtx, \ ppNextByte) \ { \ MGT_U32 *pLWV21Hdr = (MGT_U32 *) pMgtHdr; \ \ pLWV21Hdr[0] = \ ((MGTHDRV2$K_ACT_HDR_V2_1_LEN)) + \ ((MGTHDR$M_V) << 8) + \ ((0x01) << 16) + \ ((0x02) << 24); \ pLWV21Hdr[1] = \ ((hdrType)) + \ ((MGT$K_STS_RESERVED) << 8); \ pLWV21Hdr[2] = \ ((destMOID)); \ pLWV21Hdr[3] = \ ((srcMOID)); \ pLWV21Hdr[4] = \ ((actionCode)) + \ ((paramMinVer) << 16) + \ ((paramMajVer) << 24); \ pLWV21Hdr[5] = \ ((actionCtx)); \ \ if (ppNextByte != NULL) \ { \ char **MGTC21Hptr = ppNextByte; \ *MGTC21Hptr = \ (char *)&(pLWV21Hdr[6]); \ } \ } #endif /* // Create a MO V2.1 compliant miniheader // // This macro will initialize a MO V2.1 compliant // miniheader at the address specified. */ #ifdef MGT_NATIVE_INT64 #define MGT_CREATE_V2_1_MGT_MINIHEADER(pMgtHdr, \ hdrType, \ ppNextByte) \ { \ MGT_U64 *pQWV21MHdr = (MGT_U64 *) pMgtHdr; \ \ pQWV21MHdr[0] = \ ((MGT_U64)(MGTHDRV2$K_MINI_HDR_V2_1_LENGTH))+\ ((MGT_U64)(MGTHDR$M_V) << 8) + \ ((MGT_U64)(0x01) << 16) + \ ((MGT_U64)(0x02) << 24) + \ ((MGT_U64)(hdrType) << 32) + \ ((MGT_U64)(MGT$K_STS_RESERVED) << 40); \ \ if (ppNextByte != NULL) \ { \ char **MGTC21Hptr = ppNextByte; \ *MGTC21Hptr = \ (char *)&(pQWV21MHdr[1]); \ } \ } #else #define MGT_CREATE_V2_1_MGT_MINIHEADER(pMgtHdr, \ hdrType, \ ppNextByte) \ { \ MGT_U32 *pLWV21MHdr = (MGT_U32 *) pMgtHdr; \ \ pLWV21MHdr[0] = \ ((MGTHDRV2$K_MINI_HDR_V2_1_LENGTH)) + \ ((MGTHDR$M_V) << 8) + \ ((0x01) << 16) + \ ((0x02) << 24); \ pLWV21MHdr[1] = \ ((hdrType)) + \ ((MGT$K_STS_RESERVED) << 8); \ \ if (ppNextByte != NULL) \ { \ char **MGTC21Hptr = ppNextByte; \ *MGTC21Hptr = \ (char *)&(pLWV21MHdr[2]); \ } \ } #endif /* // Initialize a V1.1 MO security header into the response buffer // // Create a V1.1 MO security header into the response // buffer. // // This macro assumes that there is enough room in // the response buffer for the V1.1 security header. // // The next available byte parameter is the // address of the field that will receive the // address of the next available byte. If this // parameter is equal to NULL, // then this address is not returned. */ #define MGT_CREATE_V1_1_MGT_SEC_HDR(pDestHdr, \ ppNextByte) \ { \ MGT_CREATE_V1_1_MGT_HEADER \ (pDestHdr, \ MGTHDR$K_REC_TYPE_ACCESS_RIGHTS, \ 0x00, \ 0x00, \ 0x00, \ 0x01, \ 0x01, \ 0x00, \ ppNextByte); \ } /* // Initialize a V2.1 MO security header into the response buffer // // Create a V2.1 MO security header into the response // buffer. // // This macro assumes that there is enough room in // the response buffer for the V2.1 security header. // // The next available byte parameter is the // address of the field that will receive the // address of the next available byte. If this // parameter is equal to NULL, // then this address is not returned. */ #define MGT_CREATE_V2_1_MGT_SEC_HDR(pDestHdr, \ ppNextByte) \ { \ MGT_CREATE_V2_1_MGT_HEADER \ (pDestHdr, \ MGTHDR$K_REC_TYPE_ACCESS_RIGHTS, \ 0x00, \ 0x00, \ 0x00, \ 0x01, \ 0x01, \ 0x00, \ ppNextByte); \ } /* // Return the length of various MO error responses. */ #define MGT_V1_1_MGT_ERROR_RESPONSE_LEN \ (MGTHDR$K_RSP_HDR_V1_1_LEN) #define MGT_V2_1_MGT_ERROR_RESPONSE_LEN \ (MGTHDRV2$K_RSP_HDR_V2_1_LEN) /* // Initialize a MO response into the response buffer // // Initialize a MO response from the MO request. The // header version of the response will be the header // version of the request. // // The next available byte parameter is the // address of the field that will receive the // address of the next available byte. If this // parameter is equal to NULL, // then this address is not returned. // // This macro will carry over the fields that need // to be copied from the MO request to the MO response. // // This macro assumes that for some calls, the // request buffer is the same as the response buffer, // and that the two headers might overlap. If this // is the case, the following context should be saved: // // 1) If the MORE bit is set, the address of the // next request header // 2) If the CONTINUATION bit is set, the data // associated with the continuation packet // 3) If the CONTEXT bit is set, the packet itself // 4) The parameter length and data // 5) The number of parameter records, if applicable // */ #define MGT_INIT_MGT_RESPONSE(pSrcHdr, \ pDestHdr, \ MOErrorStatus, \ paramMajVer, \ paramMinVer, \ ppNextByte) \ { \ MGT_U64 TmpHdr[(MGTHDR$K_ACT_HDR_LEN/8)+1]; \ MGTHDR *pTmpHdr = (MGTHDR *) TmpHdr; \ MGTHDRV2 *pTmpHdrV2 = (MGTHDRV2 *) TmpHdr; \ \ if (((MGTHDR *)pSrcHdr)->mgthdr$b_hdr_major == 1) \ { \ MGT_CREATE_V1_1_MGT_HEADER \ (pTmpHdr, \ MGTHDR$K_REC_TYPE_ACT_RSP, \ 0x00, \ 0x00, \ 0x00, \ paramMajVer, \ paramMinVer, \ 0x00, \ NULL); \ pTmpHdr->mgthdr$b_rsp_status \ = MOErrorStatus; \ } \ else \ { \ MGT_CREATE_V2_1_MGT_HEADER \ (pTmpHdrV2, \ MGTHDR$K_REC_TYPE_ACT_RSP, \ 0x00, \ 0x00, \ 0x00, \ paramMajVer, \ paramMinVer, \ 0x00, \ NULL); \ pTmpHdrV2->mgthdrv2$b_rsp_status \ = MOErrorStatus; \ } \ MGT_COPY_MGT_REQUEST_INFO \ (pSrcHdr,pTmpHdr); \ MGT_COPY_MGT_HEADER \ (pTmpHdr,pDestHdr,ppNextByte); \ } /* // Initialize a MO error response into the response buffer // // Create a MO error response into the response // buffer, and initialize it with data from the MO request // and set the MO response status with the MO error status // parameter. The MO response header version is based // on the MO request header version. // // This macro assumes that there is enough room in // the response buffer for the response buffer. // If a Management is called from RMDRIVER, this // is the case. // // The next available byte parameter is the // address of the field that will receive the // address of the next available byte. If this // parameter is equal to NULL, // then this address is not returned. // // This macro will carry over the fields that need // to be copied from the MO request to the MO response. */ #define MGT_CREATE_MGT_ERROR_RESPONSE( \ pSrcHdr, \ pDestHdr, \ MOErrorStatus, \ ppNextByte) \ { \ MGT_INIT_MGT_RESPONSE \ (pSrcHdr, \ pDestHdr, \ MOErrorStatus, \ 1, \ 1, \ ppNextByte); \ } /* // Convert a MO response back to an MO request // // For the case where MO request and MO responses // share a buffer, upon a continuation the response // header needs to be converted back to a request // header. This routine does that processing. It // clears the flags field in preparation for adding // or attaching other headers. */ #define MGT_CVT_MGT_RESPONSE_TO_REQUEST(pSrcHdr, \ ppNextByte) \ { \ MGTHDR *pCMRTRSrcHdr = (MGTHDR *)pSrcHdr; \ MGTHDRV2 *pCMRTRSrcHdrV2 = (MGTHDRV2 *)pSrcHdr; \ \ pCMRTRSrcHdr->mgthdr$b_flags = 0; \ pCMRTRSrcHdr->mgthdr$v_v = 1; \ \ if (pCMRTRSrcHdr->mgthdr$b_hdr_major <= 2) \ { \ pCMRTRSrcHdr->mgthdr$b_mgt_func = \ MGTHDR$K_REC_TYPE_ACT_REQ; \ pCMRTRSrcHdr->mgthdr$b_rsp_status = \ MGT$K_STS_RESERVED; \ pCMRTRSrcHdr->mgthdr$w_par_len = \ 0; \ pCMRTRSrcHdr->mgthdr$b_num_par_recs = \ 0; \ } \ else \ { \ pCMRTRSrcHdrV2->mgthdrv2$b_mgt_func = \ MGTHDR$K_REC_TYPE_ACT_REQ; \ pCMRTRSrcHdrV2->mgthdrv2$b_rsp_status = \ MGT$K_STS_RESERVED; \ pCMRTRSrcHdrV2->mgthdrv2$w_par_len = \ 0; \ pCMRTRSrcHdrV2->mgthdrv2$b_num_par_recs = \ 0; \ } \ \ if (ppNextByte != NULL) \ { \ char **MGTCMRTRHptr = ppNextByte; \ *MGTCMRTRHptr = \ MGT_GET_MGT_PARAM_ADDR(pCMRTRSrcHdr); \ } \ } /* // Add quadword block to packet // // This macro will copy a quadword block to the // the packet, and adjust the data length of the // packet accordingly. */ #define MGT_ADD_QW_BLOCK_TO_MGT_PACKET(pMgtHdr, \ pQWSrc, \ len) \ { \ int MGTAQWDest = \ (char *)pMgtHdr + \ MGT_MGT_PACKET_LEN(pMgtHdr); \ \ MGT_COPY_QW_BLOCK \ (pQWSrc,MGTAQWDest,len); \ \ MGT_SET_MGT_PACKET_DATA_LEN \ (pMgtHdr, \ MGT_GET_MGT_PACKET_DATA_LEN \ (pMgtHdr) + \ len \ ) \ } /* // Add a main header to a MO packet set // // This macro will add a main header // to a MO packet set at the end of the packet. // It will set all the fields as needed, and will // return the address of the data section for // the added main header. This will also set // the necessary fields in the MO packet set to // indicate that another packet set follows. // // The parMaj parameter is the major version // number for the data the added main packet // will contain, and the parMin parameter is // the minor version. // // The bufLen parameter should be the length // of the buffer from the pSrcHdr parameter // to the end of the buffer. // // This routine returns the address of the // added header as well as the address of the // next available byte. */ #define MGT_ADD_MAIN_HEADER(pSrcHdr, \ bufLen, \ actionCode, \ parMaj, \ parMin, \ actionContext, \ retStatus, \ ppNextHdr, \ ppNextByte) \ { \ MGTHDR *MGTAMHSrc = (MGTHDR *)pSrcHdr; \ MGTHDR *MGTAMHDest; \ MGTHDRV2 *MGTAMHDestV2; \ int remBufLen; \ \ /* Calculate the remaining buffer len */ \ remBufLen = \ bufLen - \ MGT_GET_MGT_PACKET_SET_LEN(pSrcHdr); \ \ /* Find the address for the new */ \ /* packet set. */ \ MGTAMHDest = \ MGT_GET_NEXT_MGT_PACKET_SET_ADDR(pSrcHdr); \ \ /* Create the main header */ \ /* Since the headers are currently */ \ /* the same length and have many of */ \ /* the fields set the same, a straight */ \ /* copy of the header with some */ \ /* adjustments is good for now. */ \ /* Also, for a packet set chain, all */ \ /* the headers must have the same */ \ /* Management IDs, etc. */ \ MGT_COPY_MGT_HEADER_WITH_CHECK \ (pSrcHdr, \ MGTAMHDest, \ remBufLen, \ retStatus, \ ppNextByte \ ); \ MGTAMHDestV2 = \ (MGTHDRV2 *)MGTAMHDest; \ \ /* If this succeeded, fixup the headers */ \ /* The Management function will be the */ \ /* same as the source header */ \ if (retStatus == MGT$K_STS_SUCCESS) \ { \ /* Adjust the source header */ \ MGTAMHSrc->mgthdr$v_more = 1; \ \ /* Adjust the new header */ \ MGTAMHDest->mgthdr$b_flags = 0; \ MGTAMHDest->mgthdr$v_v = 1; \ MGTAMHDest->mgthdr$b_num_par_recs \ = 0; \ MGTAMHDest->mgthdr$w_par_len = 0; \ if (MGTAMHDest->mgthdr$b_hdr_major == 1) \ { \ MGTAMHDest->mgthdr$b_par_major = \ parMaj; \ MGTAMHDest->mgthdr$b_par_minor = \ parMin; \ MGTAMHDest->mgthdr$b_action = \ actionCode; \ MGTAMHDest->mgthdr$l_action_ctx = \ actionContext; \ } \ else \ { \ MGTAMHDestV2->mgthdrv2$b_par_major= \ parMaj; \ MGTAMHDestV2->mgthdrv2$b_par_minor= \ parMin; \ MGTAMHDestV2->mgthdrv2$b_action = \ actionCode; \ MGTAMHDestV2->mgthdrv2$l_action_ctx= \ actionContext; \ } \ \ /* Set the next header variable */ \ if (ppNextHdr != NULL) \ { \ if (MGTAMHDest->mgthdr$b_hdr_major == 1) \ { \ MGTHDR **MGTAMHDestHdr = \ (MGTHDR **)ppNextHdr; \ *MGTAMHDestHdr = MGTAMHDest; \ } \ else \ { \ MGTHDRV2 **MGTAMHDestHdrV2 = \ (MGTHDRV2 **)ppNextHdr; \ *MGTAMHDestHdrV2 = MGTAMHDestV2; \ } \ } \ } \ } /* // Add an End-of-data (EOD) header to a MO packet set // // This macro will add an EOD header to a MO packet set // as determined by the parameter length in the main header. // // The bufLen parameter is the length of the parameter // buffer (the parameter length in the main header // plus the length of the EOD header plus the parameter // length in the EOD header) minus the length of the // actual data. // // It will set all the fields as needed, and will // return the address of just after the end of // the EOD header. // // If the MO packet set already contains a continuation // packet, an error status will be returned. */ #define MGT_ADD_EOD_HEADER(pSrcHdr, \ bufLen, \ retStatus, \ ppNextByte) \ { \ MGTHDRV2 *MGTAEHSrcV2 = \ (MGTHDRV2 *)pSrcHdr; \ int MGTAEHSrcV2Len = \ MGT_GET_MGT_PACKET_LEN(MGTAEHSrcV2); \ MGTHDRV2 *MGTAEHDestV2; \ \ if ((MGTAEHSrcV2->mgthdrv2$v_continuation) || \ (MGTAEHSrcV2->mgthdrv2$v_context) \ ) \ { \ retStatus = MGT$K_STS_EOD_INVALIDADD; \ } \ else if (bufLen < \ MGTHDRV2$K_EOD_HDR_V2_1_LEN \ ) \ { \ retStatus = MGT$K_STS_EOD_INSFBUFLEN; \ } \ else \ { \ /* Find the address for the */ \ /* EOD header */ \ MGTAEHDestV2 = \ MGT_GET_NEXT_MGT_HDR_ADDR(pSrcHdr); \ \ /* Create the header */ \ MGT_CREATE_V2_1_MGT_MINIHEADER \ (MGTAEHDestV2, \ MGTHDR$K_REC_TYPE_EOD, \ NULL \ ); \ \ /* Set the length of the header */ \ MGT_SET_MGT_PACKET_DATA_LEN \ (MGTAEHDestV2, \ bufLen - \ MGT_GET_MGT_PACKET_HEADER_LEN \ (MGTAEHDestV2) \ ); \ \ /* Find the address of the next */ \ /* available byte */ \ if (ppNextByte != NULL) \ { \ char **pTmpNextByte = ppNextByte; \ \ *pTmpNextByte = \ MGT_GET_NEXT_MGT_HDR_ADDR \ (MGTAEHDestV2); \ } \ \ /* Adjust the source header */ \ MGTAEHSrcV2->mgthdrv2$v_eod = 1; \ \ retStatus = MGT$K_STS_SUCCESS; \ } \ } /* // Add a continuation header to a MO packet set // // This macro will add a continuation header // to a MO packet set at the end of the packet. // It will set all the fields as needed, and will // return the address of the data section for // the continuation header. // // If the MO packet set has contains an EOD packet, // the continuation flag will be set. // // The parMaj parameter is the major version // number for the data the continuation packet // will contain, and the parMin parameter is // the minor version. */ #define MGT_ADD_CONT_HEADER(pSrcHdr, \ bufLen, \ parMaj, \ parMin, \ actionContext, \ retStatus, \ ppNextHdr, \ ppNextByte) \ { \ MGTHDRV2 *MGTACHSrcV2 = \ (MGTHDRV2 *)pSrcHdr; \ MGTHDRV2 *MGTACHEODV2; \ MGTHDR *MGTACHDest; \ MGTHDRV2 *MGTACHDestV2; \ \ do \ { \ /* Can't add a continuation header to */ \ /* a MO packet set that already has a */ \ /* context header. */ \ if (MGTACHSrcV2->mgthdrv2$v_context) \ { \ retStatus = MGT$K_STS_CONT_INVALIDADD; \ break; \ } \ \ /* If there is an EOD header, get to */ \ /* the end of that header, else just */ \ /* the end of the main header. */ \ MGTACHEODV2 = \ MGT_GET_MGT_EOD_ADDR(pSrcHdr); \ \ /* Find the address for the */ \ /* continuation header */ \ if (MGTACHEODV2 != NULL) \ { \ MGTACHDest = \ MGT_GET_NEXT_MGT_HDR_ADDR(MGTACHEODV2); \ } \ else \ { \ MGTACHDest = \ MGT_GET_NEXT_MGT_HDR_ADDR(pSrcHdr); \ } \ \ /* Create the continuation header */ \ /* Since the headers are currently */ \ /* the same length and have many of */ \ /* the fields set the same, a straight */ \ /* copy of the header with some */ \ /* adjustments is good for now. */ \ MGT_COPY_MGT_HEADER_WITH_CHECK \ (pSrcHdr, \ MGTACHDest, \ bufLen, \ retStatus, \ ppNextByte \ ); \ if (!MGT_SUCCESS(retStatus)) \ break; \ \ MGTACHDestV2 = \ (MGTHDRV2 *)MGTACHDest; \ \ /* Adjust the source header */ \ MGTACHSrcV2-> \ mgthdrv2$v_continuation = 1; \ \ /* Adjust the EOD header if needed */ \ if (MGTACHEODV2 != NULL) \ MGTACHEODV2-> \ mgthdrv2$v_continuation = 1; \ \ /* Adjust the continuation header */ \ MGTACHDest->mgthdr$b_flags = 0; \ MGTACHDest->mgthdr$v_v = 1; \ MGTACHDest->mgthdr$b_mgt_func = \ MGTHDR$K_REC_TYPE_ACT_CONT; \ MGTACHDest->mgthdr$b_num_par_recs \ = 0; \ MGTACHDest->mgthdr$w_par_len = 0; \ MGTACHDest->mgthdr$b_par_major= parMaj; \ MGTACHDest->mgthdr$b_par_minor= parMin; \ MGTACHDest->mgthdr$l_action_ctx=actionContext; \ \ /* Set the next header variable */ \ if (ppNextHdr != NULL) \ { \ if (MGTACHDest->mgthdr$b_hdr_major == 1) \ { \ MGTHDR **MGTACHDestHdr = \ (MGTHDR **)ppNextHdr; \ *MGTACHDestHdr = MGTACHDest; \ } \ else \ { \ MGTHDRV2 **MGTACHDestHdrV2 = \ (MGTHDRV2 **)ppNextHdr; \ *MGTACHDestHdrV2 = MGTACHDestV2; \ } \ } \ \ } while (FALSE); \ } /* // Attach an existing continuation packet // to a MO packet set // // This macro will attach a continuation header // to a MO packet set at the end of the packet. // It is assumed that the continuation packet // already exists and is at the current end of the // MO packet set. This macro's purpose is to // reattach a continuation packet to a MO packet set // after a response has been converted to a request. // It will set all the fields as needed, and will // return the address at the end of the packet set. // // If the MO packet set has contains an EOD packet, // the continuation flag will be set. */ #ifdef MGTV2_DEFS #if MGTHDRV2$K_CONT_HDR_V2_1_LEN != MGTHDR$K_CONT_HDR_V1_1_LEN #error MGTHDRV2$K_CONT_HDR_V2_1_LEN != MGTHDR$K_CONT_HDR_V1_1_LEN in MGT_MACROS.H #endif #endif #define MGT_ATTACH_CONT_HEADER(pSrcHdr, \ pContHdr, \ retStatus, \ ppNextByte) \ { \ MGTHDRV2 *MGTTCHSrcV2 = \ (MGTHDRV2 *)pSrcHdr; \ MGTHDRV2 *MGTTCHEODV2; \ char *MGTTCHNextByte; \ MGTHDRV2 *MGTTCHCont = \ (MGTHDRV2 *)pContHdr; \ \ do \ { \ /* Can't attach a continuation header */ \ /* to a MO packet set that already has */ \ /* a continuation header or a context */ \ /* header. */ \ if ((MGTTCHSrcV2->mgthdrv2$v_continuation) || \ (MGTTCHSrcV2->mgthdrv2$v_context) \ ) \ { \ retStatus = MGT$K_STS_CONT_INVALIDATT; \ break; \ } \ \ /* If there is an EOD header, get to */ \ /* the end of that header, else just */ \ /* the end of the main header. */ \ MGTTCHEODV2 = \ MGT_GET_MGT_EOD_ADDR(pSrcHdr); \ \ /* Find the address for the */ \ /* continuation header */ \ if (MGTTCHEODV2 != NULL) \ { \ MGTTCHNextByte = \ MGT_GET_NEXT_MGT_HDR_ADDR(MGTTCHEODV2); \ } \ else \ { \ MGTTCHNextByte = \ MGT_GET_NEXT_MGT_HDR_ADDR(pSrcHdr); \ } \ \ /* See if the next byte is the address */ \ /* of the continuation header. */ \ if (MGTTCHNextByte != (char *)MGTTCHCont) \ { \ retStatus = MGT$K_STS_CONT_INVALIDADR; \ break; \ } \ \ /* Do a sanity check on the address */ \ /* given for the continuation header */ \ /* to see if it is still valid. */ \ if (!MGTTCHCont->mgthdrv2$v_v) \ { \ retStatus = MGT$K_STS_CONT_INVALIDHDR; \ break; \ } \ if (MGTTCHCont->mgthdrv2$b_mgt_func != \ MGTHDR$K_REC_TYPE_ACT_CONT \ ) \ { \ retStatus = MGT$K_STS_CONT_INVALIDHDR; \ break; \ } \ if (MGTTCHCont->mgthdrv2$b_hdr_len != \ MGTHDRV2$K_CONT_HDR_V2_1_LEN \ ) \ { \ retStatus = MGT$K_STS_CONT_INVALIDHDR; \ break; \ } \ \ /* Reset the flags field to reflect */ \ /* that this is the end of the packet */ \ /* set. If there is a context header */ \ /* at the end of this packet, it will */ \ /* need to be reattached so that the */ \ /* flag fields of all the headers are */ \ /* set correctly and consistent. */ \ MGTTCHCont->mgthdrv2$b_flags = 0; \ MGTTCHCont->mgthdrv2$v_v = 1; \ \ /* Adjust the source header */ \ MGTTCHSrcV2->mgthdrv2$v_continuation = 1; \ \ /* Adjust the EOD header if needed */ \ if (MGTTCHEODV2 != NULL) \ MGTTCHEODV2-> \ mgthdrv2$v_continuation = 1; \ \ /* Fill in next byte parameter */ \ if (ppNextByte != NULL) \ { \ char **MGTTCHDptr = ppNextByte; \ *MGTTCHDptr = \ MGT_GET_NEXT_MGT_HDR_ADDR(MGTTCHCont); \ } \ \ } while (FALSE); \ } /* // Copy a continuation packet from one MO packet set // to another MO packet set // // This macro will copy a continuation packet from // one MO packet set to another MO packet set. The // continuation packet will be appended to the // destination MO packet. If there is a continuation // packet already associated with the destination // MO packet set, then the retStatus will reflect this. // // This macro assumes that the first 6 fields of the // Management header are the same. */ #define MGT_COPY_CONT_PACKET(pSrcHdr, \ pDestHdr, \ bufLen, \ retStatus, \ ppNextByte) \ { \ MGTHDR *MGTCCDSrc = (MGTHDR *)pSrcHdr; \ MGTHDR *MGTCCDDest = (MGTHDR *)pDestHdr; \ \ /* Pick the right routine according */ \ /* to the Management header version */ \ switch (MGTCCDSrc->mgthdr$b_hdr_major) \ { \ case 1: \ \ MGT_COPY_V1_1_CONT_PACKET \ (pSrcHdr, \ pDestHdr, \ bufLen, \ retStatus, \ ppNextByte \ ); \ break; \ \ case 2: \ \ MGT_COPY_V2_1_CONT_PACKET \ (pSrcHdr, \ pDestHdr, \ bufLen, \ retStatus, \ ppNextByte \ ); \ break; \ \ default: \ \ retStatus = MGT$K_STS_HDR_INCOMPAT; \ break; \ \ } \ } #define MGT_COPY_V1_1_CONT_PACKET(pSrcHdr, \ pDestHdr, \ bufLen, \ retStatus, \ ppNextByte) \ { \ MGTHDR *MGTCCD11Src = (MGTHDR *)pSrcHdr; \ MGTHDR *MGTCCD11Dest = (MGTHDR *)pDestHdr; \ MGTHDR *MGTCCD11ContSrc; \ MGTHDR *MGTCCD11ContDest; \ \ /* First see if there is a */ \ /* continuation packet in the */ \ /* destination MO packet */ \ retStatus = \ (MGTCCD11Dest->mgthdr$v_continuation ? \ MGT$K_STS_CONT_DATA_INVALIDCOPY : \ MGT$K_STS_SUCCESS \ ); \ \ /* If there isn't a continuation */ \ /* already, copy the one from the */ \ /* source MO to the destination MO */ \ if (retStatus == MGT$K_STS_SUCCESS) \ { \ MGTCCD11ContSrc = \ MGT_GET_MGT_CONT_ADDR(pSrcHdr); \ MGTCCD11ContDest = \ MGT_GET_NEXT_MGT_PACKET_SET_ADDR \ (pDestHdr); \ MGT_COPY_MGT_PACKET_WITH_CHECK \ (MGTCCD11ContSrc, \ MGTCCD11ContDest, \ bufLen, \ retStatus, \ ppNextByte \ ); \ \ /* If this succeeded, fixup the header */ \ if (retStatus == MGT$K_STS_SUCCESS) \ { \ MGTCCD11Dest-> \ mgthdr$v_continuation = 1; \ } \ } \ } #define MGT_COPY_V2_1_CONT_PACKET(pSrcHdr, \ pDestHdr, \ bufLen, \ retStatus, \ ppNextByte) \ { \ MGTHDRV2 *MGTCCD21Src = (MGTHDRV2 *)pSrcHdr; \ MGTHDRV2 *MGTCCD21Dest = (MGTHDRV2 *)pDestHdr; \ MGTHDRV2 *MGTCCD21ContSrc; \ MGTHDRV2 *MGTCCD21ContDest; \ \ /* First see if there is a */ \ /* continuation packet in the */ \ /* destination MO packet */ \ retStatus = \ (MGTCCD21Dest->mgthdrv2$v_continuation ? \ MGT$K_STS_CONT_DATA_INVALIDCOPY : \ MGT$K_STS_SUCCESS \ ); \ \ /* If there isn't a continuation */ \ /* already, copy the one from the */ \ /* source MO to the destination MO */ \ if (retStatus == MGT$K_STS_SUCCESS) \ { \ MGTCCD21ContSrc = \ MGT_GET_MGT_CONT_ADDR(pSrcHdr); \ MGTCCD21ContDest = \ MGT_GET_NEXT_MGT_PACKET_SET_ADDR \ (pDestHdr); \ MGT_COPY_MGT_PACKET_WITH_CHECK \ (MGTCCD21ContSrc, \ MGTCCD21ContDest, \ bufLen, \ retStatus, \ ppNextByte \ ); \ \ /* If this succeeded, fixup the header */ \ if (retStatus == MGT$K_STS_SUCCESS) \ { \ MGTHDRV2 *MGTCCDEOD = \ MGT_GET_MGT_EOD_ADDR(pDestHdr); \ if (MGTCCDEOD != NULL) \ MGTCCDEOD-> \ mgthdrv2$v_continuation = 1; \ \ MGTCCD21Dest-> \ mgthdrv2$v_continuation = 1; \ } \ } \ } /* // Copy a continuation packet from one MO packet set // to another MO packet set, replacing the one that is // currently there. // // This macro will copy a continuation packet from // one MO packet set to another MO packet set. The // new continuation packet will replace the old in the // destination MO packet. If there isn't a continuation // packet already associated with the destination // MO packet set, then the retStatus will reflect this. // Since this is a replacement, and the confinuation // packet may be in the middle of the MO packet set, // the new continuation packet should be the same size // as the old one, and if it isn't, the retStatus will // reflect this. */ #define MGT_REPLACE_CONT_PACKET(pSrcHdr, \ pDestHdr, \ retStatus, \ ppNextByte) \ { \ MGTHDR *MGTRCPSrc = (MGTHDR *)pSrcHdr; \ MGTHDR *MGTRCPDest = (MGTHDR *)pDestHdr; \ MGTHDR *MGTRCPCSrc; \ MGTHDR *MGTRCPCDest; \ \ retStatus = MGT$K_STS_SUCCESS; \ do \ { \ /* First see if there is a */ \ /* continuation packet in the */ \ /* source and destination MO packet */ \ if ((!MGTRCPSrc->mgthdr$v_continuation) || \ (!MGTRCPDest->mgthdr$v_continuation) \ ) \ { \ retStatus = \ MGT$K_STS_CONT_DATA_INVALIDREPL; \ break; \ } \ \ /* If there is a continuation already, */ \ /* replace the one from the source MO */ \ /* to the destination MO */ \ MGTRCPCSrc = \ MGT_GET_MGT_CONT_ADDR(pSrcHdr); \ MGTRCPCDest = \ MGT_GET_MGT_CONT_ADDR(pDestHdr); \ MGT_REPLACE_MGT_PACKET \ (MGTRCPCSrc, \ MGTRCPCDest, \ retStatus, \ ppNextByte \ ); \ } while (FALSE); \ } /* // Prepare a packet set chain for another // packet set. It will return the address of the // next packet header. */ #define MGT_ADD_TO_PACKET_SET_CHAIN(pSrcHdr, \ pNextHdr) \ { \ pSrcHdr->mgthdrv2$v_more = TRUE; \ pNextHdr = \ MGT_GET_NEXT_MGT_PACKET_SET_ADDR(pSrcHdr); \ }