0

I'm working on z/OS and trying to use the Window Services provided by IBM. Everything work perfectly except the creation of an object by its DSNAME.

When I call CSRIDAC with a DSNAME I have the error : "The system was unable to allocate or unallocate the data set specified as object_name. The value rrrr is the return code from dynamic allocation. The value nnnn is the two-byte reason code from dynamic allocation. See z/OS MVS Programming: Authorized Assembler Services Guide for dynamic allocation return and reason codes."

So I searched for the meaning of the reason code which is 037c and found : "Invalid LEN specified in text unit. The accompanying message IKJ56231I indicates the number of the text unit in error."

So, it seems that the Window Services is calling the Dynamic Allocation service to create the object by its DSNAME and it makes a mistake when it counts the number of characters in the DSNAME I provided.

My DSNAME is a valid VSAM file name and I successfully read this dataset by another way with the same DSNAME.

Well, here is the code of my function calling the CSRIDAC function :

ozwinsrvObject *ozwinsrvObjectCreate(uint32_t uiFlags, int32_t iObjectSize, uint8_t *pcObjectName, int32_t *piHighOffset, int32_t *piRc)
{
ozwinsrvObject *pobject = __malloc31(sizeof(ozwinsrvObject));

    *piRc = OZWINSRV_NO_ERROR;
    pobject->pheap = __malloc31(18*4);
    pobject->pparmList = __malloc31(11 * sizeof(int32_t));
    memcpy(&pobject->parmObject.acOpType[0] , "BEGIN", 5);
    pobject->parmObject.iObjectSize = iObjectSize;
    pobject->parmObject.iHighOffset = *piHighOffset;
    if(uiFlags & OZWINSRV_OBJECT_F_TYPE_DDNAME)
    {
        memcpy(&pobject->parmObject.acObjectType[0], "DDNAME   ", 9);
    }
    else {
        if(uiFlags & OZWINSRV_OBJECT_F_TYPE_DSNAME)
        {
            memcpy(&pobject->parmObject.acObjectType[0], "DSNAME   ", 9);
        }
        else
        {
            memcpy(&pobject->parmObject.acObjectType[0], "TEMPSPACE", 9);
        }
    }
    if(uiFlags & OZWINSRV_OBJECT_F_SCROLL_AREA_YES)
    {
        memcpy(&pobject->parmObject.acScrollArea[0], "YES", 3);
    }
    else
    {
        memcpy(&pobject->parmObject.acScrollArea[0], "NO ", 3);
    }
    if(uiFlags & OZWINSRV_OBJECT_F_STATE_NEW)
    {
        memcpy(&pobject->parmObject.acObjectState[0], "NEW", 3);
    }
    else
    {
        memcpy(&pobject->parmObject.acObjectState[0], "OLD", 3);
    }
    if(uiFlags & OZWINSRV_OBJECT_F_ACCESS_MODE_UPDATE)
    {
        memcpy(&pobject->parmObject.acAccessMode[0], "UPDATE", 6);
    }
    else
    {
        memcpy(&pobject->parmObject.acAccessMode[0], "READ  ", 6);
    }
    memcpy(&pobject->acObjectName[0], pcObjectName, strlen(pcObjectName));
    if(strlen(pcObjectName) < 45)
    {
        pobject->acObjectName[strlen(pcObjectName)] = ' ';
    }
    memset(pobject->pparmList, 0, 11 * sizeof(int32_t));
    pobject->pparmList[0] = (int32_t) &pobject->parmObject.acOpType[0];
    pobject->pparmList[1] = (int32_t) &pobject->parmObject.acObjectType[0];
    pobject->pparmList[2] = (int32_t) &pobject->parmObject.acObjectName[0];
    pobject->pparmList[3] = (int32_t) &pobject->parmObject.acScrollArea[0];
    pobject->pparmList[4] = (int32_t) &pobject->parmObject.acObjectState[0];
    pobject->pparmList[5] = (int32_t) &pobject->parmObject.acAccessMode[0];
    pobject->pparmList[6] = (int32_t) &pobject->parmObject.iObjectSize;
    pobject->pparmList[7] = (int32_t) &pobject->acObjectId[0];
    pobject->pparmList[8] = (int32_t) &pobject->parmObject.iHighOffset;
    pobject->pparmList[9] = (int32_t) &pobject->parmObject.iRc;
    pobject->pparmList[10] = (int32_t) &pobject->parmObject.iReasonC;
    x6csridac(pobject->pparmList, pobject->pheap);
    if(pobject->parmObject.iRc != 0)
    {
        printf("Error creating object (csridac) Rc=0x%x, ReasonC=0x%x\n", pobject->parmObject.iRc, pobject->parmObject.iReasonC);
        *piRc = OZWINSRV_ERROR_WINDOW_OBJECT_CREATE;
    }
    *piHighOffset = pobject->parmObject.iHighOffset;
    pobject->iObjectSize = iObjectSize;
    pobject->uiFlags = uiFlags;
    pobject->uiNbViews = 0;
    return pobject;
}

Then, here is the code calling this function :

int32_t iRc = 0;
int32_t iPageSize = 32*1024;
int32_t iPageOffset = iPageSize/4/1024;
int32_t iSize = 1;
int32_t iRealSize = 1;
ozwinsrvObject *pObject;
ozwinsrvWindow *pWindow;
uint8_t acFileName[] = "DSNB10.DSNDBC.DBTLS00.TS1449.I0001.A001";

