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'.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified 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 *                                                                           *
Note: See TracChangeset for help on using the changeset viewer.