× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



Rich,

I'm glad you got past your problem and, as usual, Scott provided an
excellent response. But I would like to add two nits:

1. The inadvertent passing of a Bytes Provided value in excess of 1.5GB
did expose you to some (potentially significant depending on the error
message) storage corruption as the API would feel free to return up to that
amount of exception data and the CL compiler historically (that's a release
sensitive qualifier by the way lol) only allocates 32 bytes for a string

2. You don't need to initialize the Bytes Available field to 0 (bytes 5 -
8 of Scott's example). So long as Bytes Provided equates (I'm qualifying
again as there is a special case for CCHAR enabled error code parameters
though I've never seen it used in practice) to 8 or more, then the API will
set it to 0 if there is no error.

Bruce

On Mon, May 9, 2022 at 12:13 PM Scott Klement <midrange-l@xxxxxxxxxxxxxxxx>
wrote:


Hi Rich,


On 5/9/2022 10:32 AM, Rich Loeber wrote:
> Yep .... when it is a really odd problem, it is usually something
stupid like that.
>
> Rich
> DCL VAR(&APIERR) TYPE(*CHAR) LEN(50)
> DCL VAR(&APIK14) TYPE(*CHAR) LEN(10) VALUE('*SEC')
>
> CALL PGM(QRCVDTAQ) PARM(&DQNAME &QLIBR &FLDLEN +
> &FIELD &SECONDS &APIK6 &APIK7 &APIK8 +
> &APIK9 &APIK10 &APIOPT &APILEN *APIERR +
> &APIK14)

If you pass *APIERR, this will pass the character string '*APIERR' in
the error code parameter to the API, which is not not legitimate. The
API is expecting the first 4 bytes of the parameter to be an integer
containing the length of the parameter.

Since your &APIERR variable is 50 bytes long, the first 4 bytes of the
50 should contain the value x'00000032' (hex 32 = decimal 50). But you
are passing '*API' as the first 4 bytes, which in hex is x'5CC1D7C9', or
in decimal 1,556,207,561. So it thinks you are telling it that you've
provided a variable that is 1.5 GB long.

The API error code is meant to be a data structure containing these fields:

- bytes 1-4 = binary length of the parameter
- bytes 5-8 = binary length of the data the API has placed into the
structure (returned to you)
- bytes 9-15 = the message id (most commonly CPFxxxx)
- byte 16 = reserved
- bytes 17-END = any variable data ("MSGDTA") that goes in the message.

So with 50 bytes, bytes 17-50 (length 34) would be available for
variable data.

It's important to understand that this is one parameter (not multiple)
and contains all of this data as part of the parameter. i.e. a data
structure in most languages.

You can check the 2nd field (bytes 5-8) to determine if an error
occurred. Set it to 0 before calling the API, and if it's not 0
afterwards, you know there was an error. You can also determine the
length of the returned message data by subtracting 16 from it, so if
that second field was 26, it means 10 bytes of message data was returned.

Here's an example of defining the API error in CL.

PGM

DCL VAR(&APIERR) TYPE(*CHAR) LEN(50)
DCL VAR(&LENPROV) TYPE(*INT) LEN(4) +
STG(*DEFINED) DEFVAR(&APIERR 1)
DCL VAR(&LENAVAIL) TYPE(*INT) LEN(4) +
STG(*DEFINED) DEFVAR(&APIERR 5)
DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) +
STG(*DEFINED) DEFVAR(&APIERR 9)
DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(34) +
STG(*DEFINED) DEFVAR(&APIERR 17)

CHGVAR VAR(&LENPROV) VALUE(50)
CHGVAR VAR(&LENAVAIL) VALUE(0)

/* CALL QRCVDTAQ HERE, PASS &APIERR AS 13TH PARAMETER */

IF (&LENAVAIL *NE 0) DO
/* AN ERROR OCCURRED. THE MESSAGE ID IS IN &MSGID */
ENDDO


ENDPGM

This is using the "defined on" syntax to create one 50 byte field with
sub-fields containing the values within in... the CL version of a data
structure.

You may also run into older examples that use %BIN and %SST to access
the subfields instead of using the "defined on" syntax (which is less
code and, in my opinion, easier to read.)

PGM

DCL VAR(&APIERR) TYPE(*CHAR) LEN(50)

CHGVAR VAR(%BIN(&APIERR 1 4)) VALUE(50)
CHGVAR VAR(%BIN(&APIERR 5 4)) VALUE(0)

/* CALL QRCVDTAQ HERE, PASS &APIERR AS 13TH PARAMETER */

IF (%BIN(&APIERR 5 4) *NE 0) DO
/* AN ERROR OCCURRED. THE MESSAGE ID IS: */
CHGVAR VAR(&MSGID) VALUE(%SST(&APIERR 17 7))
ENDDO

ENDPGM

Hope that helps.
--
This is the Midrange Systems Technical Discussion (MIDRANGE-L) mailing list
To post a message email: MIDRANGE-L@xxxxxxxxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
visit: https://lists.midrange.com/mailman/listinfo/midrange-l
or email: MIDRANGE-L-request@xxxxxxxxxxxxxxxxxx
Before posting, please take a moment to review the archives
at https://archive.midrange.com/midrange-l.

Please contact support@xxxxxxxxxxxxxxxxxxxx for any subscription related
questions.

Help support midrange.com by shopping at amazon.com with our affiliate
link: https://amazon.midrange.com




As an Amazon Associate we earn from qualifying purchases.

This thread ...

Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.