- Timestamp:
- May 2, 2013, 3:35:06 PM (12 years ago)
- Location:
- rxprtutl/trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
rxprtutl/trunk/notes
r3 r13 1 USING RPUPortSet 1 Using RPUPortQuery & RPUPortSet 2 =============================== 3 4 These functions return or accept a buffer (passed as a REXX string) which 5 contains the current port configuration data as raw bytes. The format of 6 this data depends on the port driver which controls the particular port 7 being queried or set. 8 9 The data formats for several common port drivers are described below. 10 11 NOTE: 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 22 SERIAL.PDR, PARALLEL.PDR 23 ------------------------ 2 24 3 25 The standard serial and parallel port drivers do not support the SplPdSet API. 4 26 5 The PAR1284 port driver takes a data structure with the following format:6 27 28 PAR1284.PDR 29 ----------- 30 31 The high-speed BIDI parallel port (PAR1284) driver uses a data structure with 32 the following format (information taken from IBM DDK headers): 33 34 typedef struct _PORTSETTINGS{ 7 35 ULONG signature; /* Must be 0x52464E49 ('INFR') */ 8 36 ULONG ulVersion; /* Must be 0x00000001 */ … … 74 102 ULONG ulpszDeviceID; /* -> 1284 deviceID for printer on port */ 75 103 } PORTSETTINGS, *PPORTSETTINGS; 76 #define PAR12_SIGNATURE77 104 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 /* */ 78 130 typedef struct _PPTIMEOUTCHANNEL{ 79 131 ULONG ulReadIdleTimeOut; // millisecs DD has to complete entire Read … … 84 136 } PPTIMEOUTCHANNEL, *PPPTIMEOUTCHANNEL; 85 137 138 (Refer to the header file wpshell\src\wpsh\par1284\pdrtypes.h from the IBM 139 DDK for more information.) 86 140 87 141 142 CUPS.PDR 143 -------- 88 144 89 Port settings structure for CUPS.PDR:145 The eCups port driver (CUPS.PDR) uses the following port settings structure: 90 146 91 147 typedef struct _PORTSETTINGS { … … 94 150 } PORTSETTINGS, *PPORTSETTINGS; 95 151 152 (At least version 1.04 of CUPS.PDR is required.) 96 153 97 154 98 Port setting structure for SMB.PDR: 155 SMB.PDR 156 ------- 99 157 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. */ 158 The Samba port driver (SMB.PDR) takes a single 256-byte buffer. This 159 buffer must take the following format: 110 160 111 typedef struct _PORTSETTINGS { 112 CHAR szPortData[ 256 ]; 113 } PORTSETTINGS, *PPORTSETTINGS; 161 host#printer#workgroup#userid#copies#password 162 163 All fields are required; those whose values are unspecified must be left 164 empty. (Replace each field name above with its corresponding value.) 165 The buffer is padded with 0 bytes to a length of 256 as needed. 166 167 The 'password' field is a hexadecimal string; all others are standard 168 character strings. 169 170 For 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 178 In 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 60 60 #define SZ_LIBRARY_NAME "RXPRTUTL" // Name of this library 61 61 #define SZ_ERROR_NAME "RPUERROR" // REXX variable used to store error codes 62 #define SZ_VERSION "0.2. 1" // Current version of this library62 #define SZ_VERSION "0.2.2" // Current version of this library 63 63 64 64 #define APPNAME_LEAD_STR "PM_" … … 73 73 74 74 // Values that should be defined in pmsplb.h if it actually existed 75 #define TYPE_SHORT_WAIT 1 75 76 #define TYPE_LONG_WAIT 2 76 77 #define BIDI_SET_PORTDRV 0x19 78 #define BIDI_Q_PORTDRV 0x8019 77 79 78 80 // Values used by WinOpenObject … … 131 133 "RPUPortDialog", 132 134 "RPUPortInstall", 135 "RPUPortQuery", 133 136 "RPUPortSet", 134 137 "RPUPrinterCreate", … … 153 156 RexxFunctionHandler RPUPortDialog; 154 157 RexxFunctionHandler RPUPortInstall; 158 RexxFunctionHandler RPUPortQuery; 155 159 RexxFunctionHandler RPUPortSet; 156 160 RexxFunctionHandler RPUPrinterCreate; … … 168 172 ULONG UniqueDeviceName( PSZ pszName ); 169 173 BOOL WriteCompoundVariable( PSZ pszStem, PSZ pszTail, PSZ pszValue ); 174 BOOL WriteSimpleVariable( PSZ pszName, PSZ pszValue ); 170 175 BOOL WriteStemElement( PSZ pszStem, ULONG ulIndex, PSZ pszValue ); 171 176 void WriteErrorCode( ULONG ulError, PSZ pszContext ); … … 523 528 PSZ pszToken; 524 529 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 */ 525 537 ULONG flType = SPL_PR_QUEUE | SPL_PR_DIRECT_DEVICE | SPL_PR_LOCAL_ONLY, 526 538 cbBuf = 0, … … 620 632 * of the print device(s) connected to it. 621 633 */ 622 623 #if 0624 if ( pPInfo->pszComputerName ) {625 /* Network printer. Just display the local information and626 * 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 #endif642 643 634 rc = SplQueryQueue( pPInfo->pszComputerName, 644 635 pPInfo->pszPrintDestinationName, … … 787 778 * installed and registered in OS2.INI already. (REQUIRED) * 788 779 * 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) * 790 783 * * 791 784 * REXX RETURN VALUE: * … … 857 850 WriteErrorCode( rc, "SplPdInstallPort"); 858 851 MAKERXSTRING( *prsResult, "0", 1 ); 852 } 853 854 finish: 855 DosFreeModule( hPdr ); 856 cleanup: 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 * ------------------------------------------------------------------------- */ 883 ULONG 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 ); 859 965 } 860 966 … … 924 1030 !RXVALIDSTRING( argv[2] ) ) 925 1031 return ( 40 ); 926 pszPdrName = argv[0].strptr;1032 pszPdrName = strupr( argv[0].strptr ); 927 1033 pszPortName = strupr( argv[1].strptr ); 928 1034 pBuf = argv[2].strptr; … … 1014 1120 !RXVALIDSTRING( argv[1] ) ) 1015 1121 return ( 40 ); 1016 pszPdrName = argv[0].strptr;1122 pszPdrName = strupr( argv[0].strptr ); 1017 1123 pszPortName = strupr( argv[1].strptr ); 1018 1124 … … 1262 1368 1263 1369 // Try and destroy the WPS object 1370 // - NB This causes a long delay when deleting an offline LAN printer 1264 1371 if ( hObj != NULLHANDLE ) WinDestroyObject( hObj ); 1265 1372 … … 1877 1984 1878 1985 /* ------------------------------------------------------------------------- * 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 * ------------------------------------------------------------------------- */ 1997 BOOL 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 /* ------------------------------------------------------------------------- * 1879 2020 * WriteErrorCode * 1880 2021 * * -
rxprtutl/trunk/rxprtutl.def
r12 r13 1 1 LIBRARY RXPRTUTL INITINSTANCE TERMINSTANCE 2 2 DATA MULTIPLE NONSHARED 3 DESCRIPTION '@#Alex Taylor:0.2. 1#@##1## 21 Apr 2013 18:10:57REINFORCE::::::@@REXX Printer Management Utilities'3 DESCRIPTION '@#Alex Taylor:0.2.2#@##1## 1 May 2013 18:18:54 REINFORCE::::::@@REXX Printer Management Utilities' 4 4 5 5 EXPORTS RPULoadFuncs … … 13 13 RPUPortDialog 14 14 RPUPortInstall 15 RPUPortQuery 15 16 RPUPortSet 16 17 RPUOpenView -
rxprtutl/trunk/testlib.cmd
r12 r13 14 14 ELSE DO 15 15 SAY devs.0 'devices supported by' test_driver'.DRV' 16 16 /* 17 17 DO i = 1 TO devs.0 18 18 SAY ' -' devs.i 19 19 END 20 20 */ 21 21 END 22 22 SAY
Note:
See TracChangeset
for help on using the changeset viewer.