#define INCL_DOSERRORS #define INCL_DOSMISC #ifndef OS2_INCLUDED #include #endif #include #include #include #define INCL_RXSHV #define INCL_RXFUNC #include #include "shfuncs.h" const char *PSZ_ZERO = "0"; const char *PSZ_ONE = "1"; /* ------------------------------------------------------------------------- * * SaveResultString * * * * Writes new string contents to the specified RXSTRING, allocating any * * additional memory that may be required. * * * * ARGUMENTS: * * PRXSTRING prsResult: Pointer to an existing RXSTRING for writing. * * PCH pchBytes : The string contents to write to prsResult or NULL * * ULONG ulBytes : The number of bytes in pchBytes to write 0..N. * * * * RETURNS: BOOL * * TRUE if prsResult was successfully updated. FALSE otherwise. * * ------------------------------------------------------------------------- */ BOOL SaveResultString( PRXSTRING prsResult, PCSZ pchBytes, ULONG ulBytes ) { ULONG ulRC; PCH pchNew; // 2016-02-20 SHL Rework for easier usage if (!pchBytes) ulBytes = 0; // Sync for caller if ( ulBytes > 256 ) { // REXX provides 256 bytes by default; allocate more if necessary ulRC = DosAllocMem( (PVOID) &pchNew, ulBytes, PAG_WRITE | PAG_COMMIT ); if ( ulRC != 0 ) { WriteErrorCode( ulRC, "DosAllocMem"); prsResult->strlength = 0; // 2016-02-20 SHL Force result to empty string return ( FALSE ); } // 2015-06-03 SHL dropped DosFreeMem(prsResult->strptr); // 2015-06-03 SHL Pointer not allocated by DosAllocMem prsResult->strptr = pchNew; } if (ulBytes) memcpy( prsResult->strptr, pchBytes, ulBytes ); prsResult->strlength = ulBytes; return ( TRUE ); } /* ------------------------------------------------------------------------- * * WriteStemElement * * * * Creates a stem element (compound variable) in the calling REXX program * * using the REXX shared variable pool interface. * * * * ARGUMENTS: * * PSCZ pszStem : The name of the stem (before the '.') * * ULONG ulIndex : The number of the stem element (after the '.') * * PSCZ pszValue : The value to write to the compound variable. * * * * RETURNS: BOOL * * TRUE on success, FALSE on failure. * * ------------------------------------------------------------------------- */ // 2016-02-20 SHL PSZ --> PCSZ BOOL WriteStemElement( PCSZ pszStem, ULONG ulIndex, PCSZ pszValue ) { SHVBLOCK shvVar; // REXX shared variable pool block ULONG ulRc, ulBytes; CHAR szCompoundName[ US_COMPOUND_MAXZ ]; sprintf( szCompoundName, "%s.%d", pszStem, ulIndex ); if ( pszValue == NULL ) { pszValue = ""; ulBytes = 0; } else { // 2015-06-03 SHL Was using DosAllocMem and leaking memory // REXX API does not free this kind of buffer ulBytes = strlen(pszValue); } MAKERXSTRING( shvVar.shvname, szCompoundName, strlen(szCompoundName) ); shvVar.shvvalue.strptr = (PCH)pszValue; shvVar.shvvalue.strlength = ulBytes; shvVar.shvnamelen = RXSTRLEN( shvVar.shvname ); shvVar.shvvaluelen = RXSTRLEN( shvVar.shvvalue ); shvVar.shvcode = RXSHV_SYSET; shvVar.shvnext = NULL; ulRc = RexxVariablePool( &shvVar ); if ( ulRc > 1 ) { WriteErrorCode( shvVar.shvret, "RexxVariablePool (SHVBLOCK.shvret)"); return FALSE; } return TRUE; } /* ------------------------------------------------------------------------- * * WriteCompoundVariable * * * * Creates a compound variable in the calling REXX program using the REXX * * shared variable pool interface. * * * * ARGUMENTS: * * PCSZ pszStem : The name of the stem (before the '.') * * PCSZ pszTail : The name of the trailing portion (after the '.') * * PCSZ pszValue : The value to write to the compound variable. * * * * RETURNS: BOOL * * TRUE on success, FALSE on failure. * * ------------------------------------------------------------------------- */ // 2016-05-10 ALT PSZ --> PCSZ BOOL WriteCompoundVariable( PCSZ pszStem, PCSZ pszTail, PCSZ pszValue ) { SHVBLOCK shvVar; // REXX shared variable pool block ULONG ulRc, ulBytes; CHAR szCompoundName[ US_COMPOUND_MAXZ ]; sprintf( szCompoundName, "%s.%s", pszStem, pszTail ); if ( pszValue == NULL ) { pszValue = ""; ulBytes = 0; } else { ulBytes = strlen( pszValue ); } MAKERXSTRING( shvVar.shvname, szCompoundName, strlen(szCompoundName) ); shvVar.shvvalue.strptr = (PCH)pszValue; shvVar.shvvalue.strlength = ulBytes; shvVar.shvnamelen = RXSTRLEN( shvVar.shvname ); shvVar.shvvaluelen = RXSTRLEN( shvVar.shvvalue ); shvVar.shvcode = RXSHV_SYSET; shvVar.shvnext = NULL; ulRc = RexxVariablePool( &shvVar ); if ( ulRc > 1 ) { WriteErrorCode( shvVar.shvret, "RexxVariablePool (SHVBLOCK.shvret)"); return FALSE; } return TRUE; } /* ------------------------------------------------------------------------- * * WriteErrorCode * * * * Writes an error code to a special variable in the calling REXX program * * using the REXX shared variable pool interface. This is used to return * * API error codes to the REXX program, since the REXX functions themselves * * normally return string values. * * * * ARGUMENTS: * * ULONG ulError : The error code returned by the failing API call. * * PSZ pszContext: A string describing the API call that failed. * * * * RETURNS: N/A * * ------------------------------------------------------------------------- */ void WriteErrorCode( ULONG ulError, PCSZ pszContext ) { SHVBLOCK shvVar; // REXX shared variable pool block ULONG ulRc; CHAR szErrorText[ US_ERRSTR_MAXZ ]; if ( pszContext == NULL ) sprintf( szErrorText, "%u", ulError ); else sprintf( szErrorText, "%u: %s", ulError, pszContext ); MAKERXSTRING( shvVar.shvname, SZ_ERROR_NAME, strlen(SZ_ERROR_NAME) ); MAKERXSTRING( shvVar.shvvalue, szErrorText, strlen(szErrorText) ); shvVar.shvnamelen = RXSTRLEN( shvVar.shvname ); shvVar.shvvaluelen = RXSTRLEN( shvVar.shvvalue ); shvVar.shvcode = RXSHV_SYSET; shvVar.shvnext = NULL; shvVar.shvret = 0; // 2016-02-26 SHL ulRc = RexxVariablePool( &shvVar ); // 2016-02-26 SHL Correct if if ( ulRc & ~RXSHV_NEWV ) printf("* Unable to set %s: shvret = 0x%x, apiret = 0x%x\n", shvVar.shvname.strptr, (UCHAR)shvVar.shvret, ulRc ); // 2016-02-26 SHL Correct formatting }