Changeset 13 for rxprtutl


Ignore:
Timestamp:
May 2, 2013, 3:35:06 PM (12 years ago)
Author:
Alex Taylor
Message:

Added RPUPortQuery function, improved discussion of port driver settings in 'notes'.

Location:
rxprtutl/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • rxprtutl/trunk/notes

    r3 r13  
    1 USING RPUPortSet
     1Using RPUPortQuery & RPUPortSet
     2===============================
     3
     4These functions return or accept a buffer (passed as a REXX string) which
     5contains the current port configuration data as raw bytes.  The format of
     6this data depends on the port driver which controls the particular port
     7being queried or set.
     8
     9The data formats for several common port drivers are described below.
     10
     11NOTE: All data must be in raw byte (or 'character') form.  This is the form
     12      outputted by functions like D2C() or X2C().
     13
     14      In addition, multi-byte integer values like (U)LONG and (U)SHORT must
     15      be passed in little-endian order.
     16
     17      i.e.
     18      To convert <number> to USHORT:  ushort = REVERSE( X2C( D2X( number, 4 )))
     19      To convert <number> to ULONG:   ulong  = REVERSE( X2C( D2X( number, 8 )))
     20
     21
     22SERIAL.PDR, PARALLEL.PDR
     23------------------------
    224
    325The standard serial and parallel port drivers do not support the SplPdSet API.
    426
    5 The PAR1284 port driver takes a data structure with the following format:
    627
     28PAR1284.PDR
     29-----------
     30
     31The high-speed BIDI parallel port (PAR1284) driver uses a data structure with
     32the following format (information taken from IBM DDK headers):
     33
     34typedef struct _PORTSETTINGS{
    735   ULONG   signature;           /* Must be 0x52464E49 ('INFR')               */
    836   ULONG   ulVersion;           /* Must be 0x00000001                        */
     
    74102   ULONG   ulpszDeviceID;       /* -> 1284 deviceID for printer on port  */
    75103} PORTSETTINGS, *PPORTSETTINGS;
    76 #define PAR12_SIGNATURE
    77104
     105/* Structure for setting timeouts                                        */
     106/*                                                                       */
     107/* This port driver will assume that bidi capable printers can accept    */
     108/* data at a reasonable rate, so the WriteIdle timeout will default to a */
     109/* small value(like 15 seconds). The actual WriteTimeout specified by    */
     110/* the user can be larger, and our PdWrite API will handle retrying      */
     111/* requests that do not complete.  However, we will always have a        */
     112/* ParReadThread for each bidi port, and this read will typically be     */
     113/* queued up after the write. When a write completes(even if only        */
     114/* partial buffer was sent), the queued read request will reverse the    */
     115/* channel and check for data coming from the printer.  This read must   */
     116/* not take a long time(to avoid performance degradation for writes).    */
     117/*                                                                       */
     118/* We set a small ReadInterrupt timeout( about 200 ms default ) so that  */
     119/* if no data is waiting to be read, the read request returns and lets   */
     120/* the write request be processed.                                       */
     121/*                                                                       */
     122/* We set a longer ReadIdle timeout( 1000 ms ) to attempt to get the     */
     123/* entire buffer from the peripheral if there is data waiting to be sent */
     124/* to the host.                                                          */
     125/*                                                                       */
     126/* For now, we set the WriteIdle and WriteInterrupt timeouts to be the   */
     127/* same.  This means we will always return within the WriteIdle timeout  */
     128/* value specified.                                                      */
     129/*                                                                       */
    78130typedef struct _PPTIMEOUTCHANNEL{
    79131   ULONG   ulReadIdleTimeOut;  // millisecs DD has to complete entire Read
     
    84136} PPTIMEOUTCHANNEL, *PPPTIMEOUTCHANNEL;
    85137
     138(Refer to the header file wpshell\src\wpsh\par1284\pdrtypes.h from the IBM
     139DDK for more information.)
    86140
    87141
     142CUPS.PDR
     143--------
    88144
    89 Port settings structure for CUPS.PDR:
     145The eCups port driver (CUPS.PDR) uses the following port settings structure:
    90146
    91147typedef struct _PORTSETTINGS {
     
    94150} PORTSETTINGS, *PPORTSETTINGS;
    95151
     152(At least version 1.04 of CUPS.PDR is required.)
    96153
    97154
    98 Port setting structure for SMB.PDR:
     155SMB.PDR
     156-------
    99157
    100 /* szPortData contains all of the port parameters in a single buffer:  */
    101 /*   host                                                              */
    102 /*   printer                                                           */
    103 /*   workgroup                                                         */
    104 /*   userid                                                            */
    105 /*   copies                                                            */
    106 /*   password                                                          */
    107 /* All except 'password' are verbatim character strings; 'password' is */
    108 /* a hexadecimal string.  Fields are separated by '#'.  All fields are */
    109 /* required; those with unspecified values are left empty.             */
     158The Samba port driver (SMB.PDR) takes a single 256-byte buffer.  This
     159buffer must take the following format:
    110160
    111 typedef struct _PORTSETTINGS {
    112     CHAR  szPortData[ 256 ];
    113 } PORTSETTINGS, *PPORTSETTINGS;
     161    host#printer#workgroup#userid#copies#password
     162
     163All fields are required; those whose values are unspecified must be left
     164empty.  (Replace each field name above with its corresponding value.)
     165The buffer is padded with 0 bytes to a length of 256 as needed.
     166
     167The 'password' field is a hexadecimal string; all others are standard
     168character strings.
     169
     170For example, to set the following configuration:
     171  host:      PRINTSRV
     172  printer:   LJET01
     173  workgroup: <none>
     174  userid:    mrmuffin
     175  password:  blueberry
     176  copies:    1
     177
     178In REXX:
     179  params = 'PRINTSRV#LJET01##mrmuffin#1#626C75656265727279'
     180  IF LENGTH( params <= 256 ) THEN DO
     181      buffer = params || COPIES('00'x, 256 - LENGTH( params ))
     182      CALL RPUPortSet 'SMB', buffer
     183  END
     184
  • rxprtutl/trunk/rxprtutl.c

    r12 r13  
    6060#define SZ_LIBRARY_NAME         "RXPRTUTL"  // Name of this library
    6161#define SZ_ERROR_NAME           "RPUERROR"  // REXX variable used to store error codes
    62 #define SZ_VERSION              "0.2.1"     // Current version of this library
     62#define SZ_VERSION              "0.2.2"     // Current version of this library
    6363
    6464#define APPNAME_LEAD_STR        "PM_"
     
    7373
    7474// Values that should be defined in pmsplb.h if it actually existed
     75#define TYPE_SHORT_WAIT         1
    7576#define TYPE_LONG_WAIT          2
    7677#define BIDI_SET_PORTDRV        0x19
     78#define BIDI_Q_PORTDRV          0x8019
    7779
    7880// Values used by WinOpenObject
     
    131133    "RPUPortDialog",
    132134    "RPUPortInstall",
     135    "RPUPortQuery",
    133136    "RPUPortSet",
    134137    "RPUPrinterCreate",
     
    153156RexxFunctionHandler RPUPortDialog;
    154157RexxFunctionHandler RPUPortInstall;
     158RexxFunctionHandler RPUPortQuery;
    155159RexxFunctionHandler RPUPortSet;
    156160RexxFunctionHandler RPUPrinterCreate;
     
    168172ULONG   UniqueDeviceName( PSZ pszName );
    169173BOOL    WriteCompoundVariable( PSZ pszStem, PSZ pszTail, PSZ pszValue );
     174BOOL    WriteSimpleVariable( PSZ pszName, PSZ pszValue );
    170175BOOL    WriteStemElement( PSZ pszStem, ULONG ulIndex, PSZ pszValue );
    171176void    WriteErrorCode( ULONG ulError, PSZ pszContext );
     
    523528    PSZ          pszToken;
    524529    HOBJECT      hObj;                  // printer WPS object handle
     530
     531    /* Note: SPL_PR_LOCAL_ONLY apparently doesn't prevent SplEnumPrinter from
     532     *       including remote printers, it only stops it from probing them
     533     *       to query the remote queue information in addition to the local
     534     *       queue.  Specifying it here prevents a 'stall' when the remote
     535     *       host is offline or unavailable.
     536     */
    525537    ULONG        flType     = SPL_PR_QUEUE | SPL_PR_DIRECT_DEVICE | SPL_PR_LOCAL_ONLY,
    526538                 cbBuf      = 0,
     
    620632             * of the print device(s) connected to it.
    621633             */
    622 
    623 #if 0
    624             if ( pPInfo->pszComputerName ) {
    625                 /* Network printer.  Just display the local information and
    626                  * don't try to query the remote queue.
    627                  */
    628                 sprintf( szStemNode, "%s.%u", szStem, ++ulCount );
    629                 WriteCompoundVariable( szStemNode, "!name",
    630                                        pPInfo->pszPrintDestinationName );
    631                 WriteCompoundVariable( szStemNode, "!description",
    632                                        pPInfo->pszDescription );
    633                 WriteCompoundVariable( szStemNode, "!queue",
    634                                        pPInfo->pszPrintDestinationName);
    635                 WriteCompoundVariable( szStemNode, "!flags", "");
    636                 WriteCompoundVariable( szStemNode, "!handle", "");
    637                 WriteCompoundVariable( szStemNode, "!host",
    638                                        pPInfo->pszComputerName );
    639                 continue;
    640             }
    641 #endif
    642 
    643634            rc = SplQueryQueue( pPInfo->pszComputerName,
    644635                                pPInfo->pszPrintDestinationName,
     
    787778 *      installed and registered in OS2.INI already.         (REQUIRED)      *
    788779 *   2. The name of the new port to be created.  If not specified, the port  *
    789  *      driver will be responsible for using a default name. (DEFAULT: none) *
     780 *      driver will be responsible for using a default name.  This should    *
     781 *      generally be specified, as the driver is not guaranteed to support   *
     782 *      omitting it.                                         (DEFAULT: none) *
    790783 *                                                                           *
    791784 * REXX RETURN VALUE:                                                        *
     
    857850        WriteErrorCode( rc, "SplPdInstallPort");
    858851        MAKERXSTRING( *prsResult, "0", 1 );
     852    }
     853
     854finish:
     855    DosFreeModule( hPdr );
     856cleanup:
     857    WinTerminate( hab );
     858    return ( 0 );
     859}
     860
     861
     862/* ------------------------------------------------------------------------- *
     863 * RPUPortQuery                                                              *
     864 *                                                                           *
     865 * Queries the specified port's configuration settings.  IMPORTANT: not all  *
     866 * port drivers support this; the standard OS/2 serial and parallel port     *
     867 * drivers do NOT.  When this API is not supported, the return value should  *
     868 * be ''.  Otherwise, the format of the returned configuration data is a     *
     869 * string of binary data in port driver-specific format (the caller assumes  *
     870 * responsibility for knowing how to interpret it).                          *
     871 *                                                                           *
     872 * REXX ARGUMENTS:                                                           *
     873 *   1. The name of the port driver without any extension.  This must be     *
     874 *      installed and registered in OS2.INI already.              (REQUIRED) *
     875 *   2. The name of the port to be queried.                       (REQUIRED) *
     876 *                                                                           *
     877 * REXX RETURN VALUE:                                                        *
     878 *   Binary data representing the port configuration, in whatever format is  *
     879 *   returned by the driver's SplPdQuery->BIDI_Q_PORTDRV routine.  This      *
     880 *   depends on the particular port driver; consult its API documentation.   *
     881 *   '' will be returned if an error occurred.                               *
     882 * ------------------------------------------------------------------------- */
     883ULONG APIENTRY RPUPortQuery( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
     884{
     885    HAB     hab;                        // desktop anchor-block handle
     886    HMODULE hPdr = NULLHANDLE;          // handle to port driver module
     887    PFN     pfnQueryPort;               // pointer to driver's SplPdSet entrypoint
     888    ULONG   ulCB,                       // return value from PrfQueryProfileString()
     889            cBuf;                       // size of configuration buffer
     890    PSZ     pszPdrName  = NULL,         // name of the specified port driver
     891            pszPortName = NULL;         // name of the new port to create
     892    CHAR    szPathName[ CCHMAXPATH+1 ]; // FQN of the port driver module
     893    PBYTE   pBuf;                       // Pointer to configuration buffer
     894    APIRET  rc = 0;                     // return code from Dos...() functions
     895
     896
     897    // Reset the error indicator
     898    WriteErrorCode( 0, NULL );
     899
     900    // Make sure we have exactly two valid arguments
     901    if ( argc != 2 ||
     902         !RXVALIDSTRING( argv[0] ) ||
     903         !RXVALIDSTRING( argv[1] ))
     904        return ( 40 );
     905    pszPdrName  = strupr( argv[0].strptr );
     906    pszPortName = strupr( argv[1].strptr );
     907
     908    // Get the path to the installed port driver
     909    hab = WinInitialize( 0 );
     910    if ( !hab ) {
     911        WriteErrorCode( 0, "WinInitialize");
     912        MAKERXSTRING( *prsResult, "", 0 );
     913        return ( 0 );
     914    }
     915
     916    ulCB = PrfQueryProfileString( HINI_SYSTEMPROFILE, APPNAME_PM_PORT_DRIVER,
     917                                  pszPdrName, NULL, (PVOID) szPathName, CCHMAXPATH );
     918    if ( !ulCB ) {
     919        WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileString");
     920        MAKERXSTRING( *prsResult, "", 0 );
     921        goto cleanup;
     922    }
     923
     924    // Load the port driver DLL and register its query routine
     925    rc = DosLoadModule( NULL, 0, szPathName, &hPdr );
     926    if ( rc != NO_ERROR || !hPdr ) {
     927        WriteErrorCode( rc, "DosLoadModule");
     928        MAKERXSTRING( *prsResult, "", 0 );
     929        goto cleanup;
     930    }
     931    rc = DosQueryProcAddr( hPdr, 0, "SPLPDQUERY", &pfnQueryPort );
     932    if ( rc != NO_ERROR ) {
     933        WriteErrorCode( rc, "DosQueryProcAddr");
     934        MAKERXSTRING( *prsResult, "", 0 );
     935        goto finish;
     936    }
     937
     938    // Now get the port configuration
     939    rc = pfnQueryPort( pszPortName, TYPE_SHORT_WAIT, BIDI_Q_PORTDRV, NULL, 0, NULL, &cBuf );
     940    if ( cBuf && ( rc == NO_ERROR ) ||
     941                 ( rc == ERROR_MORE_DATA ) || ( rc == NERR_BufTooSmall ))
     942    {
     943        pBuf = (PBYTE) malloc( cBuf );
     944        if ( pBuf ) {
     945            rc = pfnQueryPort( pszPortName, TYPE_SHORT_WAIT, BIDI_Q_PORTDRV, NULL, 0, pBuf, &cBuf );
     946            if ( rc == NO_ERROR ) {
     947                // Write the data contents to our return RXSTRING
     948                if ( !SaveResultString( prsResult, pBuf, cBuf ))
     949                    MAKERXSTRING( *prsResult, "", 0 );
     950            }
     951            else {
     952                WriteErrorCode( rc, "SplPdQuery 2");
     953                MAKERXSTRING( *prsResult, "", 0 );
     954            }
     955            free( pBuf );
     956        }
     957        else {
     958            WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc");
     959            MAKERXSTRING( *prsResult, "", 0 );
     960        }
     961    }
     962    else {
     963        WriteErrorCode( rc, "SplPdQuery 1");
     964        MAKERXSTRING( *prsResult, "", 0 );
    859965    }
    860966
     
    9241030         !RXVALIDSTRING( argv[2] )  )
    9251031        return ( 40 );
    926     pszPdrName  = argv[0].strptr;
     1032    pszPdrName  = strupr( argv[0].strptr );
    9271033    pszPortName = strupr( argv[1].strptr );
    9281034    pBuf        = argv[2].strptr;
     
    10141120         !RXVALIDSTRING( argv[1] )  )
    10151121        return ( 40 );
    1016     pszPdrName  = argv[0].strptr;
     1122    pszPdrName  = strupr( argv[0].strptr );
    10171123    pszPortName = strupr( argv[1].strptr );
    10181124
     
    12621368
    12631369    // Try and destroy the WPS object
     1370    //  - NB This causes a long delay when deleting an offline LAN printer
    12641371    if ( hObj != NULLHANDLE ) WinDestroyObject( hObj );
    12651372
     
    18771984
    18781985/* ------------------------------------------------------------------------- *
     1986 * WriteSimpleVariable                                                       *
     1987 *                                                                           *
     1988 * Creates a variable in the calling REXX program using the REXX shared      *
     1989 * variable pool interface.                                                  *
     1990 *                                                                           *
     1991 * ARGUMENTS:                                                                *
     1992 *   PSZ pszName  : The name of the variable to write.                       *
     1993 *   PSZ pszValue : The value to write to the variable.                      *
     1994 *                                                                           *
     1995 * RETURNS: BOOL                                                             *
     1996 * ------------------------------------------------------------------------- */
     1997BOOL WriteSimpleVariable( PSZ pszName, PSZ pszValue )
     1998{
     1999    SHVBLOCK shvVar;                   // REXX shared variable pool block
     2000    ULONG    ulRc;
     2001    CHAR     szText[ US_COMPOUND_MAXZ ];
     2002
     2003    strncpy( szText, pszValue, US_COMPOUND_MAXZ-1 );
     2004    MAKERXSTRING( shvVar.shvname,  pszName, strlen(pszName) );
     2005    MAKERXSTRING( shvVar.shvvalue, szText,  strlen(szText) );
     2006    shvVar.shvnamelen  = RXSTRLEN( shvVar.shvname );
     2007    shvVar.shvvaluelen = RXSTRLEN( shvVar.shvvalue );
     2008    shvVar.shvcode     = RXSHV_SYSET;
     2009    shvVar.shvnext     = NULL;
     2010    ulRc = RexxVariablePool( &shvVar );
     2011    if ( ulRc > 1 ) {
     2012        WriteErrorCode( shvVar.shvret, "RexxVariablePool (SHVBLOCK.shvret)");
     2013        return FALSE;
     2014    }
     2015    return TRUE;
     2016}
     2017
     2018
     2019/* ------------------------------------------------------------------------- *
    18792020 * WriteErrorCode                                                            *
    18802021 *                                                                           *
  • rxprtutl/trunk/rxprtutl.def

    r12 r13  
    11LIBRARY     RXPRTUTL INITINSTANCE TERMINSTANCE
    22DATA        MULTIPLE NONSHARED
    3 DESCRIPTION '@#Alex Taylor:0.2.1#@##1## 21 Apr 2013 18:10:57     REINFORCE::::::@@REXX Printer Management Utilities'
     3DESCRIPTION '@#Alex Taylor:0.2.2#@##1## 1 May 2013 18:18:54      REINFORCE::::::@@REXX Printer Management Utilities'
    44
    55EXPORTS     RPULoadFuncs
     
    1313RPUPortDialog
    1414RPUPortInstall
     15RPUPortQuery
    1516RPUPortSet
    1617RPUOpenView
  • rxprtutl/trunk/testlib.cmd

    r12 r13  
    1414    ELSE DO
    1515        SAY devs.0 'devices supported by' test_driver'.DRV'
    16     /*
     16/*
    1717        DO i = 1 TO devs.0
    1818            SAY ' -' devs.i
    1919        END
    20     */
     20*/
    2121    END
    2222    SAY
Note: See TracChangeset for help on using the changeset viewer.