Ignore:
Timestamp:
Apr 6, 2013, 8:45:22 PM (12 years ago)
Author:
Alex Taylor
Message:

Redesigned RPUCreatePrinter to simplify parameters; device name now generated automatically.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • rxprtutl/trunk/rxprtutl.c

    r7 r8  
    8888#define US_PRTINFO_MAXZ         180                                  // ...of a printer info string
    8989#define US_PORT_MAXZ            64                                   // ...of a port name
    90 #define US_SS_MAXZ              256                                  // ...of a default WPS setup string
     90#define US_PRTDEV_MAXZ          9                                    // ...of a print device name
    9191
    9292// List of functions to be registered by RPULoadFuncs
     
    138138HOBJECT PrinterObjectHandle( PSZ pszQueueName );
    139139BOOL    SaveResultString( PRXSTRING prsResult, PCH pchBytes, ULONG ulBytes );
     140ULONG   UniqueDeviceName( PSZ pszName );
    140141BOOL    WriteCompoundVariable( PSZ pszStem, PSZ pszTail, PSZ pszValue );
    141142BOOL    WriteStemElement( PSZ pszStem, ULONG ulIndex, PSZ pszValue );
     
    10131014 *                                                                           *
    10141015 * Creates a new local printer object.  The associated print queue and       *
    1015  * device are also created if they do not exist.  However, the associated    *
    1016  * output port must exist, and the specified printer driver/model must have  *
    1017  * been installed already.                                                   *
    1018  *                                                                           *
    1019  * The WPS object is created with default settings (other than those which   *
    1020  * are specified here).  It will be assigned an object-ID automatically.     *
    1021  *                                                                           *
    1022  * This function will not create a remote (LAN) printer object.              *
     1016 * device are created automatically.  However, the specified output port     *
     1017 * must exist, and the specified printer driver/model must have been         *
     1018 * installed already.                                                        *
     1019 *                                                                           *
     1020 * The WPS object is created with default settings, and will be assigned an  *
     1021 * object-ID automatically by the WPS.                                       *
     1022 *                                                                           *
     1023 * NOTE: This function will NOT create a remote (LAN) printer object.        *
    10231024 *                                                                           *
    10241025 * REXX ARGUMENTS:                                                           *
    1025  *   1. The name of the print queue, to be created if necessary.  (REQUIRED) *
    1026  *   2. The "physical name" of the printer device, ditto.         (REQUIRED) *
     1026 *   1. The printer description, used as the WPS object title.    (REQUIRED) *
     1027 *   2. The name of the underlying print queue. Must be a legal              *
     1028 *      queue name according to OS/2 (but what is that...?)       (REQUIRED) *
    10271029 *   3. The name of the printer port, which must exist already.   (REQUIRED) *
    10281030 *   4. The default printer driver.model to be associated with               *
    1029  *      the device.  If specified, this must be installed in the             *
    1030  *      system already.  If not specified, and the named printer             *
    1031  *      device does not already exist, IBMNULL will be assumed.   (OPTIONAL) *
    1032  *   5. The printer object title (i.e. human-readable name).  If             *
    1033  *      not specified, the physical name will be used.            (OPTIONAL) *
     1031 *      the device. If specified, this must be installed in the              *
     1032 *      system already. If not specified, IBMNULL is assumed.    (OPTIONAL)  *
    10341033 *                                                                           *
    10351034 * REXX RETURN VALUE:                                                        *
     
    10401039    PRDINFO3  devinfo       = {0};
    10411040    PRQINFO3  qinfo         = {0};
    1042     ULONG     cbBuf         = 0;
    1043     BOOL      fNewD         = FALSE;
    10441041    PSZ       pszQueueName  = NULL,
    1045               pszDeviceName = NULL,
    10461042              pszPortName   = NULL,
    10471043              pszModel      = NULL,
    10481044              pszTitle      = NULL;
     1045    CHAR      szDevice[ US_PRTDEV_MAXZ ] = {0};
    10491046    SPLERR    rc;
    10501047
     
    10541051
    10551052    // Validate the REXX arguments
    1056     if (( argc < 3 ) || ( argc > 5 )  || ( ! RXVALIDSTRING( argv[0] )) ||
     1053    if (( argc < 3 ) || ( argc > 4 )  || ( ! RXVALIDSTRING( argv[0] )) ||
    10571054        ( ! RXVALIDSTRING( argv[1] )) || ( ! RXVALIDSTRING( argv[2] )))
    10581055        return ( 40 );
    10591056    if (( argc > 3 ) && ( ! RXVALIDSTRING( argv[3] )))
    10601057        return ( 40 );
    1061     if (( argc > 4 ) && ( ! RXVALIDSTRING( argv[4] )))
    1062         return ( 40 );
    1063 
    1064     pszQueueName  = argv[0].strptr;
    1065     pszDeviceName = argv[1].strptr;
     1058
     1059    pszTitle      = argv[0].strptr;
     1060    pszQueueName  = argv[1].strptr;
    10661061    pszPortName   = argv[2].strptr;
    10671062    if ( argc > 3 ) pszModel = argv[3].strptr;
    1068     pszTitle = ( argc > 4 ) ? argv[4].strptr : pszDeviceName;
    1069 
    1070     // Find out if device exists already
    1071     rc = SplQueryDevice( NULL, pszDeviceName, 0, NULL, 0, &cbBuf );
    1072     if ( rc == NERR_DestNotFound ) {
    1073 
    1074         // Nope, create it now
    1075         devinfo.pszPrinterName = pszDeviceName;
    1076         devinfo.pszUserName    = NULL;
    1077         devinfo.pszLogAddr     = pszPortName;
    1078         devinfo.pszComment     = pszTitle;
    1079         devinfo.pszDrivers     = pszModel ? pszModel : "IBMNULL";
    1080         devinfo.usTimeOut      = 45;
    1081         rc = SplCreateDevice( NULL, 3, &devinfo, sizeof( devinfo ));
    1082         if ( rc != NO_ERROR ) {
    1083             WriteErrorCode( rc, "SplCreateDevice");
    1084             MAKERXSTRING( *prsResult, "0", 1 );
    1085             return ( 0 );
    1086         }
    1087         fNewD = TRUE;
    1088     }
    1089     else if ( rc != NO_ERROR ) {
    1090         WriteErrorCode( rc, "SplQueryDevice");
     1063
     1064    // Generate a suitable (unique) device name, based on the queue name
     1065    strncpy( szDevice, pszQueueName, US_PRTDEV_MAXZ-1 );
     1066    if (( rc = UniqueDeviceName( szDevice )) != NO_ERROR ) {
     1067        if ( rc == 1 )      // shouldn't really happen
     1068            WriteErrorCode( rc, "UniqueDeviceName");
     1069        else
     1070            WriteErrorCode( rc, "SplEnumDevice");
    10911071        MAKERXSTRING( *prsResult, "0", 1 );
    10921072        return ( 0 );
    10931073    }
    10941074
    1095     // Find out if the queue name already exists
    1096     rc = SplQueryQueue( NULL, pszQueueName, 3, NULL, 0, &cbBuf );
    1097     if ( rc == NERR_QNotFound ) {
    1098 
    1099         // Nope, create it now
    1100         qinfo.pszName       = pszQueueName;
    1101         qinfo.uPriority     = PRQ_DEF_PRIORITY;
    1102         qinfo.fsType        = PRQ3_TYPE_RAW;
    1103         qinfo.pszPrProc     = "PMPRINT";
    1104         qinfo.pszComment    = pszTitle;
    1105         qinfo.pszPrinters   = pszDeviceName;
    1106         qinfo.pszDriverName = pszModel ? pszModel : "IBMNULL";
    1107         rc = SplCreateQueue( NULL, 3, &qinfo, sizeof( qinfo ));
    1108         if ( rc != NO_ERROR ) {
    1109             WriteErrorCode( rc, "SplCreateQueue");
    1110             MAKERXSTRING( *prsResult, "0", 1 );
    1111             if ( fNewD ) SplDeleteDevice( NULL, pszDeviceName );
    1112             return ( 0 );
    1113         }
    1114     }
    1115     else if ( rc != NO_ERROR ) {
    1116         WriteErrorCode( rc, "SplQueryQueue");
    1117         MAKERXSTRING( *prsResult, "0", 1 );
    1118         if ( fNewD ) SplDeleteDevice( NULL, pszDeviceName );
     1075    // Create the device
     1076    devinfo.pszPrinterName = szDevice;
     1077    devinfo.pszUserName    = NULL;
     1078    devinfo.pszLogAddr     = pszPortName;
     1079    devinfo.pszComment     = pszTitle;
     1080    devinfo.pszDrivers     = pszModel ? pszModel : "IBMNULL";
     1081    devinfo.usTimeOut      = 45;
     1082    rc = SplCreateDevice( NULL, 3, &devinfo, sizeof( devinfo ));
     1083    if ( rc != NO_ERROR ) {
     1084        WriteErrorCode( rc, "SplCreateDevice");
     1085        MAKERXSTRING( *prsResult, "0", 1 );
     1086        return ( 0 );
     1087    }
     1088
     1089    // Create the queue (automatically creates printer object)
     1090    qinfo.pszName       = pszQueueName;
     1091    qinfo.uPriority     = PRQ_DEF_PRIORITY;
     1092    qinfo.fsType        = PRQ3_TYPE_RAW;
     1093    qinfo.pszPrProc     = "PMPRINT";
     1094    qinfo.pszComment    = pszTitle;
     1095    qinfo.pszPrinters   = szDevice;
     1096    qinfo.pszDriverName = pszModel ? pszModel : "IBMNULL";
     1097    rc = SplCreateQueue( NULL, 3, &qinfo, sizeof( qinfo ));
     1098    if ( rc != NO_ERROR ) {
     1099        WriteErrorCode( rc, "SplCreateQueue");
     1100        MAKERXSTRING( *prsResult, "0", 1 );
     1101        SplDeleteDevice( NULL, szDevice );
    11191102        return ( 0 );
    11201103    }
     
    15071490
    15081491
     1492/* ------------------------------------------------------------------------- *
     1493 * UniqueDeviceName                                                          *
     1494 *                                                                           *
     1495 * Check (and, if necessary, modify) the specified print device name to make *
     1496 * sure it is unique.                                                        *
     1497 *                                                                           *
     1498 * ARGUMENTS:                                                                *
     1499 *   PSZ pszName : Pointer to device name buffer (9-byte CHAR buffer)        *
     1500 *                                                                           *
     1501 * RETURNS: ULONG                                                            *
     1502 *   0 on success, 1 if no unique name could be generated, or the return     *
     1503 *   code from SplEnumDevice() if an error occurred.                         *
     1504 * ------------------------------------------------------------------------- */
     1505ULONG UniqueDeviceName( PSZ pszName )
     1506{
     1507    PBYTE     pBuf;
     1508    PPRDINFO3 pprd3;
     1509    CHAR      szNumber[ US_PRTDEV_MAXZ ] = {0};
     1510    ULONG     i, n, pos,
     1511              ulNumber  = 0,
     1512              ulAvail   = 0,
     1513              cbBuf     = 0;
     1514    BOOL      fUnique   = FALSE;
     1515    SPLERR    rc;
     1516
     1517
     1518    rc = SplEnumDevice( NULL, 3, NULL, 0, &ulNumber, &ulAvail, &cbBuf, NULL );
     1519    if ( rc == ERROR_MORE_DATA || rc == NERR_BufTooSmall ) {
     1520        pBuf = malloc( cbBuf );
     1521        if ( pBuf ) {
     1522            rc = SplEnumDevice( NULL, 3, pBuf, cbBuf, &ulNumber, &ulAvail, &cbBuf, NULL );
     1523            if ( rc == NO_ERROR ) {
     1524                n = 1;
     1525                while ( !fUnique && ( n < 999 )) {     // max 999 as a sanity check
     1526                    for ( i = 0; i < ulNumber; i++ )  {
     1527                        pprd3 = (PPRDINFO3) pBuf + i;
     1528                        if ( stricmp( pszName, pprd3->pszPrinterName ) == 0 ) break;
     1529                    }
     1530                    if ( i >= ulNumber ) fUnique = TRUE;
     1531                    else {
     1532                        sprintf( szNumber, "%u", n++ );
     1533                        pos = strlen( pszName ) - strlen( szNumber );
     1534                        pszName[ pos ] = '\0';
     1535                        strncat( pszName, szNumber, US_PRTDEV_MAXZ-1 );
     1536                    }
     1537                }
     1538            }
     1539            free( pBuf );
     1540        }
     1541    }
     1542    if ( rc == NO_ERROR && !fUnique ) return 1;
     1543    else return rc;
     1544}
     1545
     1546
    15091547/* ************************************************************************* *
    15101548 * INTERNAL REXX DLL UTILITY FUNCTIONS                                       *
Note: See TracChangeset for help on using the changeset viewer.