home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pc3270sa.zip / apps / winaping / docpic.cpp < prev    next >
Text File  |  2002-02-28  |  18KB  |  440 lines

  1. #include "stdafx.h"
  2. #include "constdef.h"
  3. #include "cpiccmc.h"
  4.  
  5. #include "winapdoc.h"
  6. #include "docpic.h"                   // put this one after winapdoc.h
  7.  
  8. //----------------------------------------------------------------------------
  9. // This does the allocation to partner
  10. //----------------------------------------------------------------------------
  11. long DoAllocate(CWinapingDoc* pDoc) {
  12.  
  13.   static CString DEFALUT_SYM_DEST_NAME = _T("APINGD  ");
  14.   static CString   BLANK_SYM_DEST_NAME = _T("        ");
  15.   static CString       BLANK_MODE_NAME = _T("        ");
  16.  
  17.   CM_INT32         cm_rc;               // return code for CPIC calls
  18.   CM_INT32         length;              // length field for general use
  19.  
  20.   //--------------------------------------------------------------------------
  21.   // decide destination is parter lu name, symbolic name, or neither (NULL)
  22.   BOOL plnProvided = FALSE;
  23.   BOOL symProvided = FALSE;
  24.   CM_INT32 dest_len = (pDoc->pingInfo.destination).GetLength();
  25.   if (dest_len > 0) {
  26.     if ((dest_len <= MAX_SYM_DEST_NAME) &&
  27.         ((pDoc->pingInfo.destination).Find(_T(".")) == -1)) symProvided = TRUE;
  28.     else plnProvided = TRUE;
  29.         }
  30.  
  31.   //--------------------------------------------------------------------------
  32.   // cminit time
  33.   if (symProvided) {                  // cminit with given symbolic name
  34.     for (int i = dest_len; i < MAX_SYM_DEST_NAME; i++) {
  35.       pDoc->pingInfo.destination += _T(" " );        // pad with blank
  36.       }
  37.     cminit(pDoc->cm_conv_id,
  38.            (unsigned char*) (LPCTSTR)(pDoc->pingInfo.destination), &cm_rc);
  39.     if (cm_rc != CM_OK) {
  40.       pDoc->cmcall  = _T("CMINIT with ") + pDoc->pingInfo.destination;
  41.       return cm_rc;
  42.       }
  43.     }
  44.   else {                              // cminit with default names
  45.     cminit(pDoc->cm_conv_id,
  46.            (unsigned char*) (LPCTSTR)DEFALUT_SYM_DEST_NAME, &cm_rc);
  47.     if (cm_rc != CM_OK) {
  48.       cminit(pDoc->cm_conv_id,
  49.              (unsigned char*) (LPCTSTR)BLANK_SYM_DEST_NAME, &cm_rc);
  50.       if (cm_rc != CM_OK) {
  51.         pDoc->cmcall  = _T("CMINIT with default destinations");
  52.         return cm_rc;
  53.         }
  54.       }
  55.     }
  56.   if (pDoc->stoprunning) return 0;
  57.  
  58.   //--------------------------------------------------------------------------
  59.   // If partner lu name given then set it, else make sure there is a good one
  60.   if (plnProvided) {
  61.     cmspln(pDoc->cm_conv_id,
  62.            (unsigned char*) (LPCTSTR)(pDoc->pingInfo.destination),
  63.            &dest_len, &cm_rc);
  64.     if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSPLN"); return cm_rc; }
  65.     }
  66.   else {
  67.     unsigned char pln[MAX_DESTINATION + 1];
  68.     cmepln(pDoc->cm_conv_id, pln, &length, &cm_rc);
  69.     if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMEPLN"); return cm_rc; }
  70.     if ((length == 1) && (pln[0] == ' ')) {
  71.       pDoc->cmcall  = _T("CMEPLN"); return LAST_MESSAGE_NUM-1; } // special rc
  72.     }
  73.   if (pDoc->stoprunning) return 0;
  74.  
  75.   //--------------------------------------------------------------------------
  76.   // Set tp name if given
  77.   length = (pDoc->pingInfo.tpName).GetLength();
  78.   if (length > 0) {
  79.     cmstpn(pDoc->cm_conv_id, (unsigned char*) (LPCTSTR)(pDoc->pingInfo.tpName),
  80.            &length, &cm_rc);
  81.     if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSTPN"); return cm_rc; }
  82.     }
  83.   if (pDoc->stoprunning) return 0;
  84.  
  85.   //--------------------------------------------------------------------------
  86.   // Set mode name if given
  87.   length = (pDoc->pingInfo.mode).GetLength();
  88.   if ((length == 0) && plnProvided) {         // when partner lu name given &
  89.     pDoc->pingInfo.mode = BLANK_MODE_NAME;   // no mode name given, use blanks
  90.     length = 8;
  91.     }
  92.   if (length > 0) {
  93.     cmsmn(pDoc->cm_conv_id, (unsigned char*) (LPCTSTR)(pDoc->pingInfo.mode),
  94.           &length, &cm_rc);
  95.     if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSMN"); return cm_rc; }
  96.     }
  97.   if (pDoc->stoprunning) return 0;
  98.  
  99.   //--------------------------------------------------------------------------
  100.   // Security (no override when symbolic name & send security not checked)
  101.   if (plnProvided || pDoc->pingInfo.security) {
  102.     CM_INT32 security_type = XC_SECURITY_NONE;
  103.     if (pDoc->pingInfo.security) security_type = XC_SECURITY_PROGRAM;
  104.     cmscst(pDoc->cm_conv_id, &security_type, &cm_rc);
  105.     if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSCST"); return cm_rc; }
  106.     if (pDoc->stoprunning) return 0;
  107.  
  108.     if (pDoc->pingInfo.security) {
  109.       length = (pDoc->pingInfo.userID).GetLength();
  110.       if (length > 0) {
  111.         cmscsu(pDoc->cm_conv_id,
  112.                (unsigned char*) (LPCTSTR)(pDoc->pingInfo.userID),
  113.                &length, &cm_rc); if (cm_rc != CM_OK)
  114.         if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSCSU"); return cm_rc; }
  115.         if (pDoc->stoprunning) return 0;
  116.         }
  117.       length = (pDoc->pingInfo.password).GetLength();
  118.       if (length > 0) {
  119.         cmscsp(pDoc->cm_conv_id,
  120.                (unsigned char*) (LPCTSTR)(pDoc->pingInfo.password),
  121.                &length, &cm_rc);
  122.         if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSCSP"); return cm_rc; }
  123.         if (pDoc->stoprunning) return 0;
  124.         }
  125.       }
  126.     }
  127.  
  128.   //--------------------------------------------------------------------------
  129.   // Set sync level
  130.   CM_SYNC_LEVEL sync_level = CM_CONFIRM;
  131.   cmssl(pDoc->cm_conv_id, &sync_level, &cm_rc);
  132.   if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSSL"); return cm_rc; }
  133.   if (pDoc->stoprunning) return 0;
  134.  
  135.   //--------------------------------------------------------------------------
  136.   // Set prepare to receive type
  137.   CM_PREPARE_TO_RECEIVE_TYPE prep_to_receive = CM_PREP_TO_RECEIVE_FLUSH;
  138.   cmsptr(pDoc->cm_conv_id, &prep_to_receive, &cm_rc);
  139.   if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSPTR"); return cm_rc; }
  140.   if (pDoc->stoprunning) return 0;
  141.  
  142.   //--------------------------------------------------------------------------
  143.   // Do allocation
  144.   DWORD time_start = GetCurrentTime();
  145.   cmallc(pDoc->cm_conv_id, &cm_rc);
  146.   pDoc->alloctime = GetCurrentTime() - time_start;
  147.   if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMALLC"); return cm_rc; }
  148.  
  149.   return cm_rc;
  150. }
  151.  
  152. //----------------------------------------------------------------------------
  153. // This does version/plateform information exchange with partner
  154. //----------------------------------------------------------------------------
  155. long DoExchange(CWinapingDoc* pDoc) {
  156.     CM_PREPARE_TO_RECEIVE_TYPE prep_to_receive; /* CPI-C prepare to receive  */
  157.     CM_SEND_TYPE send_type;                 /* CPI-C send type               */
  158.     CM_INT32    cm_rc;                      /* CPI-C return code             */
  159.     unsigned char buffer[EXCHANGE_BUFFER_SIZE]; /* data buffer               */
  160.     CM_INT32    length;                     /* generic length variable       */
  161.     CM_INT32    rts_received;               /* request to send received      */
  162.     CM_INT32    max_receive_len;            /* Max receive length on CMRCV   */
  163.     CM_INT32    what_received;              /* What received parm from CMRCV */
  164.     CM_INT32    received_len;               /* Amount of data rcvd on CMRCV  */
  165.     CM_INT32    status_received;            /* Status from CMRCV             */
  166.  
  167.   //--------------------------------------------------------------------------
  168.   // start timer
  169.   pDoc->confirmtime = 0;
  170.   DWORD time_start = GetCurrentTime();
  171.   //--------------------------------------------------------------------------
  172.   prep_to_receive = CM_PREP_TO_RECEIVE_FLUSH;
  173.   cmsptr(pDoc->cm_conv_id, &prep_to_receive, &cm_rc);
  174.   if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSPTR"); return cm_rc; }
  175.  
  176.   send_type = CM_BUFFER_DATA;
  177.   cmsst(pDoc->cm_conv_id, &send_type, &cm_rc);
  178.   if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSST"); return cm_rc; }
  179.  
  180.   buffer[0] = CPICERR_EXCHANGE_VERSION;
  181.   buffer[1] = MAJOR_VERSION;
  182.   buffer[2] = MINOR_VERSION;
  183.   length = 3;
  184.   cmsend(pDoc->cm_conv_id, buffer, &length, &rts_received, &cm_rc);
  185.   if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSEND"); return cm_rc; }
  186.   if (pDoc->stoprunning) return 0;
  187.  
  188.   max_receive_len = sizeof(buffer);
  189.   cmrcv (pDoc->cm_conv_id, buffer, &max_receive_len, &what_received,
  190.          &received_len, &status_received, &rts_received, &cm_rc);
  191.   if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMRCV"); return cm_rc; }
  192.   if (pDoc->stoprunning) return 0;
  193.  
  194.   if (what_received != CM_NO_DATA_RECEIVED) {
  195.     if (received_len > 2 && buffer[0]==CPICERR_EXCHANGE_VERSION) {
  196.       if (!pDoc->pingInfo.echo) {                      // we are doing one way
  197.         if ( (buffer[1] >  ONEWAY_MAJOR_VERSION) ||
  198.             ((buffer[1] == ONEWAY_MAJOR_VERSION) &&
  199.              (buffer[2] >= ONEWAY_MINOR_VERSION)) ) { }
  200.         else {            // partner does not support one way, will do two way
  201.           pDoc->pingInfo.echo   = TRUE;
  202.           pDoc->pingInfo.verify = FALSE;
  203.           pDoc->cmcall  = _T("No echo request");
  204.           cm_rc = -1;     // special rc to display 2 way message
  205.           }
  206.         }
  207.     if (received_len > 4 && buffer[3]==CPICERR_EXCHANGE_OPSYS_STRING) {
  208.       LPSTR pWork = pDoc->partner.GetBuffer(received_len-4);
  209.       for (int nCount = 4; nCount < received_len; nCount++)
  210.         *pWork++ = buffer[nCount];
  211.       pDoc->partner.ReleaseBuffer(received_len-4);
  212.       }
  213.     }
  214.   if (status_received == CM_CONFIRM_RECEIVED) {
  215.     cmcfmd(pDoc->cm_conv_id, &cm_rc);
  216.     if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMCFMD"); return cm_rc; }
  217.     }
  218.   else if (status_received != CM_SEND_RECEIVED) {
  219.          pDoc->cmcall  = _T("Exchange version/platform");
  220.          cm_rc = LAST_MESSAGE_NUM - 2;                  // special rc
  221.          }
  222.   }
  223.   pDoc->confirmtime = GetCurrentTime() - time_start;
  224.  
  225.   return cm_rc;
  226. }
  227.  
  228. //----------------------------------------------------------------------------
  229. // This does one iteration
  230. //----------------------------------------------------------------------------
  231. long DoIteration(CWinapingDoc* pDoc, long* pTime, BOOL* pVerifyOK) {
  232.  
  233.   CM_INT32       cm_rc;
  234.   CM_INT32       length = pDoc->pingInfo.packetSize;
  235.   CM_INT32       rts_received;
  236.   UINT           nIdx;
  237.   unsigned char* px;
  238.   unsigned char* py;
  239.   unsigned char  seed1, seed2;
  240.   DWORD          time_start;
  241.   CM_SEND_TYPE   send_type = CM_BUFFER_DATA;
  242.  
  243.   seed1 = seed2 = rand() % 26;                 // randomly between 0 & 25
  244.   *pTime = 0;
  245.   *pVerifyOK = TRUE;
  246.   //--------------------------------------------------------------------------
  247.   cmsst(pDoc->cm_conv_id, &send_type, &cm_rc);
  248.   if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSST"); return cm_rc; }
  249.  
  250.   //--------------------------------------------------------------------------
  251.   // Start timer
  252.   time_start = GetCurrentTime();
  253.  
  254.   //--------------------------------------------------------------------------
  255.   // Send consecutivePackets times
  256.   for (nIdx = 1; nIdx <= pDoc->pingInfo.consecutivePackets; nIdx++) {
  257.     if (pDoc->pingInfo.verify) {                    // fill in buffer if verify
  258.       py = (pDoc->buffer) + (pDoc->pingInfo.packetSize);           // end point
  259.       for (px = pDoc->buffer; px < py; ) {
  260.         *(px++) = 'a'+ seed1++;
  261.         if (seed1 >= 26) seed1 -= 26;
  262.         }
  263.       }
  264.     if (nIdx == pDoc->pingInfo.consecutivePackets) { // this is last one to send
  265.       if (pDoc->pingInfo.echo) send_type = CM_SEND_AND_PREP_TO_RECEIVE;
  266.       else                     send_type = CM_SEND_AND_CONFIRM;
  267.       cmsst(pDoc->cm_conv_id, &send_type, &cm_rc);
  268.       if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSST"); return cm_rc; }
  269.       }
  270.  
  271.     cmsend(pDoc->cm_conv_id, pDoc->buffer, &length, &rts_received, &cm_rc);
  272.     if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMSEND"); return cm_rc; }
  273.     if (pDoc->stoprunning) return 0;
  274.     }
  275.  
  276.   *pTime = GetCurrentTime() - time_start;         // in no echo case
  277.   if (pDoc->pingInfo.echo) {
  278.     //--------------------------------------------------------------------------
  279.     // Receive consecutivePackets times
  280.  
  281.     CM_INT32      rts_received;
  282.     CM_INT32      max_receive_len = pDoc->pingInfo.packetSize;
  283.     CM_INT32      data_received;
  284.     CM_INT32      received_len;
  285.     CM_INT32      status_received;
  286.     unsigned long total_bytes = (pDoc->pingInfo.consecutivePackets) *
  287.                                 (pDoc->pingInfo.packetSize);   // total expected
  288.  
  289.     nIdx = pDoc->pingInfo.consecutivePackets;             // # of cmrcv expected
  290.     do {
  291.       cmrcv (pDoc->cm_conv_id, pDoc->buffer, &max_receive_len, &data_received,
  292.              &received_len, &status_received, &rts_received, &cm_rc);
  293.       if (cm_rc != CM_OK) { pDoc->cmcall  = _T("CMRCV"); return cm_rc; }
  294.       if (pDoc->stoprunning) return 0;
  295.       if (data_received != CM_NO_DATA_RECEIVED) {
  296.         nIdx--;
  297.         total_bytes -= received_len;
  298.         if ((pDoc->pingInfo.verify) && (*pVerifyOK)) {
  299.           if (nIdx) {                     // update seed2 if not last cmrcv
  300.             seed2 += (unsigned char) (received_len % 26);
  301.             if (seed2 >= 26) seed2 -= 26;
  302.             }
  303.           else {                          // verify data for the last cmrcv
  304.             px = pDoc->buffer;
  305.             py = px + received_len;       // end point
  306.             while ((*pVerifyOK) && (px < py)) {
  307.               if (*(px++) != 'a' + seed2++) *pVerifyOK = FALSE;
  308.               if (seed2 >= 26) seed2 -= 26;
  309.               }
  310.             }
  311.           }
  312.         }
  313.       } while ((status_received !=  CM_SEND_RECEIVED));
  314.  
  315.     *pTime = GetCurrentTime() - time_start;    // time it at echo end
  316.     if ((nIdx) || (total_bytes)) {
  317. //    seed2 = seed1;                                   // reset seed2 as seed1
  318.       pDoc->cmcall  = _T("An iteraion");
  319.       cm_rc = LAST_MESSAGE_NUM - 4;                    // special rc
  320.       }
  321.     }
  322.  
  323.   return cm_rc;
  324. }
  325.  
  326. //----------------------------------------------------------------------------
  327. // This does cpic deallocation with partner
  328. //----------------------------------------------------------------------------
  329. long DoDeallocate(CWinapingDoc* pDoc) {
  330.  
  331.   //--------------------------------------------------------------------------
  332.   CM_INT32 cm_rc;
  333.  
  334.   CM_CONVERSATION_STATE cm_state;
  335.   cmecs(pDoc->cm_conv_id, &cm_state, &cm_rc);
  336.   if (cm_rc == CM_PROGRAM_PARAMETER_CHECK) return 0;
  337.   if (cm_rc == CM_OK) {
  338. //if (cm_state != CM_INITIALIZE_STATE) {
  339.     CM_DEALLOCATE_TYPE deallocate_type = CM_DEALLOCATE_FLUSH;
  340.     cmsdt(pDoc->cm_conv_id, &deallocate_type, &cm_rc);
  341.     if (cm_rc != CM_OK) pDoc->cmcall  = _T("CMSDT");
  342.     else {
  343.       cmdeal(pDoc->cm_conv_id, &cm_rc);
  344.       if (cm_rc != CM_OK) {   // try again (conversation state could be RECEIVE)
  345.         deallocate_type = CM_DEALLOCATE_ABEND;
  346.         cmsdt(pDoc->cm_conv_id, &deallocate_type, &cm_rc);
  347.         if (cm_rc != CM_OK) pDoc->cmcall  = _T("CMSDT");
  348.         else {
  349.           cmdeal(pDoc->cm_conv_id, &cm_rc);
  350.           if (cm_rc != CM_OK) pDoc->cmcall  = _T("CMSDEAL");
  351.           }
  352.         }
  353.       }
  354.     }
  355.  
  356.   return cm_rc;
  357. }
  358.  
  359. //----------------------------------------------------------------------------
  360. // This translate the cpic return code to a message string
  361. //----------------------------------------------------------------------------
  362. void DoTranslate(CWinapingDoc* pDoc, long rc)
  363. {
  364.   typedef struct t_cpicmessage {
  365.     char *Message;
  366.     CM_INT32 Code;
  367.     } CPICMESSAGE;
  368.  
  369. //{"CM_SYNC_LVL_NOT_SUPPORTED_LU    ", 7},
  370. //{"CM_SYNC_LEVEL_NOT_SUPPORTED_LU  ", 7},
  371. //{"CM_CONV_DEALLOC_AFTER_SYNCPT  ", 136},
  372. //{"CM_INCLUDE_PARTNER_REJECT_BO  ", 137},
  373.  
  374.   CPICMESSAGE CPICReturnCode[] = {
  375.     {"Will do echo without verify", -1},     // -1 ===> info only, will go on
  376.     {"Unexpected number of data echoed", LAST_MESSAGE_NUM-4},
  377.     {"For Packet Size as requested", LAST_MESSAGE_NUM-3},
  378.     {"CM_SEND_RECEIVED status not received", LAST_MESSAGE_NUM-2},
  379.     {"Extracted partner lu name invalid", LAST_MESSAGE_NUM-1},
  380.     {"CM_OK", 0},
  381.     {"CM_ALLOCATE_FAILURE_NO_RETRY", 1},
  382.     {"CM_ALLOCATE_FAILURE_RETRY", 2},
  383.     {"CM_CONVERSATION_TYPE_MISMATCH", 3},
  384.     {"CM_PIP_NOT_SPECIFIED_CORRECTLY", 5},
  385.     {"CM_SECURITY_NOT_VALID", 6},
  386.     {"CM_SYNC_LVL_NOT_SUPPORTED_SYS", 7},
  387.     {"CM_SYNC_LVL_NOT_SUPPORTED_PGM", 8},
  388.     {"CM_TPN_NOT_RECOGNIZED", 9},
  389.     {"CM_SYNC_LEVEL_NOT_SUPPORTED_PGM", 8},
  390.     {"CM_TPN_NOT_RECOGNISED", 9},
  391.     {"CM_TP_NOT_AVAILABLE_NO_RETRY", 10},
  392.     {"CM_TP_NOT_AVAILABLE_RETRY", 11},
  393.     {"CM_DEALLOCATED_ABEND", 17},
  394.     {"CM_DEALLOCATED_NORMAL", 18},
  395.     {"CM_PARAMETER_ERROR", 19},
  396.     {"CM_PRODUCT_SPECIFIC_ERROR", 20},
  397.     {"CM_PROGRAM_ERROR_NO_TRUNC", 21},
  398.     {"CM_PROGRAM_ERROR_PURGING", 22},
  399.     {"CM_PROGRAM_ERROR_TRUNC", 23},
  400.     {"CM_PROGRAM_PARAMETER_CHECK ", 24},
  401.     {"CM_PROGRAM_STATE_CHECK", 25},
  402.     {"CM_RESOURCE_FAILURE_NO_RETRY", 26},
  403.     {"CM_RESOURCE_FAILURE_RETRY", 27},
  404.     {"CM_UNSUCCESSFUL", 28},
  405.     {"CM_DEALLOCATED_ABEND_SVC", 30},
  406.     {"CM_DEALLOCATED_ABEND_TIMER", 31},
  407.     {"CM_SVC_ERROR_NO_TRUNC", 32},
  408.     {"CM_SVC_ERROR_PURGING", 33},
  409.     {"CM_SVC_ERROR_TRUNC", 34},
  410.     {"CM_OPERATION_INCOMPLETE ", 35},
  411.     {"CM_SYSTEM_EVENT", 36},
  412.     {"CM_OPERATION_NOT_ACCEPTED", 37},
  413.     {"CM_CONVERSATION_ENDING", 38},
  414.     {"CM_SEND_RCV_MODE_NOT_SUPPORTED", 39},
  415.     {"CM_BUFFER_TOO_SMALL", 40},
  416.     {"CM_EXP_DATA_NOT_SUPPORTED", 41},
  417.     {"CM_DEALLOC_CONFIRM_REJECT", 42},
  418.     {"CM_ALLOCATION_ERROR", 43},
  419.     {"CM_RETRY_LIMIT_EXCEEDED", 44},
  420.     {"CM_NO_SECONDARY_INFORMATION", 45},
  421.     {"CM_SECURITY_NOT_SUPPORTED", 46},
  422.     {"CM_SECURITY_MUTUAL_FAILED", 47},
  423.     {"CM_CALL_NOT_SUPPORTED", 48},
  424.     {"CM_PARM_VALUE_NOT_SUPPORTED", 49},
  425.     {"CM_TAKE_BACKOUT", 100},
  426.     {"CM_DEALLOCATED_ABEND_BO", 130},
  427.     {"CM_DEALLOCATED_ABEND_SVC_BO", 131},
  428.     {"CM_DEALLOCATED_ABEND_TIMER_BO", 132},
  429.     {"CM_RESOURCE_FAIL_NO_RETRY_BO", 133},
  430.     {"CM_RESOURCE_FAILURE_RETRY_BO", 134},
  431.     {"CM_DEALLOCATED_NORMAL_BO", 135},
  432.     {"Invalid return code or message number", LAST_MESSAGE_NUM}
  433.     };
  434.  
  435.   int i;
  436.   for (i = 0; CPICReturnCode[i].Code < LAST_MESSAGE_NUM; i++)
  437.      if (rc == CPICReturnCode[i].Code) break;
  438.   pDoc->cmrcmsg = CPICReturnCode[i].Message;
  439. }
  440.