pObject = ozwinsrvObjectCreate(OZWINSRV_OBJECT_F_ACCESS_MODE_READ | OZWINSRV_OBJECT_F_SCROLL_AREA_NO | OZWINSRV_OBJECT_F_STATE_OLD | OZWINSRV_OBJECT_F_TYPE_DSNAME,
                               iSize, &acFileName[0], &iRealSize, &iRc);

I hope my explanation of the problem is clear. Feel free to ask some questions if it's not. Thanks !

Machavity
  • 30,841
  • 27
  • 92
  • 100
Timothée
  • 77
  • 7
  • I'm not posting this as an answer because this is only a guess, and I can't test it. There may be trailing garbage in the data set name from an uninitialized heap area. The CSRIDAC doc says "Define object_name as character data of length 1 to 44. If object_name contains fewer than 44 characters, pad the name on the right with blanks.". Your `if` statement sets just the NUL to a space, so there may be trailing garbage. I would add a `memset(&pobject->acObjectName[0], ' ', sizeof(acObjectName));` (assuming sizeof(acObjectName) is 44, otherwise hard code 44) before the acObjectName memcpy. – zarchasmpgmr Jun 11 '18 at 16:26
  • This initializes the entire area to spaces before your move, so when you move just the `strlen` of the input parameter, the area past tne NUL is still spaces. Then you can set the NUL to spaces and now you have a valid 44-byte area with a data set name. One thing to remember is that many of these interfaces were designed pre-C language, so you have to think of how the entire field to its maximum length must look (especially with things like DD names and DSNs. If this fixes your problem, please tell us and I will write this up as an answer. – zarchasmpgmr Jun 11 '18 at 16:30
  • I tried your solution but it's not solving my problem. I'm not sure that the problem is from the DSNAME finally... The Window Services could send multiple text units to the Dynamic Allocation service. The problem is that I can't know which text unit is throwing the error. Is there a way to have some logs or verbose on this ? – Timothée Jun 12 '18 at 07:19
  • 1
    One way forward is to take a system dump on the dynamic allocation error (if you don't know how, read about DYNDUMP and SYSMDUMP in the IBM Language Environment Debugging Guide). Once you have the dump, find the trace table and locate the SVC 99 trace entry just before your dump - this is the dynamic allocation. R1 at entry to the SVC will have the dynalloc parameter list (which hopefully will also be in your dump) and from there, you can probably figure out what's wrong. – Valerie R Jun 12 '18 at 17:34
  • Well, darn. I'd still keep that, though, to make sure you have 44 bytes of legitimate data for the data set name. Follow Valerie's suggestion next (take a dump). We can help you interpret the SVC 99 text units (it's fun, if you're masochistic). – zarchasmpgmr Jun 13 '18 at 00:14
  • Thank you for you answers! I can't have a dump of the dynalloc because it is done by the Window Services, so when I ask for a dump its too late and I can't see the text units. I'm continuing the investigation, the problem could come from any little thing... – Timothée Jun 13 '18 at 09:56
  • If you have a good relationship with your systems programmer, he can get you what's called a slip dump. First, take whatever dump you can after the CSR module returns and find the SVC 99 PSW in the trace table. SLIP uses the PER hardware for what's called an instruction fetch trap - when the system executes the instruction following the SVC 99 instruction, an interrupt is generated and you get your dump. Your systems programmer should know how to set it up if you give him a module and offset, or a PSW in LPA (if that's where the IBM CSR* modules live). – Valerie R Jun 15 '18 at 15:42
  • There are a lot of things wrong with that code but I wont nitpick! What does interest me is why you are creating a parameter list vector and a savearea? Is `x6csridac` and assembler routine that calls `CSRIDAC`? If so I would question why you need that for a callable service. I use `#pragma linkage(csridac,OS)`. – David Crayford Jun 20 '18 at 03:42
  • Valerie, I have to ask for a slip dump but I'm not sure my systems programmer will make it. Wait and see... David, I'm not sure why but using #pragma linkage(csridac,OS) won't works and the link to csridac cannot be created. So I created an assembler routine that calls CSRIDAC. And this is why I'm using a parameter list to call my routine, because I have a lot of parameters and it seems to be the easiest way. – Timothée Jun 20 '18 at 07:19
  • If you're having linkage problems make sure you have SYS1.CSSLIB in the SYSLIB (if your using JCL). – David Crayford Jun 22 '18 at 04:22
  • Ok, I just solved the problem! And gess want... It was a little error in my code, I switched to variables names... I'm posting the answer. Thanks to all for your help, it really helps me investigating around the problem! – Timothée Jul 02 '18 at 07:20

1 Answers1

0

I have found my error and posting the answer. I use the following line to copy the name in an array:

memcpy(&pobject->acObjectName[0], pcObjectName, strlen(pcObjectName));

But! When I put this array in my parameter list I use this line of code :

pobject->pparmList[2] = (int32_t) &pobject->parmObject.acObjectName[0];

This means that the name is in pobject->acObjectName and I put pobject->parmObject.acObjectName in the parameter list. These two arrays are not the same variables...

I'm sorry for my mistake and confirm that the DWS works well.

Timothée
  • 77
  • 7