| [3] | 1 | /****************************************************************************** | 
|---|
|  | 2 | * REXX OS/2 Printer Utility API (RXPRTUTL.DLL)                               * | 
|---|
| [37] | 3 | * (C) 2011,2016 Alex Taylor                                                  * | 
|---|
| [3] | 4 | *                                                                            * | 
|---|
|  | 5 | * LICENSE:                                                                   * | 
|---|
|  | 6 | *                                                                            * | 
|---|
|  | 7 | *   Redistribution and use in source and binary forms, with or without       * | 
|---|
|  | 8 | *   modification, are permitted provided that the following conditions are   * | 
|---|
|  | 9 | *   met:                                                                     * | 
|---|
|  | 10 | *                                                                            * | 
|---|
|  | 11 | *   1. Redistributions of source code must retain the above copyright        * | 
|---|
|  | 12 | *      notice, this list of conditions and the following disclaimer.         * | 
|---|
|  | 13 | *                                                                            * | 
|---|
|  | 14 | *   2. Redistributions in binary form must reproduce the above copyright     * | 
|---|
|  | 15 | *      notice, this list of conditions and the following disclaimer in the   * | 
|---|
|  | 16 | *      documentation and/or other materials provided with the distribution.  * | 
|---|
|  | 17 | *                                                                            * | 
|---|
|  | 18 | *   3. The name of the author may not be used to endorse or promote products * | 
|---|
|  | 19 | *      derived from this software without specific prior written permission. * | 
|---|
|  | 20 | *                                                                            * | 
|---|
|  | 21 | *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR     * | 
|---|
|  | 22 | *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED           * | 
|---|
|  | 23 | *   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE   * | 
|---|
|  | 24 | *   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,       * | 
|---|
|  | 25 | *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES       * | 
|---|
|  | 26 | *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR       * | 
|---|
|  | 27 | *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)       * | 
|---|
|  | 28 | *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,      * | 
|---|
|  | 29 | *   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * | 
|---|
|  | 30 | *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          * | 
|---|
|  | 31 | *   POSSIBILITY OF SUCH DAMAGE.                                              * | 
|---|
|  | 32 | *                                                                            * | 
|---|
|  | 33 | ******************************************************************************/ | 
|---|
|  | 34 |  | 
|---|
|  | 35 | #define INCL_DEV | 
|---|
|  | 36 | #define INCL_DOSERRORS | 
|---|
|  | 37 | #define INCL_DOSMISC | 
|---|
|  | 38 | #define INCL_DOSMODULEMGR | 
|---|
|  | 39 | #define INCL_DOSPROFILE | 
|---|
|  | 40 | #define INCL_SPL | 
|---|
|  | 41 | #define INCL_SPLDOSPRINT | 
|---|
|  | 42 | #define INCL_SPLERRORS | 
|---|
|  | 43 | #define INCL_PM | 
|---|
|  | 44 | #define INCL_WIN | 
|---|
|  | 45 | #define INCL_WINWORKPLACE | 
|---|
|  | 46 | #ifndef OS2_INCLUDED | 
|---|
|  | 47 | #include <os2.h> | 
|---|
|  | 48 | #endif | 
|---|
|  | 49 | #include <ctype.h> | 
|---|
|  | 50 | #include <stdio.h> | 
|---|
|  | 51 | #include <stdlib.h> | 
|---|
|  | 52 | #include <string.h> | 
|---|
|  | 53 | #define INCL_RXSHV | 
|---|
|  | 54 | #define INCL_RXFUNC | 
|---|
|  | 55 | #include <rexxsaa.h> | 
|---|
|  | 56 |  | 
|---|
| [32] | 57 | #include "shfuncs.h" | 
|---|
| [3] | 58 |  | 
|---|
| [32] | 59 |  | 
|---|
| [3] | 60 | // CONSTANTS | 
|---|
|  | 61 |  | 
|---|
|  | 62 | #define SZ_LIBRARY_NAME         "RXPRTUTL"  // Name of this library | 
|---|
| [38] | 63 | #define SZ_VERSION              "0.3"       // Current version of this library | 
|---|
| [3] | 64 |  | 
|---|
| [37] | 65 | //This is now defined by the Makefile: | 
|---|
|  | 66 | //#define SZ_ERROR_NAME           "RPUERROR"  // REXX variable used to store error codes | 
|---|
|  | 67 |  | 
|---|
| [3] | 68 | #define APPNAME_LEAD_STR        "PM_" | 
|---|
|  | 69 | #define APPNAME_PM_PORT_DRIVER  "PM_PORT_DRIVER" | 
|---|
|  | 70 | #define APPNAME_PM_SPOOLER_PORT "PM_SPOOLER_PORT" | 
|---|
|  | 71 | #define APPNAME_PM_PRINT_OBJECT "PM_PrintObject" | 
|---|
| [11] | 72 | #define APPNAME_PM_ABS_OBJECTS  "PM_Abstract:Objects" | 
|---|
| [3] | 73 | #define APPNAME_PM_WPS_LOCATION "PM_Workplace:Location" | 
|---|
|  | 74 |  | 
|---|
| [11] | 75 | #define ID_OBJINFO_QUEUENAME    3 | 
|---|
|  | 76 | #define ID_OBJINFO_RPQUEUENAME  13 | 
|---|
|  | 77 |  | 
|---|
| [3] | 78 | // Values that should be defined in pmsplb.h if it actually existed | 
|---|
| [13] | 79 | #define TYPE_SHORT_WAIT         1 | 
|---|
| [3] | 80 | #define TYPE_LONG_WAIT          2 | 
|---|
|  | 81 | #define BIDI_SET_PORTDRV        0x19 | 
|---|
| [13] | 82 | #define BIDI_Q_PORTDRV          0x8019 | 
|---|
| [3] | 83 |  | 
|---|
|  | 84 | // Values used by WinOpenObject | 
|---|
|  | 85 | #define OPEN_DEFAULT       0 | 
|---|
|  | 86 | #define OPEN_CONTENTS      1 | 
|---|
|  | 87 | #define OPEN_SETTINGS      2 | 
|---|
|  | 88 | #define OPEN_HELP          3 | 
|---|
|  | 89 | #define OPEN_TREE          101 | 
|---|
|  | 90 | #define OPEN_DETAILS       102 | 
|---|
|  | 91 |  | 
|---|
|  | 92 | // Maximum string lengths... | 
|---|
| [32] | 93 | #ifdef NO_SHARED_SOURCE | 
|---|
|  | 94 | #define US_COMPOUND_MAXZ    250                                  // ...of a compound variable | 
|---|
|  | 95 | #define US_ERRSTR_MAXZ      250                                  // ...of an error string | 
|---|
|  | 96 | #endif | 
|---|
|  | 97 |  | 
|---|
| [3] | 98 | #define US_INTEGER_MAXZ         12                                   // ...of an integer string | 
|---|
|  | 99 | #define US_STEM_MAXZ          ( US_COMPOUND_MAXZ - US_INTEGER_MAXZ ) // ...of a stem | 
|---|
|  | 100 | #define US_DRVINFO_MAXZ       ( CCHMAXPATH + 8 + 32 )                // ...of an driver/port info string | 
|---|
|  | 101 | #define US_PRTINFO_MAXZ         180                                  // ...of a printer info string | 
|---|
|  | 102 | #define US_PORT_MAXZ            64                                   // ...of a port name | 
|---|
| [8] | 103 | #define US_PRTDEV_MAXZ          9                                    // ...of a print device name | 
|---|
| [3] | 104 |  | 
|---|
| [11] | 105 |  | 
|---|
|  | 106 | // DATA TYPES | 
|---|
|  | 107 |  | 
|---|
|  | 108 | /* Structures needed used to parse PM_Abstract:Object data | 
|---|
|  | 109 | */ | 
|---|
|  | 110 | #pragma pack(1) | 
|---|
|  | 111 | typedef struct _Object_Info | 
|---|
|  | 112 | { | 
|---|
|  | 113 | USHORT cbName;       // Size of szName, including terminator | 
|---|
|  | 114 | USHORT cbData;       // Number of additional data bytes following szName | 
|---|
|  | 115 | CHAR   szName[1];    // Name of object type | 
|---|
|  | 116 | } OBJINFO, *POBJINFO; | 
|---|
|  | 117 |  | 
|---|
|  | 118 | typedef struct _Object_Tag_Info | 
|---|
|  | 119 | { | 
|---|
|  | 120 | USHORT usTagFormat;  // Tag data format | 
|---|
|  | 121 | USHORT usTag;        // Tag ID | 
|---|
|  | 122 | USHORT cbTag;        // Size of tag data | 
|---|
|  | 123 | } OITAG, *POITAG; | 
|---|
|  | 124 | #pragma pack() | 
|---|
|  | 125 |  | 
|---|
|  | 126 |  | 
|---|
|  | 127 | // GLOBALS | 
|---|
|  | 128 |  | 
|---|
| [3] | 129 | // List of functions to be registered by RPULoadFuncs | 
|---|
|  | 130 | static PSZ RxFunctionTbl[] = { | 
|---|
| [32] | 131 | "RPULoadFuncs",         // drop only | 
|---|
| [3] | 132 | "RPUDropFuncs", | 
|---|
| [15] | 133 | "RPUDeviceDelete", | 
|---|
| [5] | 134 | "RPUEnumModels", | 
|---|
| [3] | 135 | "RPUEnumDrivers", | 
|---|
|  | 136 | "RPUEnumPorts", | 
|---|
|  | 137 | "RPUEnumPrinters", | 
|---|
| [5] | 138 | "RPUQueueDefault", | 
|---|
|  | 139 | "RPUQueueHold", | 
|---|
|  | 140 | "RPUOpenView", | 
|---|
| [10] | 141 | "RPUPortDelete", | 
|---|
| [3] | 142 | "RPUPortDialog", | 
|---|
| [14] | 143 | "RPUPortInfo", | 
|---|
| [3] | 144 | "RPUPortInstall", | 
|---|
| [13] | 145 | "RPUPortQuery", | 
|---|
| [3] | 146 | "RPUPortSet", | 
|---|
| [5] | 147 | "RPUPrinterCreate", | 
|---|
| [7] | 148 | "RPUPrinterDelete", | 
|---|
| [3] | 149 | "RPUPrinterQuery", | 
|---|
|  | 150 | "RPUVersion" | 
|---|
|  | 151 | }; | 
|---|
|  | 152 |  | 
|---|
|  | 153 |  | 
|---|
|  | 154 | // FUNCTION DECLARATIONS | 
|---|
|  | 155 |  | 
|---|
|  | 156 | // Exported REXX functions | 
|---|
|  | 157 | RexxFunctionHandler RPULoadFuncs; | 
|---|
|  | 158 | RexxFunctionHandler RPUDropFuncs; | 
|---|
|  | 159 | RexxFunctionHandler RPUVersion; | 
|---|
| [15] | 160 | RexxFunctionHandler RPUDeviceDelete; | 
|---|
| [5] | 161 | RexxFunctionHandler RPUEnumModels; | 
|---|
| [3] | 162 | RexxFunctionHandler RPUEnumDrivers; | 
|---|
|  | 163 | RexxFunctionHandler RPUEnumPorts; | 
|---|
|  | 164 | RexxFunctionHandler RPUEnumPrinters; | 
|---|
| [5] | 165 | RexxFunctionHandler RPUOpenView; | 
|---|
| [10] | 166 | RexxFunctionHandler RPUPortDelete; | 
|---|
| [3] | 167 | RexxFunctionHandler RPUPortDialog; | 
|---|
| [14] | 168 | RexxFunctionHandler RPUPortInfo; | 
|---|
| [3] | 169 | RexxFunctionHandler RPUPortInstall; | 
|---|
| [13] | 170 | RexxFunctionHandler RPUPortQuery; | 
|---|
| [3] | 171 | RexxFunctionHandler RPUPortSet; | 
|---|
| [5] | 172 | RexxFunctionHandler RPUPrinterCreate; | 
|---|
| [7] | 173 | RexxFunctionHandler RPUPrinterDelete; | 
|---|
| [3] | 174 | RexxFunctionHandler RPUPrinterQuery; | 
|---|
| [5] | 175 | RexxFunctionHandler RPUQueueDefault; | 
|---|
|  | 176 | RexxFunctionHandler RPUQueueHold; | 
|---|
| [3] | 177 |  | 
|---|
|  | 178 | // TODO | 
|---|
|  | 179 |  | 
|---|
|  | 180 | // Internal functions | 
|---|
|  | 181 | PSZ     GetObjectID( PSZ pszHandle ); | 
|---|
|  | 182 | HOBJECT PrinterObjectHandle( PSZ pszQueueName ); | 
|---|
| [8] | 183 | ULONG   UniqueDeviceName( PSZ pszName ); | 
|---|
| [32] | 184 | #ifdef NO_SHARED_SOURCE | 
|---|
|  | 185 | BOOL    SaveResultString( PRXSTRING prsResult, PCH pchBytes, ULONG ulBytes ); | 
|---|
|  | 186 | BOOL    WriteCompoundVariable( PSZ pszStem, PSZ pszTail, PSZ pszValue ); | 
|---|
|  | 187 | //    BOOL    WriteSimpleVariable( PSZ pszName, PSZ pszValue ); | 
|---|
|  | 188 | BOOL    WriteStemElement( PSZ pszStem, ULONG ulIndex, PSZ pszValue ); | 
|---|
|  | 189 | void    WriteErrorCode( ULONG ulError, PSZ pszContext ); | 
|---|
|  | 190 | #endif | 
|---|
| [3] | 191 |  | 
|---|
|  | 192 |  | 
|---|
|  | 193 | /* ************************************************************************* * | 
|---|
|  | 194 | * EXPORTED REXX FUNCTIONS                                                   * | 
|---|
|  | 195 | * ************************************************************************* */ | 
|---|
|  | 196 |  | 
|---|
|  | 197 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 198 | * RPULoadFuncs                                                              * | 
|---|
|  | 199 | *                                                                           * | 
|---|
|  | 200 | * Register all RPU* REXX functions except this one.                         * | 
|---|
|  | 201 | *                                                                           * | 
|---|
|  | 202 | * REXX ARGUMENTS:    None                                                   * | 
|---|
|  | 203 | * REXX RETURN VALUE: ""                                                     * | 
|---|
|  | 204 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 205 | ULONG APIENTRY RPULoadFuncs( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 206 | { | 
|---|
|  | 207 | int entries, | 
|---|
|  | 208 | i; | 
|---|
|  | 209 |  | 
|---|
|  | 210 | // Reset the error indicator | 
|---|
|  | 211 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 212 |  | 
|---|
|  | 213 | if ( argc > 0 ) return ( 40 ); | 
|---|
|  | 214 | entries = sizeof(RxFunctionTbl) / sizeof(PSZ); | 
|---|
| [32] | 215 |  | 
|---|
|  | 216 | // Start from 1 to skip RPULoadFuncs (we don't want to re-register ourselves) | 
|---|
|  | 217 | for ( i = 1; i < entries; i++ ) | 
|---|
| [3] | 218 | RexxRegisterFunctionDll( RxFunctionTbl[i], SZ_LIBRARY_NAME, RxFunctionTbl[i] ); | 
|---|
|  | 219 |  | 
|---|
| [32] | 220 | SaveResultString( prsResult, NULL, 0 ); | 
|---|
| [3] | 221 | return ( 0 ); | 
|---|
|  | 222 | } | 
|---|
|  | 223 |  | 
|---|
|  | 224 |  | 
|---|
|  | 225 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 226 | * RPUDropFuncs                                                              * | 
|---|
|  | 227 | *                                                                           * | 
|---|
|  | 228 | * Deregister all RPU* REXX functions, including this one.                   * | 
|---|
|  | 229 | *                                                                           * | 
|---|
|  | 230 | * REXX ARGUMENTS:    None                                                   * | 
|---|
|  | 231 | * REXX RETURN VALUE: ""                                                     * | 
|---|
|  | 232 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 233 | ULONG APIENTRY RPUDropFuncs( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 234 | { | 
|---|
|  | 235 | int entries, | 
|---|
|  | 236 | i; | 
|---|
|  | 237 |  | 
|---|
|  | 238 | // Reset the error indicator | 
|---|
|  | 239 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 240 |  | 
|---|
|  | 241 | if ( argc > 0 ) return ( 40 ); | 
|---|
|  | 242 | entries = sizeof(RxFunctionTbl) / sizeof(PSZ); | 
|---|
|  | 243 | for ( i = 0; i < entries; i++ ) | 
|---|
|  | 244 | RexxDeregisterFunction( RxFunctionTbl[i] ); | 
|---|
|  | 245 |  | 
|---|
| [32] | 246 | SaveResultString( prsResult, NULL, 0 ); | 
|---|
| [3] | 247 | return ( 0 ); | 
|---|
|  | 248 | } | 
|---|
|  | 249 |  | 
|---|
|  | 250 |  | 
|---|
|  | 251 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 252 | * RPUVersion                                                               * | 
|---|
|  | 253 | *                                                                           * | 
|---|
|  | 254 | * Returns the current library version.                                      * | 
|---|
|  | 255 | *                                                                           * | 
|---|
|  | 256 | * REXX ARGUMENTS:    None                                                   * | 
|---|
|  | 257 | * REXX RETURN VALUE: Current version in the form "major.minor.refresh"      * | 
|---|
|  | 258 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 259 | ULONG APIENTRY RPUVersion( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 260 | { | 
|---|
|  | 261 | CHAR szVersion[ 12 ]; | 
|---|
|  | 262 |  | 
|---|
|  | 263 | // Reset the error indicator | 
|---|
|  | 264 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 265 |  | 
|---|
|  | 266 | if ( argc > 0 ) return ( 40 ); | 
|---|
|  | 267 | sprintf( szVersion, "%s", SZ_VERSION ); | 
|---|
|  | 268 |  | 
|---|
| [32] | 269 | SaveResultString( prsResult, szVersion, strlen(szVersion) ); | 
|---|
| [3] | 270 | return ( 0 ); | 
|---|
|  | 271 | } | 
|---|
|  | 272 |  | 
|---|
|  | 273 |  | 
|---|
|  | 274 | /* ------------------------------------------------------------------------- * | 
|---|
| [15] | 275 | * RPUDeviceDelete                                                           * | 
|---|
|  | 276 | *                                                                           * | 
|---|
|  | 277 | * Deletes a local print device which lacks a printer queue.  Can be useful  * | 
|---|
|  | 278 | * for cleaning up bad or corrupted printer definitions.                     * | 
|---|
|  | 279 | *                                                                           * | 
|---|
|  | 280 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 281 | *   1. The name of the print device to be deleted.               (REQUIRED) * | 
|---|
|  | 282 | *                                                                           * | 
|---|
|  | 283 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 284 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 285 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 286 | ULONG APIENTRY RPUDeviceDelete( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 287 | { | 
|---|
|  | 288 | PSZ    pszDeviceName = NULL; | 
|---|
|  | 289 | SPLERR rc; | 
|---|
|  | 290 |  | 
|---|
|  | 291 |  | 
|---|
|  | 292 | // Reset the error indicator | 
|---|
|  | 293 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 294 |  | 
|---|
|  | 295 | // Validate the REXX arguments | 
|---|
|  | 296 | if (( argc != 1 ) || ( ! RXVALIDSTRING( argv[0] ))) | 
|---|
|  | 297 | return ( 40 ); | 
|---|
|  | 298 |  | 
|---|
|  | 299 | pszDeviceName = argv[0].strptr; | 
|---|
|  | 300 |  | 
|---|
|  | 301 | rc = SplDeleteDevice( NULL, pszDeviceName ); | 
|---|
|  | 302 | if ( rc != NO_ERROR ) { | 
|---|
|  | 303 | WriteErrorCode( rc, "SplDeleteDevice"); | 
|---|
| [32] | 304 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [15] | 305 | return 0; | 
|---|
|  | 306 | } | 
|---|
|  | 307 |  | 
|---|
| [32] | 308 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [15] | 309 | return ( 0 ); | 
|---|
|  | 310 | } | 
|---|
|  | 311 |  | 
|---|
|  | 312 |  | 
|---|
|  | 313 | /* ------------------------------------------------------------------------- * | 
|---|
| [5] | 314 | * RPUEnumModels                                                             * | 
|---|
| [3] | 315 | *                                                                           * | 
|---|
| [5] | 316 | * Gets a list of the printer models supported by the specified print        * | 
|---|
|  | 317 | * driver.                                                                   * | 
|---|
| [3] | 318 | *                                                                           * | 
|---|
|  | 319 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 320 | *   1. Filespec of the printer driver to query.                  (REQUIRED) * | 
|---|
|  | 321 | *   2. The name of the stem in which to return the results.      (REQUIRED) * | 
|---|
|  | 322 | *                                                                           * | 
|---|
|  | 323 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 324 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 325 | * ------------------------------------------------------------------------- */ | 
|---|
| [5] | 326 | ULONG APIENTRY RPUEnumModels( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
| [3] | 327 | { | 
|---|
|  | 328 | HAB    hab;                         // desktop anchor-block handle | 
|---|
|  | 329 | PSZ    pszDriver;                   // print driver filespec | 
|---|
|  | 330 | CHAR   szStem[ US_STEM_MAXZ ],      // buffers used for building stem | 
|---|
|  | 331 | szNumber[ US_INTEGER_MAXZ ]; // ... | 
|---|
|  | 332 | BOOL   fSuccess;                    // success indicator | 
|---|
|  | 333 | PSTR32 aDeviceName;                 // array of device names | 
|---|
|  | 334 | PSTR64 aDeviceDesc;                 // array of device descriptions | 
|---|
|  | 335 | PSTR16 aDataType;                   // array of data types | 
|---|
|  | 336 | LONG   pldn = 0L,                   // number of device names/descriptions | 
|---|
|  | 337 | pldt = 0L,                   // number of data types | 
|---|
|  | 338 | i; | 
|---|
| [15] | 339 | APIRET rc = 0; | 
|---|
| [3] | 340 |  | 
|---|
|  | 341 | // Reset the error indicator | 
|---|
|  | 342 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 343 |  | 
|---|
|  | 344 | // Make sure we have exactly two valid arguments | 
|---|
|  | 345 | if (( argc != 2 ) || | 
|---|
|  | 346 | ( ! RXVALIDSTRING( argv[0] )) || | 
|---|
|  | 347 | ( ! RXVALIDSTRING( argv[1] )) || | 
|---|
|  | 348 | ( RXSTRLEN( argv[1] ) > US_STEM_MAXZ )) | 
|---|
|  | 349 | return ( 40 ); | 
|---|
|  | 350 | pszDriver = argv[0].strptr; | 
|---|
|  | 351 |  | 
|---|
|  | 352 | if ( argv[1].strptr[ argv[1].strlength-1 ] == '.') argv[1].strlength--; | 
|---|
|  | 353 | strncpy( szStem, argv[1].strptr, RXSTRLEN( argv[1] )); | 
|---|
|  | 354 | szStem[ RXSTRLEN( argv[1] ) ] = '\0'; | 
|---|
|  | 355 |  | 
|---|
|  | 356 | hab = WinInitialize( 0 ); | 
|---|
|  | 357 | if ( !hab ) { | 
|---|
|  | 358 | WriteErrorCode( 0, "WinInitialize"); | 
|---|
| [32] | 359 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 360 | return ( 0 ); | 
|---|
|  | 361 | } | 
|---|
|  | 362 |  | 
|---|
|  | 363 | // Query the size of the available data | 
|---|
|  | 364 | fSuccess = DevQueryDeviceNames( hab, pszDriver, &pldn, NULL, NULL, &pldt, NULL ); | 
|---|
|  | 365 | if ( !fSuccess ) { | 
|---|
|  | 366 | WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "DevQueryDeviceNames"); | 
|---|
| [32] | 367 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 368 | goto cleanup; | 
|---|
|  | 369 | } | 
|---|
|  | 370 |  | 
|---|
|  | 371 | // Now get the actual data | 
|---|
| [32] | 372 | /* (This originally used malloc() - switched to DosAllocMem() while in the | 
|---|
|  | 373 | * process of trying to hunt down an intermittent trap.  In fact, the trap | 
|---|
|  | 374 | * was probably caused by a flaw in WriteStemElement() which has since been | 
|---|
|  | 375 | * fixed.) | 
|---|
|  | 376 | */ | 
|---|
| [15] | 377 | #if 1 | 
|---|
|  | 378 | rc = DosAllocMem( (PVOID) &aDeviceName, (ULONG) pldn * sizeof( STR32 ), PAG_WRITE | PAG_COMMIT ); | 
|---|
|  | 379 | if ( rc != NO_ERROR ) { | 
|---|
|  | 380 | WriteErrorCode( rc, "DosAllocMem"); | 
|---|
| [32] | 381 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [15] | 382 | goto cleanup; | 
|---|
|  | 383 | } | 
|---|
|  | 384 | rc = DosAllocMem( (PVOID) &aDeviceDesc, (ULONG) pldn * sizeof( STR64 ), PAG_WRITE | PAG_COMMIT ); | 
|---|
|  | 385 | if ( rc != NO_ERROR ) { | 
|---|
|  | 386 | WriteErrorCode( rc, "DosAllocMem"); | 
|---|
| [32] | 387 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [15] | 388 | DosFreeMem( aDeviceName ); | 
|---|
|  | 389 | goto cleanup; | 
|---|
|  | 390 | } | 
|---|
|  | 391 | rc = DosAllocMem( (PVOID) &aDataType, (ULONG) pldt * sizeof( STR16 ), PAG_WRITE | PAG_COMMIT ); | 
|---|
|  | 392 | if ( rc != NO_ERROR ) { | 
|---|
|  | 393 | WriteErrorCode( rc, "DosAllocMem"); | 
|---|
| [32] | 394 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [15] | 395 | DosFreeMem( aDeviceName ); | 
|---|
|  | 396 | DosFreeMem( aDeviceDesc ); | 
|---|
|  | 397 | goto cleanup; | 
|---|
|  | 398 | } | 
|---|
|  | 399 | #else | 
|---|
| [3] | 400 | aDeviceName = malloc( pldn * sizeof( STR32 )); | 
|---|
| [15] | 401 | if ( !aDeviceName ) { | 
|---|
|  | 402 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 403 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [15] | 404 | goto cleanup; | 
|---|
|  | 405 | } | 
|---|
| [3] | 406 | aDeviceDesc = malloc( pldn * sizeof( STR64 )); | 
|---|
| [15] | 407 | if ( !aDeviceDesc ) { | 
|---|
| [3] | 408 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 409 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [15] | 410 | free( aDeviceName ); | 
|---|
| [3] | 411 | goto cleanup; | 
|---|
|  | 412 | } | 
|---|
| [15] | 413 | aDataType = malloc( pldt * sizeof( STR16 )); | 
|---|
|  | 414 | if ( !aDataType ) { | 
|---|
|  | 415 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 416 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [15] | 417 | free( aDeviceName ); | 
|---|
|  | 418 | free( aDeviceDesc ); | 
|---|
|  | 419 | goto cleanup; | 
|---|
|  | 420 | } | 
|---|
|  | 421 | #endif | 
|---|
| [3] | 422 | fSuccess = DevQueryDeviceNames( hab, pszDriver, &pldn, aDeviceName, | 
|---|
|  | 423 | aDeviceDesc, &pldt, aDataType ); | 
|---|
|  | 424 | for ( i = 0; i < pldn; i++ ) { | 
|---|
|  | 425 | WriteStemElement( szStem, i+1, (PSZ)aDeviceName[i] ); | 
|---|
|  | 426 | } | 
|---|
|  | 427 | sprintf( szNumber, "%u", pldn ); | 
|---|
|  | 428 | WriteStemElement( szStem, 0, szNumber ); | 
|---|
|  | 429 |  | 
|---|
|  | 430 | // Return 1 on success | 
|---|
| [32] | 431 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [3] | 432 |  | 
|---|
| [15] | 433 | #if 1 | 
|---|
|  | 434 | DosFreeMem( aDeviceName ); | 
|---|
|  | 435 | DosFreeMem( aDeviceDesc ); | 
|---|
|  | 436 | DosFreeMem( aDataType ); | 
|---|
|  | 437 | #else | 
|---|
| [3] | 438 | free( aDeviceName ); | 
|---|
|  | 439 | free( aDeviceDesc ); | 
|---|
|  | 440 | free( aDataType ); | 
|---|
| [15] | 441 | #endif | 
|---|
| [3] | 442 |  | 
|---|
|  | 443 | cleanup: | 
|---|
|  | 444 | WinTerminate( hab ); | 
|---|
|  | 445 | return ( 0 ); | 
|---|
|  | 446 | } | 
|---|
|  | 447 |  | 
|---|
|  | 448 |  | 
|---|
|  | 449 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 450 | * RPUEnumPorts                                                              * | 
|---|
|  | 451 | *                                                                           * | 
|---|
|  | 452 | * Gets a list of the printer ports currently defined on the system. Returns * | 
|---|
|  | 453 | * a REXX array (stem) consisting of one string per port, of the form:       * | 
|---|
|  | 454 | *   <port> <driver> <driver path>                                           * | 
|---|
|  | 455 | *                                                                           * | 
|---|
|  | 456 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 457 | *   1. The name of the stem in which to return the results.      (REQUIRED) * | 
|---|
|  | 458 | *                                                                           * | 
|---|
|  | 459 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 460 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 461 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 462 | ULONG APIENTRY RPUEnumPorts( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 463 | { | 
|---|
|  | 464 | PPRPORTINFO1 pInfo; | 
|---|
|  | 465 | PVOID        pbuf; | 
|---|
|  | 466 | ULONG        cbBuf, | 
|---|
|  | 467 | cTotal, | 
|---|
|  | 468 | cReturned, | 
|---|
|  | 469 | cbNeeded, | 
|---|
|  | 470 | i; | 
|---|
|  | 471 | CHAR         szStem[ US_STEM_MAXZ ],      // buffers used for building stem | 
|---|
|  | 472 | szNumber[ US_INTEGER_MAXZ ], // ... | 
|---|
|  | 473 | szInfo[ US_DRVINFO_MAXZ ]; | 
|---|
|  | 474 | SPLERR       rc; | 
|---|
|  | 475 |  | 
|---|
|  | 476 | // Reset the error indicator | 
|---|
|  | 477 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 478 |  | 
|---|
|  | 479 | // Make sure we have exactly one valid argument (the stem name) | 
|---|
|  | 480 | if (( argc != 1 ) || ( ! RXVALIDSTRING( argv[0] ))) | 
|---|
|  | 481 | return ( 40 ); | 
|---|
|  | 482 | if ( argv[0].strptr[ argv[0].strlength-1 ] == '.') argv[0].strlength--; | 
|---|
|  | 483 | strncpy( szStem, argv[0].strptr, RXSTRLEN( argv[0] )); | 
|---|
|  | 484 | szStem[ RXSTRLEN( argv[0] ) ] = '\0'; | 
|---|
|  | 485 |  | 
|---|
|  | 486 | // Query the amount of available data | 
|---|
|  | 487 | rc = SplEnumPort( NULL, 1, NULL, 0L, &cReturned, &cTotal, &cbNeeded, NULL ); | 
|---|
|  | 488 | if (( rc != ERROR_MORE_DATA ) && ( rc != NERR_BufTooSmall )) { | 
|---|
|  | 489 | WriteErrorCode( rc, "SplEnumPort"); | 
|---|
| [32] | 490 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 491 | return ( 0 ); | 
|---|
|  | 492 | } | 
|---|
|  | 493 |  | 
|---|
|  | 494 | // Now get the actual data | 
|---|
|  | 495 | pbuf = malloc( cbNeeded ); | 
|---|
|  | 496 | if ( !pbuf ) { | 
|---|
|  | 497 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 498 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 499 | return ( 0 ); | 
|---|
|  | 500 | } | 
|---|
|  | 501 | cbBuf = cbNeeded; | 
|---|
|  | 502 | rc = SplEnumPort( NULL, 1, pbuf, cbBuf, | 
|---|
|  | 503 | &cReturned, &cTotal, &cbNeeded, NULL ); | 
|---|
|  | 504 | if ( rc == NO_ERROR ) { | 
|---|
|  | 505 | pInfo = (PPRPORTINFO1) pbuf; | 
|---|
|  | 506 | for ( i = 0; i < cReturned; i++ ) { | 
|---|
|  | 507 | sprintf( szInfo, "%.32s %.8s %s", | 
|---|
|  | 508 | pInfo->pszPortName, | 
|---|
|  | 509 | pInfo->pszPortDriverName? pInfo->pszPortDriverName: "", | 
|---|
|  | 510 | pInfo->pszPortDriverPathName? pInfo->pszPortDriverPathName: ""); | 
|---|
|  | 511 | WriteStemElement( szStem, i+1, szInfo ); | 
|---|
|  | 512 | pInfo++; | 
|---|
|  | 513 | } | 
|---|
|  | 514 | sprintf( szNumber, "%u", cReturned ); | 
|---|
|  | 515 | WriteStemElement( szStem, 0, szNumber ); | 
|---|
| [32] | 516 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [3] | 517 | } | 
|---|
|  | 518 | else { | 
|---|
|  | 519 | WriteErrorCode( rc, "SplEnumPort"); | 
|---|
| [32] | 520 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 521 | } | 
|---|
|  | 522 | free( pbuf ); | 
|---|
|  | 523 |  | 
|---|
|  | 524 | return ( 0 ); | 
|---|
|  | 525 | } | 
|---|
|  | 526 |  | 
|---|
|  | 527 |  | 
|---|
|  | 528 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 529 | * RPUEnumDrivers                                                            * | 
|---|
|  | 530 | *                                                                           * | 
|---|
|  | 531 | * Gets a list of the printer drivers currently installed on the system.     * | 
|---|
|  | 532 | * Returns a REXX array (stem) with each item being a driver name string.    * | 
|---|
|  | 533 | *                                                                           * | 
|---|
|  | 534 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 535 | *   1. The name of the stem in which to return the results.      (REQUIRED) * | 
|---|
|  | 536 | *                                                                           * | 
|---|
|  | 537 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 538 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 539 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 540 | ULONG APIENTRY RPUEnumDrivers( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 541 | { | 
|---|
|  | 542 | PSZ    pszDriverName; | 
|---|
|  | 543 | PBYTE  pbuf; | 
|---|
|  | 544 | ULONG  cbBuf, | 
|---|
|  | 545 | cTotal, | 
|---|
|  | 546 | cReturned, | 
|---|
|  | 547 | cbNeeded, | 
|---|
|  | 548 | i; | 
|---|
|  | 549 | CHAR   szStem[ US_STEM_MAXZ ],      // buffers used for building stem | 
|---|
|  | 550 | szNumber[ US_INTEGER_MAXZ ]; // ... | 
|---|
|  | 551 | SPLERR rc; | 
|---|
|  | 552 |  | 
|---|
|  | 553 |  | 
|---|
|  | 554 | // Reset the error indicator | 
|---|
|  | 555 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 556 |  | 
|---|
|  | 557 | // Make sure we have exactly one valid argument (the stem name) | 
|---|
|  | 558 | if (( argc != 1 ) || ( ! RXVALIDSTRING( argv[0] ))) | 
|---|
|  | 559 | return ( 40 ); | 
|---|
|  | 560 | if ( argv[0].strptr[ argv[0].strlength-1 ] == '.') argv[0].strlength--; | 
|---|
|  | 561 | strncpy( szStem, argv[0].strptr, RXSTRLEN( argv[0] )); | 
|---|
|  | 562 | szStem[ RXSTRLEN( argv[0] ) ] = '\0'; | 
|---|
|  | 563 |  | 
|---|
|  | 564 | // Query the amount of available data | 
|---|
|  | 565 | rc = SplEnumDriver( NULL, 0L, NULL, 0L, &cReturned, &cTotal, &cbNeeded, NULL ); | 
|---|
|  | 566 | if (( rc != ERROR_MORE_DATA ) && ( rc != NERR_BufTooSmall )) { | 
|---|
|  | 567 | WriteErrorCode( rc, "SplEnumDriver"); | 
|---|
| [32] | 568 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 569 | return ( 0 ); | 
|---|
|  | 570 | } | 
|---|
|  | 571 |  | 
|---|
|  | 572 | // Now get the actual data | 
|---|
|  | 573 | pbuf  = (PBYTE) malloc( cbNeeded ); | 
|---|
|  | 574 | if ( !pbuf ) { | 
|---|
|  | 575 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 576 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 577 | return ( 0 ); | 
|---|
|  | 578 | } | 
|---|
|  | 579 | cbBuf = cbNeeded; | 
|---|
|  | 580 | rc = SplEnumDriver( NULL, 0L, pbuf, cbBuf, &cReturned ,&cTotal, &cbNeeded, NULL ) ; | 
|---|
|  | 581 | if ( rc == NO_ERROR ) { | 
|---|
|  | 582 | pszDriverName = (PSZ) pbuf; | 
|---|
|  | 583 | for ( i = 0; i < cReturned ; i++ ) { | 
|---|
|  | 584 | WriteStemElement( szStem, i+1, pszDriverName ); | 
|---|
|  | 585 | pszDriverName += DRIV_NAME_SIZE + DRIV_DEVICENAME_SIZE + 2; | 
|---|
|  | 586 | } | 
|---|
|  | 587 | sprintf( szNumber, "%u", cReturned ); | 
|---|
|  | 588 | WriteStemElement( szStem, 0, szNumber ); | 
|---|
| [32] | 589 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [3] | 590 | } | 
|---|
|  | 591 | else { | 
|---|
|  | 592 | WriteErrorCode( rc, "SplEnumDriver"); | 
|---|
| [32] | 593 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 594 | } | 
|---|
|  | 595 | free( pbuf ); | 
|---|
|  | 596 |  | 
|---|
|  | 597 | return ( 0 ); | 
|---|
|  | 598 | } | 
|---|
|  | 599 |  | 
|---|
|  | 600 |  | 
|---|
|  | 601 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 602 | * RPUEnumPrinters                                                           * | 
|---|
|  | 603 | *                                                                           * | 
|---|
|  | 604 | * Gets a list of the printers currently defined on the system.  Returns a   * | 
|---|
|  | 605 | * compound (stem) variable with the following format:                       * | 
|---|
|  | 606 | *                                                                           * | 
|---|
|  | 607 | *   (stem).0               Number of printers                               * | 
|---|
|  | 608 | *   (stem).i.!name         Printer device (a.k.a. physical) name            * | 
|---|
|  | 609 | *   (stem).i.!queue        Printer queue name ('' for direct printers)      * | 
|---|
|  | 610 | *   (stem).i.!host         Name of LAN host where printer queue is located  * | 
|---|
|  | 611 | *                          ('' for non-LAN printers)                        * | 
|---|
|  | 612 | *   (stem).i.!description  Printer description (name of WPS object)         * | 
|---|
|  | 613 | *   (stem).i.!handle       Printer's object handle ('' for direct printers) * | 
|---|
|  | 614 | *   (stem).i.!flags        Zero or more of the following flags (any order): * | 
|---|
|  | 615 | *                            D  This is the default printer queue           * | 
|---|
|  | 616 | *                            P  Printer queue is paused (held)              * | 
|---|
|  | 617 | *                                                                           * | 
|---|
|  | 618 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 619 | *   1. The name of the stem in which to return the results.      (REQUIRED) * | 
|---|
|  | 620 | *                                                                           * | 
|---|
|  | 621 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 622 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 623 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 624 | ULONG APIENTRY RPUEnumPrinters( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 625 | { | 
|---|
|  | 626 | PPRINTERINFO pPInfo     = NULL;     // pointer to enumerated printer information | 
|---|
|  | 627 | PPRQINFO6    pQInfo     = NULL;     // queue information (level 6) | 
|---|
|  | 628 | PVOID        pbEnum     = NULL,     // buffer for SplEnumPrinter | 
|---|
|  | 629 | pbQueue    = NULL;     // buffer for SplQueryQueue | 
|---|
|  | 630 | PSZ          pszToken; | 
|---|
|  | 631 | HOBJECT      hObj;                  // printer WPS object handle | 
|---|
| [13] | 632 |  | 
|---|
|  | 633 | /* Note: SPL_PR_LOCAL_ONLY apparently doesn't prevent SplEnumPrinter from | 
|---|
|  | 634 | *       including remote printers, it only stops it from probing them | 
|---|
|  | 635 | *       to query the remote queue information in addition to the local | 
|---|
|  | 636 | *       queue.  Specifying it here prevents a 'stall' when the remote | 
|---|
|  | 637 | *       host is offline or unavailable. | 
|---|
|  | 638 | */ | 
|---|
| [12] | 639 | ULONG        flType     = SPL_PR_QUEUE | SPL_PR_DIRECT_DEVICE | SPL_PR_LOCAL_ONLY, | 
|---|
| [3] | 640 | cbBuf      = 0, | 
|---|
|  | 641 | cTotal     = 0, | 
|---|
|  | 642 | cReturned  = 0, | 
|---|
|  | 643 | cbNeeded   = 0, | 
|---|
|  | 644 | ulCount    = 0,        // number of printers found | 
|---|
|  | 645 | i; | 
|---|
|  | 646 | CHAR         szFlags[ 3 ],          // string of flag characters | 
|---|
|  | 647 | szHandle[ 9 ],         // string for hex object handle | 
|---|
|  | 648 | // buffers used for building compound variables: | 
|---|
|  | 649 | szStem[ US_STEM_MAXZ - US_INTEGER_MAXZ - 1 ], | 
|---|
|  | 650 | szNumber[ US_INTEGER_MAXZ ], | 
|---|
|  | 651 | szStemNode[ US_STEM_MAXZ ]; | 
|---|
|  | 652 | SPLERR       rc; | 
|---|
|  | 653 |  | 
|---|
|  | 654 |  | 
|---|
|  | 655 | // Reset the error indicator | 
|---|
|  | 656 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 657 |  | 
|---|
|  | 658 | // Make sure we have exactly one valid argument (the stem name) | 
|---|
|  | 659 | if (( argc != 1 ) || ( ! RXVALIDSTRING( argv[0] ))) | 
|---|
|  | 660 | return ( 40 ); | 
|---|
|  | 661 | if ( argv[0].strptr[ argv[0].strlength-1 ] == '.') argv[0].strlength--; | 
|---|
|  | 662 | strncpy( szStem, argv[0].strptr, RXSTRLEN( argv[0] )); | 
|---|
|  | 663 | szStem[ RXSTRLEN( argv[0] ) ] = '\0'; | 
|---|
|  | 664 |  | 
|---|
|  | 665 |  | 
|---|
|  | 666 | /* Our enumeration query asks for two types of devices: direct (non-queued) | 
|---|
|  | 667 | * printers, and printer queues. | 
|---|
|  | 668 | * | 
|---|
|  | 669 | * In the latter case, it's important to note that we ask for the queues | 
|---|
|  | 670 | * themselves rather than queued printers.  Why?  Because we'll need to | 
|---|
|  | 671 | * gather information about both printers and their underlying queues (some | 
|---|
|  | 672 | * things associated with printer objects actually belong to the queue | 
|---|
|  | 673 | * rather than the printer device). | 
|---|
|  | 674 | * | 
|---|
|  | 675 | * The thing is, given a printer name, there doesn't seem to be an easy way | 
|---|
|  | 676 | * to find out the queue associated with it.  So we need to do it the other | 
|---|
|  | 677 | * way around: get the queue names, then we can identify the printers | 
|---|
|  | 678 | * connected to them. | 
|---|
|  | 679 | */ | 
|---|
|  | 680 |  | 
|---|
|  | 681 | // Query the amount of available data | 
|---|
|  | 682 | rc = SplEnumPrinter( NULL, 0L, flType, NULL, 0L, | 
|---|
|  | 683 | &cReturned, &cTotal, &cbNeeded, NULL ); | 
|---|
|  | 684 | if (( rc != ERROR_MORE_DATA ) && ( rc != NERR_BufTooSmall )) | 
|---|
|  | 685 | //   && ( rc != ERROR_INVALID_PARAMETER )) | 
|---|
|  | 686 | { | 
|---|
|  | 687 | WriteErrorCode( rc, "SplEnumPrinter"); | 
|---|
| [32] | 688 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 689 | return ( 0 ); | 
|---|
|  | 690 | } | 
|---|
|  | 691 |  | 
|---|
|  | 692 | // Now get the actual data | 
|---|
|  | 693 | pbEnum = malloc( cbNeeded ); | 
|---|
|  | 694 | if ( !pbEnum ) { | 
|---|
|  | 695 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 696 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 697 | return ( 0 ); | 
|---|
|  | 698 | } | 
|---|
|  | 699 | cbBuf = cbNeeded; | 
|---|
|  | 700 | rc = SplEnumPrinter( NULL, 0L, flType, pbEnum, cbBuf, | 
|---|
|  | 701 | &cReturned, &cTotal, &cbNeeded, NULL ); | 
|---|
|  | 702 | if ( rc != NO_ERROR ) { | 
|---|
|  | 703 | WriteErrorCode( rc, "SplEnumPrinter"); | 
|---|
| [32] | 704 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 705 | goto cleanup; | 
|---|
|  | 706 | } | 
|---|
|  | 707 |  | 
|---|
|  | 708 | pPInfo = (PPRINTERINFO) pbEnum; | 
|---|
|  | 709 | for ( i = 0; i < cReturned; i++ ) { | 
|---|
|  | 710 |  | 
|---|
|  | 711 | if ( pPInfo->flType == SPL_PR_DIRECT_DEVICE ) { | 
|---|
|  | 712 |  | 
|---|
|  | 713 | /* Direct print device.  No queue, no handle; flags do not apply. | 
|---|
|  | 714 | * The destination name and description are those of the printer | 
|---|
|  | 715 | * device itself, so we don't need any additional queries. | 
|---|
|  | 716 | */ | 
|---|
|  | 717 | sprintf( szStemNode, "%s.%u", szStem, ++ulCount ); | 
|---|
|  | 718 |  | 
|---|
|  | 719 | WriteCompoundVariable( szStemNode, "!name", | 
|---|
|  | 720 | pPInfo->pszPrintDestinationName ); | 
|---|
|  | 721 | WriteCompoundVariable( szStemNode, "!description", | 
|---|
|  | 722 | pPInfo->pszDescription ); | 
|---|
|  | 723 | WriteCompoundVariable( szStemNode, "!queue", ""); | 
|---|
|  | 724 | WriteCompoundVariable( szStemNode, "!flags", ""); | 
|---|
|  | 725 | WriteCompoundVariable( szStemNode, "!handle", ""); | 
|---|
|  | 726 |  | 
|---|
|  | 727 | WriteCompoundVariable( szStemNode, "!host", | 
|---|
|  | 728 | pPInfo->pszComputerName? | 
|---|
|  | 729 | pPInfo->pszComputerName: ""); | 
|---|
|  | 730 | } | 
|---|
|  | 731 | else if ( pPInfo->flType == SPL_PR_QUEUE ) { | 
|---|
|  | 732 |  | 
|---|
|  | 733 | /* Print queue.  We need to query the queue to find out the details | 
|---|
|  | 734 | * of the print device(s) connected to it. | 
|---|
|  | 735 | */ | 
|---|
| [11] | 736 | rc = SplQueryQueue( pPInfo->pszComputerName, | 
|---|
|  | 737 | pPInfo->pszPrintDestinationName, | 
|---|
| [3] | 738 | 6L, NULL, 0L, &cbNeeded ); | 
|---|
|  | 739 | if (( rc != NO_ERROR ) && ( rc != NERR_BufTooSmall )) { | 
|---|
|  | 740 | WriteErrorCode( rc, "SplQueryQueue"); | 
|---|
| [32] | 741 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [11] | 742 | //goto cleanup; | 
|---|
|  | 743 | continue; | 
|---|
| [3] | 744 | } | 
|---|
|  | 745 | pbQueue = malloc( cbNeeded ); | 
|---|
|  | 746 | if ( !pbQueue ) { | 
|---|
|  | 747 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 748 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [11] | 749 | //goto cleanup; | 
|---|
|  | 750 | continue; | 
|---|
| [3] | 751 | } | 
|---|
|  | 752 | cbBuf = cbNeeded; | 
|---|
| [11] | 753 | rc = SplQueryQueue( pPInfo->pszComputerName, pPInfo->pszPrintDestinationName, | 
|---|
| [3] | 754 | 6L, pbQueue, cbBuf, &cbNeeded ); | 
|---|
|  | 755 | if ( rc != NO_ERROR ) { | 
|---|
|  | 756 | WriteErrorCode( rc, "SplQueryQueue"); | 
|---|
| [32] | 757 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 758 | free( pbQueue ); | 
|---|
| [11] | 759 | //goto cleanup; | 
|---|
|  | 760 | continue; | 
|---|
| [3] | 761 | } | 
|---|
|  | 762 | pQInfo = (PPRQINFO6) pbQueue; | 
|---|
|  | 763 |  | 
|---|
|  | 764 | // Now go through the list of printers connected to this queue... | 
|---|
|  | 765 | pszToken = strtok( pQInfo->pszPrinters, ","); | 
|---|
|  | 766 | while ( pszToken ) { | 
|---|
|  | 767 | sprintf( szStemNode, "%s.%u", szStem, ++ulCount ); | 
|---|
|  | 768 | WriteCompoundVariable( szStemNode, "!name", pszToken ); | 
|---|
|  | 769 | WriteCompoundVariable( szStemNode, "!description", pQInfo->pszComment ); | 
|---|
|  | 770 | WriteCompoundVariable( szStemNode, "!queue", pQInfo->pszName ); | 
|---|
|  | 771 | WriteCompoundVariable( szStemNode, "!driver", pQInfo->pszDriverName ); | 
|---|
|  | 772 | WriteCompoundVariable( szStemNode, "!host", | 
|---|
|  | 773 | pQInfo->pszRemoteComputerName ? | 
|---|
|  | 774 | pQInfo->pszRemoteComputerName: ""); | 
|---|
|  | 775 |  | 
|---|
|  | 776 | hObj = PrinterObjectHandle( pQInfo->pszName ); | 
|---|
|  | 777 | if ( hObj ) | 
|---|
|  | 778 | sprintf( szHandle, "%X", hObj ); | 
|---|
|  | 779 | else | 
|---|
|  | 780 | sprintf( szHandle, ""); | 
|---|
|  | 781 | WriteCompoundVariable( szStemNode, "!handle", szHandle ); | 
|---|
|  | 782 |  | 
|---|
|  | 783 | memset( szFlags, 0, sizeof( szFlags )); | 
|---|
|  | 784 | if ( pQInfo->fsType & PRQ3_TYPE_APPDEFAULT ) | 
|---|
|  | 785 | strcat( szFlags, "D"); | 
|---|
|  | 786 | if ( pQInfo->fsStatus & PRQ3_PAUSED ) | 
|---|
|  | 787 | strcat( szFlags, "P"); | 
|---|
|  | 788 | WriteCompoundVariable( szStemNode, "!flags", szFlags ); | 
|---|
|  | 789 |  | 
|---|
|  | 790 | pszToken = strtok( NULL, ","); | 
|---|
|  | 791 | } // while | 
|---|
|  | 792 |  | 
|---|
|  | 793 | free( pbQueue ); | 
|---|
|  | 794 | } | 
|---|
|  | 795 |  | 
|---|
|  | 796 | pPInfo++; | 
|---|
|  | 797 | } | 
|---|
|  | 798 | sprintf( szNumber, "%u", ulCount ); | 
|---|
|  | 799 | WriteStemElement( szStem, 0, szNumber ); | 
|---|
| [32] | 800 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [3] | 801 |  | 
|---|
|  | 802 | cleanup: | 
|---|
|  | 803 | free( pbEnum ); | 
|---|
|  | 804 | return ( 0 ); | 
|---|
|  | 805 | } | 
|---|
|  | 806 |  | 
|---|
|  | 807 |  | 
|---|
|  | 808 | /* ------------------------------------------------------------------------- * | 
|---|
| [5] | 809 | * RPUOpenView                                                               * | 
|---|
| [3] | 810 | *                                                                           * | 
|---|
|  | 811 | * Opens the requested view of the WPS object corresponding to the specified * | 
|---|
|  | 812 | * print queue.  (Note that WPS printer objects are associated with a queue  * | 
|---|
|  | 813 | * rather than a printer device, so it is the queue name that must be passed * | 
|---|
|  | 814 | * to this function.)                                                        * | 
|---|
|  | 815 | *                                                                           * | 
|---|
|  | 816 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 817 | *   1. The name of the printer queue for the object to open.  (REQUIRED)    * | 
|---|
|  | 818 | *   2. Optional view flag, one of:                                          * | 
|---|
|  | 819 | *        O  Object's default view  (DEFAULT)                                * | 
|---|
|  | 820 | *        D  Details view                                                    * | 
|---|
|  | 821 | *        I  Icon view                                                       * | 
|---|
|  | 822 | *        S  Settings                                                        * | 
|---|
|  | 823 | *                                                                           * | 
|---|
|  | 824 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 825 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 826 | * ------------------------------------------------------------------------- */ | 
|---|
| [5] | 827 | ULONG APIENTRY RPUOpenView( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
| [3] | 828 | { | 
|---|
|  | 829 | HOBJECT hObj; | 
|---|
|  | 830 | ULONG   ulView = OPEN_DEFAULT; | 
|---|
|  | 831 | BOOL    fRC; | 
|---|
|  | 832 |  | 
|---|
|  | 833 |  | 
|---|
|  | 834 | // Reset the error indicator | 
|---|
|  | 835 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 836 |  | 
|---|
|  | 837 | // Make sure we have at least one valid argument (the queue name) | 
|---|
|  | 838 | if ( argc < 1  || ( !RXVALIDSTRING(argv[0]) )) return ( 40 ); | 
|---|
|  | 839 | pszName = argv[0].strptr; | 
|---|
|  | 840 |  | 
|---|
|  | 841 | // Second argument: view (optional, but must be correct if specified) | 
|---|
|  | 842 | if ( argc == 2 ) { | 
|---|
|  | 843 | if ( RXVALIDSTRING(argv[1]) ) { | 
|---|
|  | 844 | switch ( argv[1].strptr[0] ) { | 
|---|
|  | 845 | case 'o': | 
|---|
|  | 846 | case 'O': ulView = OPEN_DEFAULT;  break; | 
|---|
|  | 847 | case 'd': | 
|---|
|  | 848 | case 'D': ulView = OPEN_DETAILS;  break; | 
|---|
|  | 849 | case 'i': | 
|---|
|  | 850 | case 'I': ulView = OPEN_CONTENTS; break; | 
|---|
|  | 851 | case 's': | 
|---|
|  | 852 | case 'S': ulView = OPEN_SETTINGS; break; | 
|---|
|  | 853 | default : return ( 40 ); | 
|---|
|  | 854 | } | 
|---|
|  | 855 | } | 
|---|
|  | 856 | else return ( 40 ); | 
|---|
|  | 857 | } | 
|---|
|  | 858 | if ( argc > 2 ) return ( 40 ); | 
|---|
|  | 859 |  | 
|---|
|  | 860 | hObj = PrinterObjectHandle( pszName ); | 
|---|
| [11] | 861 | if ( !hObj ) { | 
|---|
| [32] | 862 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [11] | 863 | return ( 0 ); | 
|---|
|  | 864 | } | 
|---|
| [3] | 865 |  | 
|---|
|  | 866 | fRC = WinOpenObject( hObj, ulView, TRUE ); | 
|---|
|  | 867 |  | 
|---|
| [32] | 868 | SaveResultString( prsResult, fRC? PSZ_ONE: PSZ_ZERO, 1 ); | 
|---|
| [3] | 869 | return ( 0 ); | 
|---|
|  | 870 | } | 
|---|
|  | 871 |  | 
|---|
|  | 872 |  | 
|---|
|  | 873 | /* ------------------------------------------------------------------------- * | 
|---|
| [14] | 874 | * RPUPortInfo                                                               * | 
|---|
|  | 875 | *                                                                           * | 
|---|
|  | 876 | * Queries basic information about a local port.  This is different from     * | 
|---|
|  | 877 | * RPUPortQuery() in that the latter returns port configuration information  * | 
|---|
|  | 878 | * from the port driver itself, whereas this function only returns what the  * | 
|---|
|  | 879 | * spooler itself knows about the port.                                      * | 
|---|
|  | 880 | *                                                                           * | 
|---|
|  | 881 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 882 | *   1. The name of the port.                                     (REQUIRED) * | 
|---|
|  | 883 | *   2. The name of the stem in which to return the results:      (REQUIRED) * | 
|---|
|  | 884 | *      (stem).!name       The name of the port                              * | 
|---|
|  | 885 | *      (stem).!driver     The name of the port driver                       * | 
|---|
|  | 886 | *      (stem).!converter  The name of the protocol converter used           * | 
|---|
| [15] | 887 | *   TODO                                                                    * | 
|---|
|  | 888 | *      (stem).!printer    The device name of the printer(s) using this      * | 
|---|
|  | 889 | *                         port, if any ('' if not in use)                   * | 
|---|
| [14] | 890 | *                                                                           * | 
|---|
|  | 891 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 892 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 893 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 894 | ULONG APIENTRY RPUPortInfo( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 895 | { | 
|---|
|  | 896 | PPRPORTINFO2 pInfo      = NULL; | 
|---|
|  | 897 | PVOID        pbuf       = NULL; | 
|---|
|  | 898 | ULONG        cbBuf      = 0, | 
|---|
|  | 899 | cbNeeded   = 0; | 
|---|
|  | 900 | CHAR         szStem[ US_STEM_MAXZ ];   // compound variable stem name | 
|---|
|  | 901 | PSZ          pszPortName; | 
|---|
|  | 902 | SPLERR       rc; | 
|---|
|  | 903 |  | 
|---|
|  | 904 |  | 
|---|
|  | 905 | // Reset the error indicator | 
|---|
|  | 906 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 907 |  | 
|---|
|  | 908 | // Validate the REXX arguments | 
|---|
|  | 909 | if (( argc != 2 ) || | 
|---|
|  | 910 | ( ! RXVALIDSTRING( argv[0] )) || ( ! RXVALIDSTRING( argv[1] ))) | 
|---|
|  | 911 | return ( 40 ); | 
|---|
|  | 912 |  | 
|---|
|  | 913 | pszPortName = argv[0].strptr; | 
|---|
|  | 914 |  | 
|---|
|  | 915 | // Initialize the result stem name | 
|---|
|  | 916 | if ( RXSTRLEN(argv[1]) > US_STEM_MAXZ ) return ( 40 ); | 
|---|
|  | 917 | if ( argv[1].strptr[ argv[1].strlength-1 ] == '.') argv[1].strlength--; | 
|---|
|  | 918 | strncpy( szStem, argv[1].strptr, RXSTRLEN( argv[1] )); | 
|---|
|  | 919 | szStem[ RXSTRLEN( argv[1] ) ] = '\0'; | 
|---|
|  | 920 |  | 
|---|
|  | 921 |  | 
|---|
|  | 922 | // Query the amount of available data | 
|---|
|  | 923 | rc = SplQueryPort( NULL, pszPortName, 2L, NULL, 0L, &cbNeeded ); | 
|---|
|  | 924 | if (( rc != ERROR_MORE_DATA ) && ( rc != NERR_BufTooSmall )) | 
|---|
|  | 925 | { | 
|---|
|  | 926 | WriteErrorCode( rc, "SplQueryPort"); | 
|---|
| [32] | 927 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [14] | 928 | return ( 0 ); | 
|---|
|  | 929 | } | 
|---|
|  | 930 |  | 
|---|
|  | 931 | // Now get the actual data | 
|---|
|  | 932 | pbuf = malloc( cbNeeded ); | 
|---|
|  | 933 | if ( !pbuf ) { | 
|---|
|  | 934 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 935 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [14] | 936 | return ( 0 ); | 
|---|
|  | 937 | } | 
|---|
|  | 938 | cbBuf = cbNeeded; | 
|---|
|  | 939 | rc = SplQueryPort( NULL, pszPortName, 2L, pbuf, cbBuf, &cbNeeded ); | 
|---|
|  | 940 | if ( rc == NO_ERROR ) { | 
|---|
|  | 941 | pInfo = (PPRPORTINFO2) pbuf; | 
|---|
|  | 942 | WriteCompoundVariable( szStem, "!name",      pInfo->pszPortName ); | 
|---|
|  | 943 | WriteCompoundVariable( szStem, "!driver",    pInfo->pszPortDriver ); | 
|---|
|  | 944 | WriteCompoundVariable( szStem, "!converter", pInfo->pszProtocolConverter ); | 
|---|
| [32] | 945 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [14] | 946 | } | 
|---|
|  | 947 | else { | 
|---|
|  | 948 | WriteErrorCode( rc, "SplQueryPort"); | 
|---|
| [32] | 949 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [14] | 950 | } | 
|---|
|  | 951 |  | 
|---|
|  | 952 | free( pbuf ); | 
|---|
|  | 953 | return ( 0 ); | 
|---|
|  | 954 | } | 
|---|
|  | 955 |  | 
|---|
|  | 956 |  | 
|---|
|  | 957 | /* ------------------------------------------------------------------------- * | 
|---|
| [3] | 958 | * RPUPortInstall                                                            * | 
|---|
|  | 959 | *                                                                           * | 
|---|
|  | 960 | * Creates a new printer port.                                               * | 
|---|
|  | 961 | *                                                                           * | 
|---|
|  | 962 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 963 | *   1. The name of the port driver without any extension.  This must be     * | 
|---|
|  | 964 | *      installed and registered in OS2.INI already.         (REQUIRED)      * | 
|---|
|  | 965 | *   2. The name of the new port to be created.  If not specified, the port  * | 
|---|
| [13] | 966 | *      driver will be responsible for using a default name.  This should    * | 
|---|
|  | 967 | *      generally be specified, as the driver is not guaranteed to support   * | 
|---|
|  | 968 | *      omitting it.                                         (DEFAULT: none) * | 
|---|
| [3] | 969 | *                                                                           * | 
|---|
|  | 970 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 971 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 972 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 973 | ULONG APIENTRY RPUPortInstall( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 974 | { | 
|---|
|  | 975 | HAB     hab;                        // desktop anchor-block handle | 
|---|
|  | 976 | HMODULE hPdr = NULLHANDLE;          // handle to port driver module | 
|---|
|  | 977 | PFN     pfnInstallPort;             // pointer to driver's SplPdInstallPort entrypoint | 
|---|
|  | 978 | ULONG   ulCB;                       // return value from PrfQueryProfileString() | 
|---|
|  | 979 | PSZ     pszPdrName     = NULL,      // name of the specified port driver | 
|---|
|  | 980 | pszPortName    = NULL;      // name of the new port to create | 
|---|
|  | 981 | CHAR    szPathName[ CCHMAXPATH+1 ]; // FQN of the port driver module | 
|---|
|  | 982 | APIRET  rc = 0;                     // return code from Dos...() functions | 
|---|
|  | 983 |  | 
|---|
|  | 984 |  | 
|---|
|  | 985 | // Reset the error indicator | 
|---|
|  | 986 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 987 |  | 
|---|
|  | 988 | // Make sure we have at least one valid argument (the port driver name) | 
|---|
|  | 989 | if ( argc < 1  || ( !RXVALIDSTRING(argv[0]) )) return ( 40 ); | 
|---|
|  | 990 | pszPdrName = argv[0].strptr; | 
|---|
|  | 991 |  | 
|---|
|  | 992 | // Second argument: new port name (optional, but must be correct if specified) | 
|---|
|  | 993 | if ( argc >= 2 ) { | 
|---|
|  | 994 | if ( RXVALIDSTRING(argv[1]) ) | 
|---|
|  | 995 | pszPortName = strupr( argv[1].strptr ); | 
|---|
|  | 996 | else return ( 40 ); | 
|---|
|  | 997 | } | 
|---|
|  | 998 |  | 
|---|
|  | 999 | // Get the path to the installed port driver | 
|---|
|  | 1000 | hab = WinInitialize( 0 ); | 
|---|
|  | 1001 | if ( !hab ) { | 
|---|
|  | 1002 | WriteErrorCode( 0, "WinInitialize"); | 
|---|
| [32] | 1003 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1004 | return ( 0 ); | 
|---|
|  | 1005 | } | 
|---|
|  | 1006 |  | 
|---|
|  | 1007 | ulCB = PrfQueryProfileString( HINI_SYSTEMPROFILE, APPNAME_PM_PORT_DRIVER, | 
|---|
|  | 1008 | pszPdrName, NULL, (PVOID) szPathName, CCHMAXPATH ); | 
|---|
|  | 1009 | if ( !ulCB ) { | 
|---|
|  | 1010 | WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileString"); | 
|---|
| [32] | 1011 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1012 | goto cleanup; | 
|---|
|  | 1013 | } | 
|---|
|  | 1014 |  | 
|---|
|  | 1015 | // Load the port driver DLL and register its port install routine | 
|---|
|  | 1016 | rc = DosLoadModule( NULL, 0, szPathName, &hPdr ); | 
|---|
|  | 1017 | if ( rc != NO_ERROR || !hPdr ) { | 
|---|
|  | 1018 | WriteErrorCode( rc, "DosLoadModule"); | 
|---|
| [32] | 1019 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1020 | goto cleanup; | 
|---|
|  | 1021 | } | 
|---|
|  | 1022 | rc = DosQueryProcAddr( hPdr, 0, "SPLPDINSTALLPORT", &pfnInstallPort ); | 
|---|
|  | 1023 | if ( rc != NO_ERROR ) { | 
|---|
|  | 1024 | WriteErrorCode( rc, "DosQueryProcAddr"); | 
|---|
| [32] | 1025 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1026 | goto finish; | 
|---|
|  | 1027 | } | 
|---|
|  | 1028 |  | 
|---|
|  | 1029 | // Now create the new port (the driver will assign it default settings) | 
|---|
|  | 1030 | rc = pfnInstallPort( hab, pszPortName ); | 
|---|
|  | 1031 | if ( rc == NO_ERROR ) { | 
|---|
|  | 1032 | // Return 1 on success | 
|---|
| [32] | 1033 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [3] | 1034 | } | 
|---|
|  | 1035 | else { | 
|---|
|  | 1036 | WriteErrorCode( rc, "SplPdInstallPort"); | 
|---|
| [32] | 1037 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1038 | } | 
|---|
|  | 1039 |  | 
|---|
|  | 1040 | finish: | 
|---|
|  | 1041 | DosFreeModule( hPdr ); | 
|---|
|  | 1042 | cleanup: | 
|---|
|  | 1043 | WinTerminate( hab ); | 
|---|
|  | 1044 | return ( 0 ); | 
|---|
|  | 1045 | } | 
|---|
|  | 1046 |  | 
|---|
|  | 1047 |  | 
|---|
|  | 1048 | /* ------------------------------------------------------------------------- * | 
|---|
| [13] | 1049 | * RPUPortQuery                                                              * | 
|---|
|  | 1050 | *                                                                           * | 
|---|
|  | 1051 | * Queries the specified port's configuration settings.  IMPORTANT: not all  * | 
|---|
|  | 1052 | * port drivers support this; the standard OS/2 serial and parallel port     * | 
|---|
|  | 1053 | * drivers do NOT.  When this API is not supported, the return value should  * | 
|---|
|  | 1054 | * be ''.  Otherwise, the format of the returned configuration data is a     * | 
|---|
|  | 1055 | * string of binary data in port driver-specific format (the caller assumes  * | 
|---|
|  | 1056 | * responsibility for knowing how to interpret it).                          * | 
|---|
|  | 1057 | *                                                                           * | 
|---|
|  | 1058 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 1059 | *   1. The name of the port driver without any extension.  This must be     * | 
|---|
|  | 1060 | *      installed and registered in OS2.INI already.              (REQUIRED) * | 
|---|
|  | 1061 | *   2. The name of the port to be queried.                       (REQUIRED) * | 
|---|
|  | 1062 | *                                                                           * | 
|---|
|  | 1063 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 1064 | *   Binary data representing the port configuration, in whatever format is  * | 
|---|
|  | 1065 | *   returned by the driver's SplPdQuery->BIDI_Q_PORTDRV routine.  This      * | 
|---|
|  | 1066 | *   depends on the particular port driver; consult its API documentation.   * | 
|---|
|  | 1067 | *   '' will be returned if an error occurred.                               * | 
|---|
|  | 1068 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1069 | ULONG APIENTRY RPUPortQuery( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 1070 | { | 
|---|
|  | 1071 | HAB     hab;                        // desktop anchor-block handle | 
|---|
|  | 1072 | HMODULE hPdr = NULLHANDLE;          // handle to port driver module | 
|---|
|  | 1073 | PFN     pfnQueryPort;               // pointer to driver's SplPdSet entrypoint | 
|---|
|  | 1074 | ULONG   ulCB,                       // return value from PrfQueryProfileString() | 
|---|
|  | 1075 | cBuf;                       // size of configuration buffer | 
|---|
|  | 1076 | PSZ     pszPdrName  = NULL,         // name of the specified port driver | 
|---|
|  | 1077 | pszPortName = NULL;         // name of the new port to create | 
|---|
|  | 1078 | CHAR    szPathName[ CCHMAXPATH+1 ]; // FQN of the port driver module | 
|---|
|  | 1079 | PBYTE   pBuf;                       // Pointer to configuration buffer | 
|---|
|  | 1080 | APIRET  rc = 0;                     // return code from Dos...() functions | 
|---|
|  | 1081 |  | 
|---|
|  | 1082 |  | 
|---|
|  | 1083 | // Reset the error indicator | 
|---|
|  | 1084 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 1085 |  | 
|---|
|  | 1086 | // Make sure we have exactly two valid arguments | 
|---|
|  | 1087 | if ( argc != 2 || | 
|---|
|  | 1088 | !RXVALIDSTRING( argv[0] ) || | 
|---|
|  | 1089 | !RXVALIDSTRING( argv[1] )) | 
|---|
|  | 1090 | return ( 40 ); | 
|---|
|  | 1091 | pszPdrName  = strupr( argv[0].strptr ); | 
|---|
|  | 1092 | pszPortName = strupr( argv[1].strptr ); | 
|---|
|  | 1093 |  | 
|---|
|  | 1094 | // Get the path to the installed port driver | 
|---|
|  | 1095 | hab = WinInitialize( 0 ); | 
|---|
|  | 1096 | if ( !hab ) { | 
|---|
|  | 1097 | WriteErrorCode( 0, "WinInitialize"); | 
|---|
| [32] | 1098 | SaveResultString( prsResult, NULL, 0 ); | 
|---|
| [13] | 1099 | return ( 0 ); | 
|---|
|  | 1100 | } | 
|---|
|  | 1101 |  | 
|---|
|  | 1102 | ulCB = PrfQueryProfileString( HINI_SYSTEMPROFILE, APPNAME_PM_PORT_DRIVER, | 
|---|
|  | 1103 | pszPdrName, NULL, (PVOID) szPathName, CCHMAXPATH ); | 
|---|
|  | 1104 | if ( !ulCB ) { | 
|---|
|  | 1105 | WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileString"); | 
|---|
| [32] | 1106 | SaveResultString( prsResult, NULL, 0 ); | 
|---|
| [13] | 1107 | goto cleanup; | 
|---|
|  | 1108 | } | 
|---|
|  | 1109 |  | 
|---|
|  | 1110 | // Load the port driver DLL and register its query routine | 
|---|
|  | 1111 | rc = DosLoadModule( NULL, 0, szPathName, &hPdr ); | 
|---|
|  | 1112 | if ( rc != NO_ERROR || !hPdr ) { | 
|---|
|  | 1113 | WriteErrorCode( rc, "DosLoadModule"); | 
|---|
| [32] | 1114 | SaveResultString( prsResult, NULL, 0 ); | 
|---|
| [13] | 1115 | goto cleanup; | 
|---|
|  | 1116 | } | 
|---|
|  | 1117 | rc = DosQueryProcAddr( hPdr, 0, "SPLPDQUERY", &pfnQueryPort ); | 
|---|
|  | 1118 | if ( rc != NO_ERROR ) { | 
|---|
|  | 1119 | WriteErrorCode( rc, "DosQueryProcAddr"); | 
|---|
| [32] | 1120 | SaveResultString( prsResult, NULL, 0 ); | 
|---|
| [13] | 1121 | goto finish; | 
|---|
|  | 1122 | } | 
|---|
|  | 1123 |  | 
|---|
|  | 1124 | // Now get the port configuration | 
|---|
|  | 1125 | rc = pfnQueryPort( pszPortName, TYPE_SHORT_WAIT, BIDI_Q_PORTDRV, NULL, 0, NULL, &cBuf ); | 
|---|
|  | 1126 | if ( cBuf && ( rc == NO_ERROR ) || | 
|---|
|  | 1127 | ( rc == ERROR_MORE_DATA ) || ( rc == NERR_BufTooSmall )) | 
|---|
|  | 1128 | { | 
|---|
|  | 1129 | pBuf = (PBYTE) malloc( cBuf ); | 
|---|
|  | 1130 | if ( pBuf ) { | 
|---|
|  | 1131 | rc = pfnQueryPort( pszPortName, TYPE_SHORT_WAIT, BIDI_Q_PORTDRV, NULL, 0, pBuf, &cBuf ); | 
|---|
|  | 1132 | if ( rc == NO_ERROR ) { | 
|---|
|  | 1133 | // Write the data contents to our return RXSTRING | 
|---|
|  | 1134 | if ( !SaveResultString( prsResult, pBuf, cBuf )) | 
|---|
| [32] | 1135 | SaveResultString( prsResult, NULL, 0 ); | 
|---|
| [13] | 1136 | } | 
|---|
|  | 1137 | else { | 
|---|
|  | 1138 | WriteErrorCode( rc, "SplPdQuery 2"); | 
|---|
| [32] | 1139 | SaveResultString( prsResult, NULL, 0 ); | 
|---|
| [13] | 1140 | } | 
|---|
|  | 1141 | free( pBuf ); | 
|---|
|  | 1142 | } | 
|---|
|  | 1143 | else { | 
|---|
|  | 1144 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 1145 | SaveResultString( prsResult, NULL, 0 ); | 
|---|
| [13] | 1146 | } | 
|---|
|  | 1147 | } | 
|---|
|  | 1148 | else { | 
|---|
|  | 1149 | WriteErrorCode( rc, "SplPdQuery 1"); | 
|---|
| [32] | 1150 | SaveResultString( prsResult, NULL, 0 ); | 
|---|
| [13] | 1151 | } | 
|---|
|  | 1152 |  | 
|---|
|  | 1153 | finish: | 
|---|
|  | 1154 | DosFreeModule( hPdr ); | 
|---|
|  | 1155 | cleanup: | 
|---|
|  | 1156 | WinTerminate( hab ); | 
|---|
|  | 1157 | return ( 0 ); | 
|---|
|  | 1158 | } | 
|---|
|  | 1159 |  | 
|---|
|  | 1160 |  | 
|---|
|  | 1161 | /* ------------------------------------------------------------------------- * | 
|---|
| [3] | 1162 | * RPUPortSet                                                                * | 
|---|
|  | 1163 | *                                                                           * | 
|---|
|  | 1164 | * Sets the specified port's configuration settings.  IMPORTANT: not all     * | 
|---|
|  | 1165 | * port drivers support this; the standard OS/2 serial and parallel port     * | 
|---|
|  | 1166 | * drivers do NOT.  Depending on the port driver, there are two possible     * | 
|---|
|  | 1167 | * outcomes when this API is not supported:                                  * | 
|---|
|  | 1168 | *   A. Port driver does not have an entrypoint for SplPdSet. This is the    * | 
|---|
|  | 1169 | *      case for any port driver using pre-Warp conventions. RPUPortSet will * | 
|---|
|  | 1170 | *      return 0 and RPUERROR will be "1: DosQueryProcAddr".                 * | 
|---|
|  | 1171 | *   B. Port driver supports SplPdSet but does not (correctly) implement the * | 
|---|
|  | 1172 | *      BIDI_SET_PORTDRV command. This is the case for some third-party port * | 
|---|
|  | 1173 | *      drivers. In this case, whether or not RPUPortSet returns a success   * | 
|---|
|  | 1174 | *      code entirely depends on how conscientiously the port driver itself  * | 
|---|
|  | 1175 | *      is written, but the "INITIALIZATION" key (and possibly others) in    * | 
|---|
|  | 1176 | *      the port's entry in OS2SYS.INI will not be updated. The application  * | 
|---|
|  | 1177 | *      should always check for this after calling RPUPortSet!               * | 
|---|
|  | 1178 | * If the application determines that either of these failure conditions has * | 
|---|
|  | 1179 | * occurred, it is advisable to call RPUPortDialog as a fallback measure.    * | 
|---|
|  | 1180 | *                                                                           * | 
|---|
|  | 1181 | * Because of the above, use of this function is not generally encouraged    * | 
|---|
|  | 1182 | * except when absolutely necessary.                                         * | 
|---|
|  | 1183 | *                                                                           * | 
|---|
|  | 1184 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 1185 | *   1. The name of the port driver without any extension.  This must be     * | 
|---|
|  | 1186 | *      installed and registered in OS2.INI already.              (REQUIRED) * | 
|---|
|  | 1187 | *   2. The name of the port to be configured.                    (REQUIRED) * | 
|---|
|  | 1188 | *   3. Byte sequence representing the new port configuration.  The format   * | 
|---|
|  | 1189 | *      depends on the port driver (and it is up to the caller to know what  * | 
|---|
|  | 1190 | *      it is).                                                   (REQUIRED) * | 
|---|
|  | 1191 | *                                                                           * | 
|---|
|  | 1192 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 1193 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 1194 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1195 | ULONG APIENTRY RPUPortSet( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 1196 | { | 
|---|
|  | 1197 | HAB     hab;                        // desktop anchor-block handle | 
|---|
|  | 1198 | HMODULE hPdr = NULLHANDLE;          // handle to port driver module | 
|---|
|  | 1199 | PFN     pfnSetPort;                 // pointer to driver's SplPdSet entrypoint | 
|---|
|  | 1200 | ULONG   ulCB,                       // return value from PrfQueryProfileString() | 
|---|
|  | 1201 | cBuf;                       // size of configuration buffer | 
|---|
|  | 1202 | PSZ     pszPdrName  = NULL,         // name of the specified port driver | 
|---|
|  | 1203 | pszPortName = NULL;         // name of the new port to create | 
|---|
|  | 1204 | CHAR    szPathName[ CCHMAXPATH+1 ]; // FQN of the port driver module | 
|---|
|  | 1205 | PBYTE   pBuf;                       // Pointer to configuration buffer | 
|---|
|  | 1206 | APIRET  rc = 0;                     // return code from Dos...() functions | 
|---|
|  | 1207 |  | 
|---|
|  | 1208 |  | 
|---|
|  | 1209 | // Reset the error indicator | 
|---|
|  | 1210 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 1211 |  | 
|---|
|  | 1212 | // Make sure we have exactly three valid arguments | 
|---|
|  | 1213 | if ( argc != 3 || | 
|---|
|  | 1214 | !RXVALIDSTRING( argv[0] ) || | 
|---|
|  | 1215 | !RXVALIDSTRING( argv[1] ) || | 
|---|
|  | 1216 | !RXVALIDSTRING( argv[2] )  ) | 
|---|
|  | 1217 | return ( 40 ); | 
|---|
| [13] | 1218 | pszPdrName  = strupr( argv[0].strptr ); | 
|---|
| [3] | 1219 | pszPortName = strupr( argv[1].strptr ); | 
|---|
|  | 1220 | pBuf        = argv[2].strptr; | 
|---|
|  | 1221 | cBuf        = argv[2].strlength; | 
|---|
|  | 1222 |  | 
|---|
|  | 1223 | // Get the path to the installed port driver | 
|---|
|  | 1224 | hab = WinInitialize( 0 ); | 
|---|
|  | 1225 | if ( !hab ) { | 
|---|
|  | 1226 | WriteErrorCode( 0, "WinInitialize"); | 
|---|
| [32] | 1227 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1228 | return ( 0 ); | 
|---|
|  | 1229 | } | 
|---|
|  | 1230 |  | 
|---|
|  | 1231 | ulCB = PrfQueryProfileString( HINI_SYSTEMPROFILE, APPNAME_PM_PORT_DRIVER, | 
|---|
|  | 1232 | pszPdrName, NULL, (PVOID) szPathName, CCHMAXPATH ); | 
|---|
|  | 1233 | if ( !ulCB ) { | 
|---|
|  | 1234 | WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileString"); | 
|---|
| [32] | 1235 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1236 | goto cleanup; | 
|---|
|  | 1237 | } | 
|---|
|  | 1238 |  | 
|---|
|  | 1239 | // Load the port driver DLL and register its configuration routine | 
|---|
|  | 1240 | rc = DosLoadModule( NULL, 0, szPathName, &hPdr ); | 
|---|
|  | 1241 | if ( rc != NO_ERROR || !hPdr ) { | 
|---|
|  | 1242 | WriteErrorCode( rc, "DosLoadModule"); | 
|---|
| [32] | 1243 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1244 | goto cleanup; | 
|---|
|  | 1245 | } | 
|---|
|  | 1246 | rc = DosQueryProcAddr( hPdr, 0, "SPLPDSET", &pfnSetPort ); | 
|---|
|  | 1247 | if ( rc != NO_ERROR ) { | 
|---|
|  | 1248 | WriteErrorCode( rc, "DosQueryProcAddr"); | 
|---|
| [32] | 1249 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1250 | goto finish; | 
|---|
|  | 1251 | } | 
|---|
|  | 1252 |  | 
|---|
|  | 1253 | // Now set the new port configuration | 
|---|
|  | 1254 | rc = pfnSetPort( pszPortName, TYPE_LONG_WAIT, BIDI_SET_PORTDRV, pBuf, cBuf ); | 
|---|
|  | 1255 | if ( rc == NO_ERROR ) { | 
|---|
|  | 1256 | // Return 1 on success | 
|---|
| [32] | 1257 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [3] | 1258 | } | 
|---|
|  | 1259 | else { | 
|---|
|  | 1260 | WriteErrorCode( rc, "SplPdSet"); | 
|---|
| [32] | 1261 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1262 | } | 
|---|
|  | 1263 |  | 
|---|
|  | 1264 | finish: | 
|---|
|  | 1265 | DosFreeModule( hPdr ); | 
|---|
|  | 1266 | cleanup: | 
|---|
|  | 1267 | WinTerminate( hab ); | 
|---|
|  | 1268 | return ( 0 ); | 
|---|
|  | 1269 | } | 
|---|
|  | 1270 |  | 
|---|
|  | 1271 |  | 
|---|
|  | 1272 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 1273 | * RPUPortDialog                                                             * | 
|---|
|  | 1274 | *                                                                           * | 
|---|
|  | 1275 | * Brings up the specified port's configuration dialog.  This function can   * | 
|---|
|  | 1276 | * only be used from a PM process.                                           * | 
|---|
|  | 1277 | *                                                                           * | 
|---|
|  | 1278 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 1279 | *   1. The name of the port driver without any extension.  This must be     * | 
|---|
|  | 1280 | *      installed and registered in OS2.INI already.              (REQUIRED) * | 
|---|
|  | 1281 | *   2. The name of the port to be configured.                    (REQUIRED) * | 
|---|
|  | 1282 | *                                                                           * | 
|---|
|  | 1283 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 1284 | *   1 if the user modified the port configuration.                          * | 
|---|
|  | 1285 | *   0 if no changes were made, or if an error occurred.                     * | 
|---|
|  | 1286 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1287 | ULONG APIENTRY RPUPortDialog( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 1288 | { | 
|---|
|  | 1289 | HAB     hab;                        // desktop anchor-block handle | 
|---|
|  | 1290 | HMODULE hPdr = NULLHANDLE;          // handle to port driver module | 
|---|
|  | 1291 | PFN     pfnSetPort;                 // pointer to driver's SplPdSet entrypoint | 
|---|
|  | 1292 | ULONG   ulCB,                       // return value from PrfQueryProfileString() | 
|---|
|  | 1293 | flModified  = 0;            // flag indicating settings were changed | 
|---|
|  | 1294 | PSZ     pszPdrName  = NULL,         // name of the specified port driver | 
|---|
|  | 1295 | pszPortName = NULL;         // name of the new port to create | 
|---|
|  | 1296 | CHAR    szPathName[ CCHMAXPATH+1 ]; // FQN of the port driver module | 
|---|
|  | 1297 | APIRET  rc = 0;                     // return code from Dos...() functions | 
|---|
|  | 1298 |  | 
|---|
|  | 1299 |  | 
|---|
|  | 1300 | // Reset the error indicator | 
|---|
|  | 1301 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 1302 |  | 
|---|
|  | 1303 | // Make sure we have exactly two valid arguments | 
|---|
|  | 1304 | if ( argc != 2 || | 
|---|
|  | 1305 | !RXVALIDSTRING( argv[0] ) || | 
|---|
|  | 1306 | !RXVALIDSTRING( argv[1] )  ) | 
|---|
|  | 1307 | return ( 40 ); | 
|---|
| [13] | 1308 | pszPdrName  = strupr( argv[0].strptr ); | 
|---|
| [3] | 1309 | pszPortName = strupr( argv[1].strptr ); | 
|---|
|  | 1310 |  | 
|---|
|  | 1311 | // Get the path to the installed port driver | 
|---|
|  | 1312 | hab = WinInitialize( 0 ); | 
|---|
|  | 1313 | if ( !hab ) { | 
|---|
|  | 1314 | WriteErrorCode( 0, "WinInitialize"); | 
|---|
| [32] | 1315 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1316 | return ( 0 ); | 
|---|
|  | 1317 | } | 
|---|
|  | 1318 |  | 
|---|
|  | 1319 | ulCB = PrfQueryProfileString( HINI_SYSTEMPROFILE, APPNAME_PM_PORT_DRIVER, | 
|---|
|  | 1320 | pszPdrName, NULL, (PVOID) szPathName, CCHMAXPATH ); | 
|---|
|  | 1321 | if ( !ulCB ) { | 
|---|
|  | 1322 | WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileString"); | 
|---|
| [32] | 1323 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1324 | goto cleanup; | 
|---|
|  | 1325 | } | 
|---|
|  | 1326 |  | 
|---|
|  | 1327 | // Load the port driver DLL and register its dialog routine | 
|---|
|  | 1328 | rc = DosLoadModule( NULL, 0, szPathName, &hPdr ); | 
|---|
|  | 1329 | if ( rc != NO_ERROR || !hPdr ) { | 
|---|
|  | 1330 | WriteErrorCode( rc, "DosLoadModule"); | 
|---|
| [32] | 1331 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1332 | goto cleanup; | 
|---|
|  | 1333 | } | 
|---|
|  | 1334 | rc = DosQueryProcAddr( hPdr, 0, "SPLPDSETPORT", &pfnSetPort ); | 
|---|
|  | 1335 | if ( rc != NO_ERROR ) { | 
|---|
|  | 1336 | WriteErrorCode( rc, "DosQueryProcAddr"); | 
|---|
| [32] | 1337 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1338 | goto finish; | 
|---|
|  | 1339 | } | 
|---|
|  | 1340 |  | 
|---|
|  | 1341 | // Now show the port configuration dialog | 
|---|
|  | 1342 | rc = pfnSetPort( hab, pszPortName, &flModified ); | 
|---|
|  | 1343 | if ( rc == NO_ERROR ) { | 
|---|
|  | 1344 | // Return 1 if settings were modified | 
|---|
| [32] | 1345 | SaveResultString( prsResult, flModified? PSZ_ONE: PSZ_ZERO, 1 ); | 
|---|
| [3] | 1346 | } | 
|---|
|  | 1347 | else { | 
|---|
|  | 1348 | WriteErrorCode( rc, "SplPdSetPort"); | 
|---|
| [32] | 1349 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [3] | 1350 | } | 
|---|
|  | 1351 |  | 
|---|
|  | 1352 | finish: | 
|---|
|  | 1353 | DosFreeModule( hPdr ); | 
|---|
|  | 1354 | cleanup: | 
|---|
|  | 1355 | WinTerminate( hab ); | 
|---|
|  | 1356 | return ( 0 ); | 
|---|
|  | 1357 | } | 
|---|
|  | 1358 |  | 
|---|
|  | 1359 |  | 
|---|
| [5] | 1360 | /* ------------------------------------------------------------------------- * | 
|---|
| [10] | 1361 | * RPUPortDelete                                                             * | 
|---|
|  | 1362 | *                                                                           * | 
|---|
|  | 1363 | * Deletes a printer port.                                                   * | 
|---|
|  | 1364 | *                                                                           * | 
|---|
|  | 1365 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 1366 | *   1. The name of the port to be deleted.                       (REQUIRED) * | 
|---|
|  | 1367 | *                                                                           * | 
|---|
|  | 1368 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 1369 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 1370 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1371 | ULONG APIENTRY RPUPortDelete( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 1372 | { | 
|---|
|  | 1373 | PSZ    pszPortName; | 
|---|
|  | 1374 | SPLERR rc = 0; | 
|---|
|  | 1375 |  | 
|---|
|  | 1376 |  | 
|---|
|  | 1377 | // Reset the error indicator | 
|---|
|  | 1378 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 1379 |  | 
|---|
|  | 1380 | // Make sure we have at least one valid argument (the port name) | 
|---|
|  | 1381 | if ( argc < 1  || ( !RXVALIDSTRING(argv[0]) )) return ( 40 ); | 
|---|
|  | 1382 | pszPortName = strupr( argv[0].strptr ); | 
|---|
|  | 1383 |  | 
|---|
|  | 1384 | rc = SplDeletePort( NULL, pszPortName ); | 
|---|
|  | 1385 | if ( rc == NO_ERROR ) { | 
|---|
|  | 1386 | // Return 1 on success | 
|---|
| [32] | 1387 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [10] | 1388 | } | 
|---|
|  | 1389 | else { | 
|---|
|  | 1390 | WriteErrorCode( rc, "SplDeletePort"); | 
|---|
| [32] | 1391 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [10] | 1392 | } | 
|---|
|  | 1393 |  | 
|---|
|  | 1394 | return ( 0 ); | 
|---|
|  | 1395 | } | 
|---|
|  | 1396 |  | 
|---|
|  | 1397 |  | 
|---|
|  | 1398 | /* ------------------------------------------------------------------------- * | 
|---|
| [5] | 1399 | * RPUPrinterCreate                                                          * | 
|---|
|  | 1400 | *                                                                           * | 
|---|
|  | 1401 | * Creates a new local printer object.  The associated print queue and       * | 
|---|
| [8] | 1402 | * device are created automatically.  However, the specified output port     * | 
|---|
|  | 1403 | * must exist, and the specified printer driver/model must have been         * | 
|---|
|  | 1404 | * installed already.                                                        * | 
|---|
| [5] | 1405 | *                                                                           * | 
|---|
| [8] | 1406 | * The WPS object is created with default settings, and will be assigned an  * | 
|---|
|  | 1407 | * object-ID automatically by the WPS.                                       * | 
|---|
| [5] | 1408 | *                                                                           * | 
|---|
| [8] | 1409 | * NOTE: This function will NOT create a remote (LAN) printer object.        * | 
|---|
| [5] | 1410 | *                                                                           * | 
|---|
|  | 1411 | * REXX ARGUMENTS:                                                           * | 
|---|
| [8] | 1412 | *   1. The printer description, used as the WPS object title.    (REQUIRED) * | 
|---|
|  | 1413 | *   2. The name of the underlying print queue. Must be a legal              * | 
|---|
|  | 1414 | *      queue name according to OS/2 (but what is that...?)       (REQUIRED) * | 
|---|
| [5] | 1415 | *   3. The name of the printer port, which must exist already.   (REQUIRED) * | 
|---|
|  | 1416 | *   4. The default printer driver.model to be associated with               * | 
|---|
| [8] | 1417 | *      the device. If specified, this must be installed in the              * | 
|---|
|  | 1418 | *      system already. If not specified, IBMNULL is assumed.    (OPTIONAL)  * | 
|---|
| [5] | 1419 | *                                                                           * | 
|---|
|  | 1420 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 1421 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 1422 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1423 | ULONG APIENTRY RPUPrinterCreate( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 1424 | { | 
|---|
|  | 1425 | PRDINFO3  devinfo       = {0}; | 
|---|
|  | 1426 | PRQINFO3  qinfo         = {0}; | 
|---|
|  | 1427 | PSZ       pszQueueName  = NULL, | 
|---|
|  | 1428 | pszPortName   = NULL, | 
|---|
|  | 1429 | pszModel      = NULL, | 
|---|
| [6] | 1430 | pszTitle      = NULL; | 
|---|
| [8] | 1431 | CHAR      szDevice[ US_PRTDEV_MAXZ ] = {0}; | 
|---|
| [5] | 1432 | SPLERR    rc; | 
|---|
|  | 1433 |  | 
|---|
|  | 1434 |  | 
|---|
|  | 1435 | // Reset the error indicator | 
|---|
|  | 1436 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 1437 |  | 
|---|
|  | 1438 | // Validate the REXX arguments | 
|---|
| [8] | 1439 | if (( argc < 3 ) || ( argc > 4 )  || ( ! RXVALIDSTRING( argv[0] )) || | 
|---|
| [5] | 1440 | ( ! RXVALIDSTRING( argv[1] )) || ( ! RXVALIDSTRING( argv[2] ))) | 
|---|
|  | 1441 | return ( 40 ); | 
|---|
|  | 1442 | if (( argc > 3 ) && ( ! RXVALIDSTRING( argv[3] ))) | 
|---|
|  | 1443 | return ( 40 ); | 
|---|
|  | 1444 |  | 
|---|
| [8] | 1445 | pszTitle      = argv[0].strptr; | 
|---|
|  | 1446 | pszQueueName  = argv[1].strptr; | 
|---|
| [5] | 1447 | pszPortName   = argv[2].strptr; | 
|---|
|  | 1448 | if ( argc > 3 ) pszModel = argv[3].strptr; | 
|---|
|  | 1449 |  | 
|---|
| [8] | 1450 | // Generate a suitable (unique) device name, based on the queue name | 
|---|
|  | 1451 | strncpy( szDevice, pszQueueName, US_PRTDEV_MAXZ-1 ); | 
|---|
|  | 1452 | if (( rc = UniqueDeviceName( szDevice )) != NO_ERROR ) { | 
|---|
|  | 1453 | if ( rc == 1 )      // shouldn't really happen | 
|---|
|  | 1454 | WriteErrorCode( rc, "UniqueDeviceName"); | 
|---|
|  | 1455 | else | 
|---|
|  | 1456 | WriteErrorCode( rc, "SplEnumDevice"); | 
|---|
| [32] | 1457 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [8] | 1458 | return ( 0 ); | 
|---|
|  | 1459 | } | 
|---|
| [5] | 1460 |  | 
|---|
| [8] | 1461 | // Create the device | 
|---|
|  | 1462 | devinfo.pszPrinterName = szDevice; | 
|---|
|  | 1463 | devinfo.pszUserName    = NULL; | 
|---|
|  | 1464 | devinfo.pszLogAddr     = pszPortName; | 
|---|
|  | 1465 | devinfo.pszComment     = pszTitle; | 
|---|
|  | 1466 | devinfo.pszDrivers     = pszModel ? pszModel : "IBMNULL"; | 
|---|
|  | 1467 | devinfo.usTimeOut      = 45; | 
|---|
|  | 1468 | rc = SplCreateDevice( NULL, 3, &devinfo, sizeof( devinfo )); | 
|---|
|  | 1469 | if ( rc != NO_ERROR ) { | 
|---|
|  | 1470 | WriteErrorCode( rc, "SplCreateDevice"); | 
|---|
| [32] | 1471 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [5] | 1472 | return ( 0 ); | 
|---|
|  | 1473 | } | 
|---|
|  | 1474 |  | 
|---|
| [8] | 1475 | // Create the queue (automatically creates printer object) | 
|---|
|  | 1476 | qinfo.pszName       = pszQueueName; | 
|---|
|  | 1477 | qinfo.uPriority     = PRQ_DEF_PRIORITY; | 
|---|
|  | 1478 | qinfo.fsType        = PRQ3_TYPE_RAW; | 
|---|
|  | 1479 | qinfo.pszPrProc     = "PMPRINT"; | 
|---|
|  | 1480 | qinfo.pszComment    = pszTitle; | 
|---|
|  | 1481 | qinfo.pszPrinters   = szDevice; | 
|---|
|  | 1482 | qinfo.pszDriverName = pszModel ? pszModel : "IBMNULL"; | 
|---|
|  | 1483 | rc = SplCreateQueue( NULL, 3, &qinfo, sizeof( qinfo )); | 
|---|
|  | 1484 | if ( rc != NO_ERROR ) { | 
|---|
|  | 1485 | WriteErrorCode( rc, "SplCreateQueue"); | 
|---|
| [32] | 1486 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [8] | 1487 | SplDeleteDevice( NULL, szDevice ); | 
|---|
| [5] | 1488 | return ( 0 ); | 
|---|
|  | 1489 | } | 
|---|
|  | 1490 |  | 
|---|
| [32] | 1491 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [7] | 1492 | return ( 0 ); | 
|---|
|  | 1493 | } | 
|---|
| [6] | 1494 |  | 
|---|
| [7] | 1495 |  | 
|---|
|  | 1496 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 1497 | * RPUPrinterDelete                                                          * | 
|---|
|  | 1498 | *                                                                           * | 
|---|
|  | 1499 | * Deletes a local printer queue and its associated print device definition. * | 
|---|
|  | 1500 | *                                                                           * | 
|---|
|  | 1501 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 1502 | *   1. The name of the printer queue to be deleted.              (REQUIRED) * | 
|---|
|  | 1503 | *                                                                           * | 
|---|
|  | 1504 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 1505 | *   1 on success, or 0 if an error occurred.  (1 will be returned even if   * | 
|---|
|  | 1506 | *   the WPS printer object could not be deleted, so long as the queue and   * | 
|---|
| [10] | 1507 | *   device were destroyed successfully.)                                    * | 
|---|
| [7] | 1508 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1509 | ULONG APIENTRY RPUPrinterDelete( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 1510 | { | 
|---|
|  | 1511 | PPRQINFO3 pInfo         = NULL; | 
|---|
|  | 1512 | ULONG     cbBuf         = 0; | 
|---|
|  | 1513 | PSZ       pszQueueName  = NULL, | 
|---|
|  | 1514 | pszDeviceName = NULL; | 
|---|
|  | 1515 | HOBJECT   hObj; | 
|---|
|  | 1516 | SPLERR    rc; | 
|---|
|  | 1517 |  | 
|---|
|  | 1518 |  | 
|---|
|  | 1519 | // Reset the error indicator | 
|---|
|  | 1520 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 1521 |  | 
|---|
|  | 1522 | // Validate the REXX arguments | 
|---|
|  | 1523 | if (( argc != 1 ) || ( ! RXVALIDSTRING( argv[0] ))) | 
|---|
|  | 1524 | return ( 40 ); | 
|---|
|  | 1525 |  | 
|---|
|  | 1526 | pszQueueName = argv[0].strptr; | 
|---|
|  | 1527 | hObj = PrinterObjectHandle( pszQueueName ); | 
|---|
|  | 1528 |  | 
|---|
|  | 1529 | rc = SplQueryQueue( NULL, pszQueueName, 3, NULL, 0, &cbBuf ); | 
|---|
|  | 1530 | if (( rc != NO_ERROR ) && ( rc != NERR_BufTooSmall )) { | 
|---|
|  | 1531 | WriteErrorCode( rc, "SplQueryQueue"); | 
|---|
| [32] | 1532 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [7] | 1533 | return ( 0 ); | 
|---|
| [6] | 1534 | } | 
|---|
| [7] | 1535 | pInfo = (PPRQINFO3) malloc( cbBuf ); | 
|---|
|  | 1536 | if ( !pInfo ) { | 
|---|
|  | 1537 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 1538 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [5] | 1539 | return ( 0 ); | 
|---|
|  | 1540 | } | 
|---|
| [7] | 1541 | rc = SplQueryQueue( NULL, pszQueueName, 3, pInfo, cbBuf, &cbBuf ); | 
|---|
|  | 1542 | if ( rc != NO_ERROR ) { | 
|---|
|  | 1543 | WriteErrorCode( rc, "SplQueryQueue"); | 
|---|
| [32] | 1544 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [7] | 1545 | goto cleanup; | 
|---|
|  | 1546 | } | 
|---|
|  | 1547 | pszDeviceName = strtok( pInfo->pszPrinters, ","); | 
|---|
|  | 1548 | rc = SplDeleteDevice( NULL, pszDeviceName ); | 
|---|
|  | 1549 | if ( rc != NO_ERROR ) { | 
|---|
|  | 1550 | WriteErrorCode( rc, "SplDeleteDevice"); | 
|---|
| [32] | 1551 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [7] | 1552 | goto cleanup; | 
|---|
|  | 1553 | } | 
|---|
|  | 1554 |  | 
|---|
|  | 1555 | // Try and destroy the WPS object | 
|---|
| [13] | 1556 | //  - NB This causes a long delay when deleting an offline LAN printer | 
|---|
| [7] | 1557 | if ( hObj != NULLHANDLE ) WinDestroyObject( hObj ); | 
|---|
|  | 1558 |  | 
|---|
| [32] | 1559 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [7] | 1560 | cleanup: | 
|---|
|  | 1561 | free( pInfo ); | 
|---|
| [5] | 1562 | return ( 0 ); | 
|---|
|  | 1563 | } | 
|---|
|  | 1564 |  | 
|---|
|  | 1565 |  | 
|---|
|  | 1566 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 1567 | * RPUPrinterQuery                                                           * | 
|---|
|  | 1568 | *                                                                           * | 
|---|
|  | 1569 | * Gets information about the specified printer device.                      * | 
|---|
|  | 1570 | *                                                                           * | 
|---|
| [15] | 1571 | *   (stem).!description  Printer description (name of WPS object)           * | 
|---|
|  | 1572 | *   (stem).!port         Name of the port the printer is using              * | 
|---|
|  | 1573 | *   (stem).!driver2      List of the drivers used by this printer           * | 
|---|
|  | 1574 | *   (stem).!jobflags     Zero or more of the following flags (any order):   * | 
|---|
| [5] | 1575 | *                            E  A printer error has occurred                * | 
|---|
| [12] | 1576 | *                            H  Printer destination is paused (held)        * | 
|---|
| [5] | 1577 | *                            I  Intervention required                       * | 
|---|
|  | 1578 | *                            N  Printer has raised a notification alert     * | 
|---|
|  | 1579 | *                            O  Printer is offline                          * | 
|---|
|  | 1580 | *                            P  Printer is out of paper                     * | 
|---|
|  | 1581 | *                                                                           * | 
|---|
|  | 1582 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 1583 | *   1. The name of the printer device being queried.             (REQUIRED) * | 
|---|
|  | 1584 | *   2. The name of the stem in which to return the results.      (REQUIRED) * | 
|---|
|  | 1585 | *                                                                           * | 
|---|
|  | 1586 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 1587 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 1588 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1589 | ULONG APIENTRY RPUPrinterQuery( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 1590 | { | 
|---|
|  | 1591 | PPRDINFO3 pInfo      = NULL; | 
|---|
|  | 1592 | PVOID     pbuf       = NULL; | 
|---|
|  | 1593 | ULONG     cbBuf      = 0, | 
|---|
|  | 1594 | cbNeeded   = 0; | 
|---|
|  | 1595 | PSZ       pszDeviceName; | 
|---|
| [12] | 1596 | CHAR      szFlags[ 8 ] = {0}, | 
|---|
|  | 1597 | szStem[ US_STEM_MAXZ ];   // compound variable stem name | 
|---|
| [5] | 1598 | SPLERR    rc; | 
|---|
|  | 1599 |  | 
|---|
|  | 1600 |  | 
|---|
|  | 1601 | // Reset the error indicator | 
|---|
|  | 1602 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 1603 |  | 
|---|
|  | 1604 | // Validate the REXX arguments | 
|---|
|  | 1605 | if (( argc != 2 ) || | 
|---|
|  | 1606 | ( ! RXVALIDSTRING( argv[0] )) || ( ! RXVALIDSTRING( argv[1] ))) | 
|---|
|  | 1607 | return ( 40 ); | 
|---|
|  | 1608 |  | 
|---|
|  | 1609 | pszDeviceName = argv[0].strptr; | 
|---|
|  | 1610 |  | 
|---|
|  | 1611 | // Initialize the result stem name | 
|---|
|  | 1612 | if ( RXSTRLEN(argv[1]) > US_STEM_MAXZ ) return ( 40 ); | 
|---|
|  | 1613 | if ( argv[1].strptr[ argv[1].strlength-1 ] == '.') argv[1].strlength--; | 
|---|
|  | 1614 | strncpy( szStem, argv[1].strptr, RXSTRLEN( argv[1] )); | 
|---|
|  | 1615 | szStem[ RXSTRLEN( argv[1] ) ] = '\0'; | 
|---|
|  | 1616 |  | 
|---|
|  | 1617 |  | 
|---|
|  | 1618 | // Query the amount of available data | 
|---|
|  | 1619 | rc = SplQueryDevice( NULL, pszDeviceName, 3L, NULL, 0L, &cbNeeded ); | 
|---|
|  | 1620 | if (( rc != ERROR_MORE_DATA ) && ( rc != NERR_BufTooSmall )) | 
|---|
|  | 1621 | { | 
|---|
|  | 1622 | WriteErrorCode( rc, "SplQueryDevice"); | 
|---|
| [32] | 1623 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [5] | 1624 | return ( 0 ); | 
|---|
|  | 1625 | } | 
|---|
|  | 1626 |  | 
|---|
|  | 1627 | // Now get the actual data | 
|---|
|  | 1628 | pbuf = malloc( cbNeeded ); | 
|---|
|  | 1629 | if ( !pbuf ) { | 
|---|
|  | 1630 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
| [32] | 1631 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [5] | 1632 | return ( 0 ); | 
|---|
|  | 1633 | } | 
|---|
|  | 1634 | cbBuf = cbNeeded; | 
|---|
|  | 1635 | rc = SplQueryDevice( NULL, pszDeviceName, 3L, pbuf, cbBuf, &cbNeeded ); | 
|---|
|  | 1636 | if ( rc == NO_ERROR ) { | 
|---|
|  | 1637 | pInfo = (PPRDINFO3) pbuf; | 
|---|
|  | 1638 | WriteCompoundVariable( szStem, "!name", pInfo->pszPrinterName ); | 
|---|
|  | 1639 | WriteCompoundVariable( szStem, "!port", pInfo->pszLogAddr ); | 
|---|
|  | 1640 | WriteCompoundVariable( szStem, "!description", pInfo->pszComment ); | 
|---|
|  | 1641 | WriteCompoundVariable( szStem, "!drivers", pInfo->pszDrivers ); | 
|---|
| [12] | 1642 | if ( pInfo->fsStatus & PRJ_ERROR  )      strcat( szFlags, "E"); | 
|---|
|  | 1643 | if ( pInfo->fsStatus & PRJ_DESTPAUSED )  strcat( szFlags, "H"); | 
|---|
|  | 1644 | if ( pInfo->fsStatus & PRJ_INTERV )      strcat( szFlags, "I"); | 
|---|
|  | 1645 | if ( pInfo->fsStatus & PRJ_NOTIFY )      strcat( szFlags, "N"); | 
|---|
|  | 1646 | if ( pInfo->fsStatus & PRJ_DESTOFFLINE ) strcat( szFlags, "O"); | 
|---|
|  | 1647 | if ( pInfo->fsStatus & PRJ_DESTNOPAPER ) strcat( szFlags, "P"); | 
|---|
|  | 1648 | WriteCompoundVariable( szStem, "!jobflags", szFlags ); | 
|---|
| [32] | 1649 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [5] | 1650 | } | 
|---|
|  | 1651 | else { | 
|---|
|  | 1652 | WriteErrorCode( rc, "SplQueryDevice"); | 
|---|
| [32] | 1653 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [5] | 1654 | } | 
|---|
|  | 1655 |  | 
|---|
|  | 1656 | free( pbuf ); | 
|---|
|  | 1657 | return ( 0 ); | 
|---|
|  | 1658 | } | 
|---|
|  | 1659 |  | 
|---|
|  | 1660 |  | 
|---|
|  | 1661 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 1662 | * RPUQueueDefault                                                           * | 
|---|
|  | 1663 | *                                                                           * | 
|---|
|  | 1664 | * Sets the requested printer queue as the system default printer.           * | 
|---|
|  | 1665 | *                                                                           * | 
|---|
|  | 1666 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 1667 | *   1. The name of the printer queue to set as default. (REQUIRED)          * | 
|---|
|  | 1668 | *                                                                           * | 
|---|
|  | 1669 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 1670 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 1671 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1672 | ULONG APIENTRY RPUQueueDefault( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 1673 | { | 
|---|
|  | 1674 | HOBJECT hObj; | 
|---|
|  | 1675 | BOOL    fRC; | 
|---|
|  | 1676 |  | 
|---|
|  | 1677 | // Reset the error indicator | 
|---|
|  | 1678 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 1679 |  | 
|---|
|  | 1680 | // Make sure we have at least one valid argument (the queue name) | 
|---|
|  | 1681 | if ( argc != 1  || ( !RXVALIDSTRING(argv[0]) )) return ( 40 ); | 
|---|
|  | 1682 | pszName = argv[0].strptr; | 
|---|
|  | 1683 |  | 
|---|
|  | 1684 | hObj = PrinterObjectHandle( pszName ); | 
|---|
|  | 1685 | if ( !hObj ) return ( 40 ); | 
|---|
|  | 1686 |  | 
|---|
|  | 1687 | fRC = WinSetObjectData( hObj, "APPDEFAULT=YES;"); | 
|---|
|  | 1688 |  | 
|---|
| [32] | 1689 | SaveResultString( prsResult, fRC? PSZ_ONE: PSZ_ZERO, 1 ); | 
|---|
| [5] | 1690 | return ( 0 ); | 
|---|
|  | 1691 | } | 
|---|
|  | 1692 |  | 
|---|
|  | 1693 |  | 
|---|
|  | 1694 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 1695 | * RPUQueueHold                                                              * | 
|---|
|  | 1696 | *                                                                           * | 
|---|
|  | 1697 | * Holds or releases the specified print queue.                              * | 
|---|
|  | 1698 | *                                                                           * | 
|---|
|  | 1699 | * REXX ARGUMENTS:                                                           * | 
|---|
|  | 1700 | *   1. The name of the printer queue to hold or release. (REQUIRED)         * | 
|---|
|  | 1701 | *   2. Action flag, one of:                                                 * | 
|---|
|  | 1702 | *        Y  Hold printer (DEFAULT)                                          * | 
|---|
|  | 1703 | *        N  Release printer                                                 * | 
|---|
|  | 1704 | *                                                                           * | 
|---|
|  | 1705 | * REXX RETURN VALUE:                                                        * | 
|---|
|  | 1706 | *   1 on success, or 0 if an error occurred.                                * | 
|---|
|  | 1707 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1708 | ULONG APIENTRY RPUQueueHold( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) | 
|---|
|  | 1709 | { | 
|---|
|  | 1710 | PSZ    pszQueueName;           // Print queue name | 
|---|
|  | 1711 | BOOL   fHold = TRUE; | 
|---|
|  | 1712 | SPLERR rc; | 
|---|
|  | 1713 |  | 
|---|
|  | 1714 |  | 
|---|
|  | 1715 | // Reset the error indicator | 
|---|
|  | 1716 | WriteErrorCode( 0, NULL ); | 
|---|
|  | 1717 |  | 
|---|
|  | 1718 | // Make sure we have at least one valid argument (the queue name) | 
|---|
|  | 1719 | if ( argc < 1 || argc > 2 || ( !RXVALIDSTRING(argv[0]) )) return ( 40 ); | 
|---|
|  | 1720 | pszQueueName = argv[0].strptr; | 
|---|
|  | 1721 |  | 
|---|
|  | 1722 | // Second argument: view (optional, but must be correct if specified) | 
|---|
|  | 1723 | if ( argc == 2 ) { | 
|---|
|  | 1724 | if ( RXVALIDSTRING(argv[1]) ) { | 
|---|
|  | 1725 | switch ( argv[1].strptr[0] ) { | 
|---|
|  | 1726 | case 'y': | 
|---|
|  | 1727 | case 'Y': fHold = TRUE;  break; | 
|---|
|  | 1728 | case 'n': | 
|---|
|  | 1729 | case 'N': fHold = FALSE; break; | 
|---|
|  | 1730 | default : return ( 40 ); | 
|---|
|  | 1731 | } | 
|---|
|  | 1732 | } | 
|---|
|  | 1733 | else return ( 40 ); | 
|---|
|  | 1734 | } | 
|---|
|  | 1735 |  | 
|---|
|  | 1736 | rc = fHold ? SplHoldQueue( NULL, pszQueueName ) : | 
|---|
|  | 1737 | SplReleaseQueue( NULL, pszQueueName ); | 
|---|
|  | 1738 | if ( rc != NO_ERROR ) { | 
|---|
|  | 1739 | WriteErrorCode( rc, fHold ? "SplHoldQueue" : "SplReleaseQueue"); | 
|---|
| [32] | 1740 | SaveResultString( prsResult, PSZ_ZERO, 1 ); | 
|---|
| [5] | 1741 | } | 
|---|
| [32] | 1742 | else | 
|---|
|  | 1743 | SaveResultString( prsResult, PSZ_ONE, 1 ); | 
|---|
| [5] | 1744 |  | 
|---|
|  | 1745 | return ( 0 ); | 
|---|
|  | 1746 | } | 
|---|
|  | 1747 |  | 
|---|
|  | 1748 |  | 
|---|
| [3] | 1749 | /* ************************************************************************* * | 
|---|
|  | 1750 | * INTERNAL PRINTER-RELATED FUNCTIONS                                        * | 
|---|
|  | 1751 | * ************************************************************************* */ | 
|---|
|  | 1752 |  | 
|---|
|  | 1753 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 1754 | * PrinterObjectHandle                                                       * | 
|---|
|  | 1755 | *                                                                           * | 
|---|
|  | 1756 | * Given a print queue name, obtain the handle to the WPS printer object     * | 
|---|
|  | 1757 | * associated with that queue.  This is done by querying OS2.INI for the     * | 
|---|
|  | 1758 | * queues defined in PM_PrintObject and reading the associated handle IDs.   * | 
|---|
|  | 1759 | *                                                                           * | 
|---|
|  | 1760 | * ARGUMENTS:                                                                * | 
|---|
|  | 1761 | *   PSZ pszQueueName: The printer queue name.  This is NOT the same as the  * | 
|---|
|  | 1762 | *                     printer device name, although in many cases they may  * | 
|---|
|  | 1763 | *                     have the same value.                                  * | 
|---|
|  | 1764 | *                                                                           * | 
|---|
|  | 1765 | * RETURNS: HOBJECT                                                          * | 
|---|
|  | 1766 | *   WPS object handle of the printer object; NULLHANDLE if no object was    * | 
|---|
|  | 1767 | *   found or an error occurred.                                             * | 
|---|
|  | 1768 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1769 | HOBJECT PrinterObjectHandle( PSZ pszQueueName ) | 
|---|
|  | 1770 | { | 
|---|
| [11] | 1771 | PVOID   pbuf = NULL, | 
|---|
|  | 1772 | pdata = NULL; | 
|---|
|  | 1773 | PBYTE   pb, | 
|---|
|  | 1774 | pbEnd, | 
|---|
|  | 1775 | pbGrpEnd; | 
|---|
|  | 1776 | POBJINFO pInfo = NULL; | 
|---|
|  | 1777 | POITAG   pTag = NULL; | 
|---|
|  | 1778 | PSZ     psz, | 
|---|
|  | 1779 | pszName; | 
|---|
|  | 1780 | CHAR    szValue[ 256 ], | 
|---|
|  | 1781 | szObject[ 5 ]; | 
|---|
| [3] | 1782 | ULONG   cbTotal  = 0, | 
|---|
| [11] | 1783 | cbActual = 0, | 
|---|
|  | 1784 | ulHandle; | 
|---|
|  | 1785 | HOBJECT hObj = 0; | 
|---|
|  | 1786 | BOOL    fFound, | 
|---|
|  | 1787 | fRC; | 
|---|
| [3] | 1788 |  | 
|---|
|  | 1789 |  | 
|---|
|  | 1790 | fRC = PrfQueryProfileSize( HINI_USERPROFILE, | 
|---|
|  | 1791 | APPNAME_PM_PRINT_OBJECT, NULL, &cbTotal ); | 
|---|
|  | 1792 | if ( !fRC || !cbTotal ) { | 
|---|
|  | 1793 | //WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileSize"); | 
|---|
|  | 1794 | return NULLHANDLE; | 
|---|
|  | 1795 | } | 
|---|
|  | 1796 | pbuf = malloc( cbTotal ); | 
|---|
|  | 1797 | if ( !pbuf ) { | 
|---|
|  | 1798 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
|  | 1799 | return NULLHANDLE; | 
|---|
|  | 1800 | } | 
|---|
|  | 1801 |  | 
|---|
|  | 1802 | cbActual = PrfQueryProfileString( HINI_USERPROFILE, APPNAME_PM_PRINT_OBJECT, | 
|---|
|  | 1803 | NULL, NULL, pbuf, cbTotal ); | 
|---|
|  | 1804 | if ( !cbActual ) { | 
|---|
|  | 1805 | //WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileString"); | 
|---|
|  | 1806 | return NULLHANDLE; | 
|---|
|  | 1807 | } | 
|---|
|  | 1808 |  | 
|---|
| [11] | 1809 | fFound = FALSE; | 
|---|
| [3] | 1810 | psz = (PSZ) pbuf; | 
|---|
| [11] | 1811 | while ( *psz && !fFound ) { | 
|---|
|  | 1812 | #if 1 | 
|---|
|  | 1813 |  | 
|---|
|  | 1814 | /* Just checking the queue names associated with the handle in | 
|---|
|  | 1815 | * PM_PrintObject is not reliable, because remote (LAN) printers | 
|---|
|  | 1816 | * will store the name of the _remote_ queue there (which is not | 
|---|
|  | 1817 | * only impossible to map to a local queue name, it may actually | 
|---|
|  | 1818 | * be the same AS a local queue name... for a different printer). | 
|---|
|  | 1819 | * | 
|---|
|  | 1820 | * So what we do here is parse the queue name out of the object | 
|---|
|  | 1821 | * settings (from PM_Abstract:Objects).  We also have to handle | 
|---|
|  | 1822 | * remote printers slightly differently from local ones. | 
|---|
|  | 1823 | * | 
|---|
|  | 1824 | * I am indebted to Henk Kelder's WPTOOLS source code for providing | 
|---|
|  | 1825 | * the basic logic, although the code below is largely original. | 
|---|
|  | 1826 | */ | 
|---|
|  | 1827 |  | 
|---|
|  | 1828 | if ( sscanf( psz, "%u", &ulHandle ) && LOUSHORT( ulHandle )) { | 
|---|
|  | 1829 | sprintf( szObject, "%X", LOUSHORT( ulHandle )); | 
|---|
|  | 1830 | fRC = PrfQueryProfileSize( HINI_USERPROFILE, APPNAME_PM_ABS_OBJECTS, | 
|---|
|  | 1831 | szObject, &cbTotal ); | 
|---|
|  | 1832 | if ( !fRC || ( cbTotal < 25 ) || ((pdata = malloc( cbTotal )) == NULL )) { | 
|---|
|  | 1833 | psz += strlen( psz ) + 1; | 
|---|
|  | 1834 | continue; | 
|---|
|  | 1835 | } | 
|---|
|  | 1836 | if ( PrfQueryProfileData( HINI_USERPROFILE, APPNAME_PM_ABS_OBJECTS, | 
|---|
|  | 1837 | szObject, (PVOID) pdata, &cbTotal )) | 
|---|
|  | 1838 | { | 
|---|
|  | 1839 | BOOL fRemote; | 
|---|
|  | 1840 | pbEnd = (PBYTE) pdata + cbTotal; | 
|---|
|  | 1841 | pszName = (PSZ) pdata + sizeof( ULONG ); | 
|---|
|  | 1842 | fRemote = strcmp( pszName, "WPRPrinter") ? FALSE : TRUE; | 
|---|
|  | 1843 | pb = (PBYTE) pszName + strlen( pszName ) + 17; | 
|---|
|  | 1844 | while (( pb < pbEnd ) && !fFound ) { | 
|---|
|  | 1845 | pInfo = (POBJINFO) pb; | 
|---|
|  | 1846 | pb += sizeof( OBJINFO ) + strlen( pInfo->szName ); | 
|---|
|  | 1847 | pbGrpEnd = pb + pInfo->cbData; | 
|---|
|  | 1848 | if ( pbGrpEnd > pbEnd ) pbGrpEnd = pbEnd; | 
|---|
|  | 1849 | while (( pb < pbGrpEnd ) && !fFound ) { | 
|---|
|  | 1850 | pTag = (POITAG) pb; | 
|---|
|  | 1851 | pb += sizeof( OITAG ); | 
|---|
|  | 1852 | /* For network printers, tag ID 3 indicates the name of | 
|---|
|  | 1853 | * the queue on the remote server.  We want the local | 
|---|
|  | 1854 | * queue name, which has tag ID 13. | 
|---|
|  | 1855 | */ | 
|---|
|  | 1856 | if ( fRemote && ( pTag->usTag == ID_OBJINFO_RPQUEUENAME )) { | 
|---|
|  | 1857 | memcpy( szValue, pb, pTag->cbTag ); | 
|---|
|  | 1858 | if ( !strcmp( szValue, pszQueueName )) { | 
|---|
|  | 1859 | hObj = (HOBJECT) ulHandle; | 
|---|
|  | 1860 | fFound = TRUE; | 
|---|
|  | 1861 | } | 
|---|
|  | 1862 | } | 
|---|
|  | 1863 | // For local printers, just look for tag ID 3 | 
|---|
|  | 1864 | else if ( pTag->usTag == ID_OBJINFO_QUEUENAME ) { | 
|---|
|  | 1865 | memcpy( szValue, pb, pTag->cbTag ); | 
|---|
|  | 1866 | if ( !strcmp( szValue, pszQueueName )) { | 
|---|
|  | 1867 | hObj = (HOBJECT) ulHandle; | 
|---|
|  | 1868 | fFound = TRUE; | 
|---|
|  | 1869 | } | 
|---|
|  | 1870 | } | 
|---|
|  | 1871 | pb += pTag->cbTag; | 
|---|
|  | 1872 | } | 
|---|
|  | 1873 | } | 
|---|
|  | 1874 | } | 
|---|
|  | 1875 | free( pdata ); | 
|---|
|  | 1876 | } | 
|---|
|  | 1877 | #else | 
|---|
|  | 1878 | /* Old method, do not use (unreliable for the reasons noted above). | 
|---|
|  | 1879 | */ | 
|---|
| [3] | 1880 | if ( !PrfQueryProfileString( HINI_USERPROFILE, APPNAME_PM_PRINT_OBJECT, | 
|---|
|  | 1881 | psz, NULL, szValue, 255 )) | 
|---|
|  | 1882 | { | 
|---|
|  | 1883 | //WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileString"); | 
|---|
|  | 1884 | break; | 
|---|
|  | 1885 | } | 
|---|
|  | 1886 | if (( strcmp( szValue, pszQueueName ) == 0 ) && | 
|---|
|  | 1887 | ( sscanf( psz, "%u", (PULONG) &hObj ) == 1 )) | 
|---|
|  | 1888 | { | 
|---|
| [11] | 1889 | fFound = TRUE; | 
|---|
| [3] | 1890 | break; | 
|---|
|  | 1891 | } | 
|---|
| [11] | 1892 | #endif | 
|---|
| [3] | 1893 | psz += strlen( psz ) + 1; | 
|---|
|  | 1894 | } | 
|---|
|  | 1895 |  | 
|---|
|  | 1896 | free ( pbuf ); | 
|---|
|  | 1897 | return ( hObj ); | 
|---|
|  | 1898 | } | 
|---|
|  | 1899 |  | 
|---|
|  | 1900 |  | 
|---|
|  | 1901 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 1902 | * GetObjectID                                                               * | 
|---|
|  | 1903 | *                                                                           * | 
|---|
|  | 1904 | * Given a WPS object handle, find out the corresponding object ID if one    * | 
|---|
|  | 1905 | * exists.                                                                   * | 
|---|
|  | 1906 | *                                                                           * | 
|---|
|  | 1907 | * ARGUMENTS:                                                                * | 
|---|
|  | 1908 | *   PSZ pszHandle: The WPS object handle, as a hexadecimal string.  This    * | 
|---|
|  | 1909 | *                  should have no prefix, and be all upper-case.            * | 
|---|
|  | 1910 | *                                                                           * | 
|---|
|  | 1911 | * RETURNS: PSZ                                                              * | 
|---|
|  | 1912 | *   The object ID string.  It is up to the caller to free it when done.     * | 
|---|
|  | 1913 | *   This will be NULL if no object ID was found.                            * | 
|---|
|  | 1914 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1915 | PSZ GetObjectID( PSZ pszHandle ) | 
|---|
|  | 1916 | { | 
|---|
|  | 1917 | PVOID   pbuf = NULL; | 
|---|
|  | 1918 | ULONG   cbTotal  = 0, | 
|---|
|  | 1919 | cbActual = 0; | 
|---|
|  | 1920 | CHAR    szValue[ 9 ]; | 
|---|
|  | 1921 | PSZ     psz, | 
|---|
|  | 1922 | pszObjID = NULL; | 
|---|
|  | 1923 | BOOL    fRC; | 
|---|
|  | 1924 |  | 
|---|
|  | 1925 |  | 
|---|
|  | 1926 | fRC = PrfQueryProfileSize( HINI_USERPROFILE, | 
|---|
|  | 1927 | APPNAME_PM_WPS_LOCATION, NULL, &cbTotal ); | 
|---|
|  | 1928 | if ( !fRC || !cbTotal ) { | 
|---|
|  | 1929 | //WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileSize"); | 
|---|
|  | 1930 | return NULL; | 
|---|
|  | 1931 | } | 
|---|
|  | 1932 | pbuf = malloc( cbTotal ); | 
|---|
|  | 1933 | if ( !pbuf ) { | 
|---|
|  | 1934 | WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "malloc"); | 
|---|
|  | 1935 | return NULL; | 
|---|
|  | 1936 | } | 
|---|
|  | 1937 |  | 
|---|
|  | 1938 | cbActual = PrfQueryProfileString( HINI_USERPROFILE, APPNAME_PM_WPS_LOCATION, | 
|---|
|  | 1939 | NULL, NULL, pbuf, cbTotal ); | 
|---|
|  | 1940 | if ( !cbActual ) { | 
|---|
|  | 1941 | //WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileString"); | 
|---|
|  | 1942 | return NULL; | 
|---|
|  | 1943 | } | 
|---|
|  | 1944 |  | 
|---|
|  | 1945 | psz = (PSZ) pbuf; | 
|---|
|  | 1946 | while ( *psz ) { | 
|---|
|  | 1947 | if ( !PrfQueryProfileString( HINI_USERPROFILE, APPNAME_PM_WPS_LOCATION, | 
|---|
|  | 1948 | psz, NULL, szValue, 8 )) | 
|---|
|  | 1949 | { | 
|---|
|  | 1950 | //WriteErrorCode( ERRORIDERROR( WinGetLastError( hab )), "PrfQueryProfileString"); | 
|---|
|  | 1951 | break; | 
|---|
|  | 1952 | } | 
|---|
|  | 1953 | if (( strcmp( szValue, pszHandle ) == 0 ) && | 
|---|
|  | 1954 | (( pszObjID = strdup( psz )) != NULL )) | 
|---|
|  | 1955 | { | 
|---|
|  | 1956 | break; | 
|---|
|  | 1957 | } | 
|---|
|  | 1958 | psz += strlen( psz ) + 1; | 
|---|
|  | 1959 | } | 
|---|
|  | 1960 |  | 
|---|
|  | 1961 | free ( pbuf ); | 
|---|
|  | 1962 | return ( pszObjID ); | 
|---|
|  | 1963 | } | 
|---|
|  | 1964 |  | 
|---|
|  | 1965 |  | 
|---|
| [8] | 1966 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 1967 | * UniqueDeviceName                                                          * | 
|---|
|  | 1968 | *                                                                           * | 
|---|
|  | 1969 | * Check (and, if necessary, modify) the specified print device name to make * | 
|---|
|  | 1970 | * sure it is unique.                                                        * | 
|---|
|  | 1971 | *                                                                           * | 
|---|
|  | 1972 | * ARGUMENTS:                                                                * | 
|---|
|  | 1973 | *   PSZ pszName : Pointer to device name buffer (9-byte CHAR buffer)        * | 
|---|
|  | 1974 | *                                                                           * | 
|---|
|  | 1975 | * RETURNS: ULONG                                                            * | 
|---|
|  | 1976 | *   0 on success, 1 if no unique name could be generated, or the return     * | 
|---|
|  | 1977 | *   code from SplEnumDevice() if an error occurred.                         * | 
|---|
|  | 1978 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 1979 | ULONG UniqueDeviceName( PSZ pszName ) | 
|---|
|  | 1980 | { | 
|---|
|  | 1981 | PBYTE     pBuf; | 
|---|
|  | 1982 | PPRDINFO3 pprd3; | 
|---|
|  | 1983 | CHAR      szNumber[ US_PRTDEV_MAXZ ] = {0}; | 
|---|
|  | 1984 | ULONG     i, n, pos, | 
|---|
|  | 1985 | ulNumber  = 0, | 
|---|
|  | 1986 | ulAvail   = 0, | 
|---|
|  | 1987 | cbBuf     = 0; | 
|---|
|  | 1988 | BOOL      fUnique   = FALSE; | 
|---|
|  | 1989 | SPLERR    rc; | 
|---|
|  | 1990 |  | 
|---|
|  | 1991 |  | 
|---|
|  | 1992 | rc = SplEnumDevice( NULL, 3, NULL, 0, &ulNumber, &ulAvail, &cbBuf, NULL ); | 
|---|
|  | 1993 | if ( rc == ERROR_MORE_DATA || rc == NERR_BufTooSmall ) { | 
|---|
|  | 1994 | pBuf = malloc( cbBuf ); | 
|---|
|  | 1995 | if ( pBuf ) { | 
|---|
|  | 1996 | rc = SplEnumDevice( NULL, 3, pBuf, cbBuf, &ulNumber, &ulAvail, &cbBuf, NULL ); | 
|---|
|  | 1997 | if ( rc == NO_ERROR ) { | 
|---|
|  | 1998 | n = 1; | 
|---|
|  | 1999 | while ( !fUnique && ( n < 999 )) {     // max 999 as a sanity check | 
|---|
|  | 2000 | for ( i = 0; i < ulNumber; i++ )  { | 
|---|
|  | 2001 | pprd3 = (PPRDINFO3) pBuf + i; | 
|---|
|  | 2002 | if ( stricmp( pszName, pprd3->pszPrinterName ) == 0 ) break; | 
|---|
|  | 2003 | } | 
|---|
|  | 2004 | if ( i >= ulNumber ) fUnique = TRUE; | 
|---|
|  | 2005 | else { | 
|---|
|  | 2006 | sprintf( szNumber, "%u", n++ ); | 
|---|
|  | 2007 | pos = strlen( pszName ) - strlen( szNumber ); | 
|---|
|  | 2008 | pszName[ pos ] = '\0'; | 
|---|
|  | 2009 | strncat( pszName, szNumber, US_PRTDEV_MAXZ-1 ); | 
|---|
|  | 2010 | } | 
|---|
|  | 2011 | } | 
|---|
|  | 2012 | } | 
|---|
|  | 2013 | free( pBuf ); | 
|---|
| [9] | 2014 | if ( rc == NO_ERROR && !fUnique ) return 1; | 
|---|
| [8] | 2015 | } | 
|---|
|  | 2016 | } | 
|---|
| [9] | 2017 | else if ( rc == NO_ERROR ) fUnique = TRUE; | 
|---|
|  | 2018 | return rc; | 
|---|
| [8] | 2019 | } | 
|---|
|  | 2020 |  | 
|---|
|  | 2021 |  | 
|---|
| [3] | 2022 | /* ************************************************************************* * | 
|---|
|  | 2023 | * INTERNAL REXX DLL UTILITY FUNCTIONS                                       * | 
|---|
|  | 2024 | * ************************************************************************* */ | 
|---|
|  | 2025 |  | 
|---|
| [32] | 2026 | #ifdef NO_SHARED_SOURCE | 
|---|
| [3] | 2027 |  | 
|---|
|  | 2028 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 2029 | * SaveResultString                                                          * | 
|---|
|  | 2030 | *                                                                           * | 
|---|
|  | 2031 | * Writes new string contents to the specified RXSTRING, allocating any      * | 
|---|
|  | 2032 | * additional memory that may be required.  If the string to be written has  * | 
|---|
|  | 2033 | * zero length, nothing is done.                                             * | 
|---|
|  | 2034 | *                                                                           * | 
|---|
| [32] | 2035 | * This function should be used in place of MAKERXSTRING to generate all     * | 
|---|
|  | 2036 | * REXX return values.                                                       * | 
|---|
| [3] | 2037 | *                                                                           * | 
|---|
|  | 2038 | * ARGUMENTS:                                                                * | 
|---|
|  | 2039 | *   PRXSTRING prsResult: Pointer to an existing RXSTRING for writing.       * | 
|---|
|  | 2040 | *   PCH       pchBytes : The string contents to write to prsResult.         * | 
|---|
|  | 2041 | *   ULONG     ulBytes  : The number of bytes in pchBytes to write.          * | 
|---|
|  | 2042 | *                                                                           * | 
|---|
|  | 2043 | * RETURNS: BOOL                                                             * | 
|---|
|  | 2044 | *   TRUE if prsResult was successfully updated.  FALSE otherwise.           * | 
|---|
|  | 2045 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 2046 | BOOL SaveResultString( PRXSTRING prsResult, PCH pchBytes, ULONG ulBytes ) | 
|---|
|  | 2047 | { | 
|---|
|  | 2048 | ULONG ulRC; | 
|---|
|  | 2049 | PCH   pchNew; | 
|---|
|  | 2050 |  | 
|---|
|  | 2051 | if ( ulBytes == 0 ) return ( FALSE ); | 
|---|
|  | 2052 | if ( ulBytes > 256 ) { | 
|---|
|  | 2053 | // REXX provides 256 bytes by default; allocate more if necessary | 
|---|
|  | 2054 | ulRC = DosAllocMem( (PVOID) &pchNew, ulBytes, PAG_WRITE | PAG_COMMIT ); | 
|---|
|  | 2055 | if ( ulRC != 0 ) { | 
|---|
|  | 2056 | WriteErrorCode( ulRC, "DosAllocMem"); | 
|---|
|  | 2057 | return ( FALSE ); | 
|---|
|  | 2058 | } | 
|---|
|  | 2059 | prsResult->strptr = pchNew; | 
|---|
|  | 2060 | } | 
|---|
|  | 2061 | memcpy( prsResult->strptr, pchBytes, ulBytes ); | 
|---|
|  | 2062 | prsResult->strlength = ulBytes; | 
|---|
|  | 2063 |  | 
|---|
|  | 2064 | return ( TRUE ); | 
|---|
|  | 2065 | } | 
|---|
|  | 2066 |  | 
|---|
|  | 2067 |  | 
|---|
|  | 2068 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 2069 | * WriteStemElement                                                          * | 
|---|
|  | 2070 | *                                                                           * | 
|---|
|  | 2071 | * Creates a stem element (compound variable) in the calling REXX program    * | 
|---|
|  | 2072 | * using the REXX shared variable pool interface.                            * | 
|---|
|  | 2073 | *                                                                           * | 
|---|
|  | 2074 | * ARGUMENTS:                                                                * | 
|---|
|  | 2075 | *   PSZ   pszStem  : The name of the stem (before the '.')                  * | 
|---|
|  | 2076 | *   ULONG ulIndex  : The number of the stem element (after the '.')         * | 
|---|
|  | 2077 | *   PSZ   pszValue : The value to write to the compound variable.           * | 
|---|
|  | 2078 | *                                                                           * | 
|---|
|  | 2079 | * RETURNS: BOOL                                                             * | 
|---|
|  | 2080 | *   TRUE on success, FALSE on failure.                                      * | 
|---|
|  | 2081 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 2082 | BOOL WriteStemElement( PSZ pszStem, ULONG ulIndex, PSZ pszValue ) | 
|---|
|  | 2083 | { | 
|---|
|  | 2084 | SHVBLOCK shvVar;                   // REXX shared variable pool block | 
|---|
|  | 2085 | ULONG    ulRc, | 
|---|
|  | 2086 | ulBytes; | 
|---|
| [27] | 2087 | CHAR     szCompoundName[ US_COMPOUND_MAXZ ]; | 
|---|
| [3] | 2088 |  | 
|---|
|  | 2089 | sprintf( szCompoundName, "%s.%d", pszStem, ulIndex ); | 
|---|
|  | 2090 | if ( pszValue == NULL ) { | 
|---|
| [27] | 2091 | pszValue = ""; | 
|---|
| [3] | 2092 | ulBytes  = 0; | 
|---|
|  | 2093 | } else { | 
|---|
|  | 2094 | ulBytes = strlen( pszValue ); | 
|---|
|  | 2095 | } | 
|---|
|  | 2096 | MAKERXSTRING( shvVar.shvname, szCompoundName, strlen(szCompoundName) ); | 
|---|
| [27] | 2097 | shvVar.shvvalue.strptr    = pszValue; | 
|---|
| [3] | 2098 | shvVar.shvvalue.strlength = ulBytes; | 
|---|
|  | 2099 | shvVar.shvnamelen  = RXSTRLEN( shvVar.shvname ); | 
|---|
|  | 2100 | shvVar.shvvaluelen = RXSTRLEN( shvVar.shvvalue ); | 
|---|
|  | 2101 | shvVar.shvcode     = RXSHV_SYSET; | 
|---|
|  | 2102 | shvVar.shvnext     = NULL; | 
|---|
|  | 2103 | ulRc = RexxVariablePool( &shvVar ); | 
|---|
|  | 2104 | if ( ulRc > 1 ) { | 
|---|
|  | 2105 | WriteErrorCode( shvVar.shvret, "RexxVariablePool (SHVBLOCK.shvret)"); | 
|---|
|  | 2106 | return FALSE; | 
|---|
|  | 2107 | } | 
|---|
|  | 2108 | return TRUE; | 
|---|
|  | 2109 |  | 
|---|
|  | 2110 | } | 
|---|
|  | 2111 |  | 
|---|
|  | 2112 |  | 
|---|
|  | 2113 | /* ------------------------------------------------------------------------- * | 
|---|
|  | 2114 | * WriteCompoundVariable                                                     * | 
|---|
|  | 2115 | *                                                                           * | 
|---|
|  | 2116 | * Creates a compound variable in the calling REXX program using the REXX    * | 
|---|
|  | 2117 | * shared variable pool interface.                                           * | 
|---|
|  | 2118 | *                                                                           * | 
|---|
|  | 2119 | * ARGUMENTS:                                                                * | 
|---|
|  | 2120 | *   PSZ   pszStem  : The name of the stem (before the '.')                  * | 
|---|
|  | 2121 | *   PSZ   pszTail  : The name of the trailing portion (after the '.')       * | 
|---|
|  | 2122 | *   PSZ   pszValue : The value to write to the compound variable.           * | 
|---|
|  | 2123 | *                                                                           * | 
|---|
|  | 2124 | * RETURNS: BOOL                                                             * | 
|---|
|  | 2125 | *   TRUE on success, FALSE on failure.                                      * | 
|---|
|  | 2126 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 2127 | BOOL WriteCompoundVariable( PSZ pszStem, PSZ pszTail, PSZ pszValue ) | 
|---|
|  | 2128 | { | 
|---|
|  | 2129 | SHVBLOCK shvVar;                   // REXX shared variable pool block | 
|---|
|  | 2130 | ULONG    ulRc, | 
|---|
|  | 2131 | ulBytes; | 
|---|
| [27] | 2132 | CHAR     szCompoundName[ US_COMPOUND_MAXZ ]; | 
|---|
| [3] | 2133 |  | 
|---|
|  | 2134 | sprintf( szCompoundName, "%s.%s", pszStem, pszTail ); | 
|---|
|  | 2135 | if ( pszValue == NULL ) { | 
|---|
| [27] | 2136 | pszValue = ""; | 
|---|
| [3] | 2137 | ulBytes  = 0; | 
|---|
|  | 2138 | } else { | 
|---|
|  | 2139 | ulBytes = strlen( pszValue ); | 
|---|
|  | 2140 | } | 
|---|
|  | 2141 | MAKERXSTRING( shvVar.shvname, szCompoundName, strlen(szCompoundName) ); | 
|---|
| [27] | 2142 | shvVar.shvvalue.strptr    = pszValue; | 
|---|
| [3] | 2143 | shvVar.shvvalue.strlength = ulBytes; | 
|---|
|  | 2144 | shvVar.shvnamelen  = RXSTRLEN( shvVar.shvname ); | 
|---|
|  | 2145 | shvVar.shvvaluelen = RXSTRLEN( shvVar.shvvalue ); | 
|---|
|  | 2146 | shvVar.shvcode     = RXSHV_SYSET; | 
|---|
|  | 2147 | shvVar.shvnext     = NULL; | 
|---|
|  | 2148 | ulRc = RexxVariablePool( &shvVar ); | 
|---|
|  | 2149 | if ( ulRc > 1 ) { | 
|---|
|  | 2150 | WriteErrorCode( shvVar.shvret, "RexxVariablePool (SHVBLOCK.shvret)"); | 
|---|
|  | 2151 | return FALSE; | 
|---|
|  | 2152 | } | 
|---|
|  | 2153 | return TRUE; | 
|---|
|  | 2154 | } | 
|---|
|  | 2155 |  | 
|---|
|  | 2156 |  | 
|---|
|  | 2157 | /* ------------------------------------------------------------------------- * | 
|---|
| [13] | 2158 | * WriteSimpleVariable                                                       * | 
|---|
|  | 2159 | *                                                                           * | 
|---|
|  | 2160 | * Creates a variable in the calling REXX program using the REXX shared      * | 
|---|
|  | 2161 | * variable pool interface.                                                  * | 
|---|
|  | 2162 | *                                                                           * | 
|---|
|  | 2163 | * ARGUMENTS:                                                                * | 
|---|
|  | 2164 | *   PSZ pszName  : The name of the variable to write.                       * | 
|---|
|  | 2165 | *   PSZ pszValue : The value to write to the variable.                      * | 
|---|
|  | 2166 | *                                                                           * | 
|---|
|  | 2167 | * RETURNS: BOOL                                                             * | 
|---|
|  | 2168 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 2169 | BOOL WriteSimpleVariable( PSZ pszName, PSZ pszValue ) | 
|---|
|  | 2170 | { | 
|---|
|  | 2171 | SHVBLOCK shvVar;                   // REXX shared variable pool block | 
|---|
|  | 2172 | ULONG    ulRc; | 
|---|
|  | 2173 | CHAR     szText[ US_COMPOUND_MAXZ ]; | 
|---|
|  | 2174 |  | 
|---|
|  | 2175 | strncpy( szText, pszValue, US_COMPOUND_MAXZ-1 ); | 
|---|
|  | 2176 | MAKERXSTRING( shvVar.shvname,  pszName, strlen(pszName) ); | 
|---|
|  | 2177 | MAKERXSTRING( shvVar.shvvalue, szText,  strlen(szText) ); | 
|---|
|  | 2178 | shvVar.shvnamelen  = RXSTRLEN( shvVar.shvname ); | 
|---|
|  | 2179 | shvVar.shvvaluelen = RXSTRLEN( shvVar.shvvalue ); | 
|---|
|  | 2180 | shvVar.shvcode     = RXSHV_SYSET; | 
|---|
|  | 2181 | shvVar.shvnext     = NULL; | 
|---|
|  | 2182 | ulRc = RexxVariablePool( &shvVar ); | 
|---|
|  | 2183 | if ( ulRc > 1 ) { | 
|---|
|  | 2184 | WriteErrorCode( shvVar.shvret, "RexxVariablePool (SHVBLOCK.shvret)"); | 
|---|
|  | 2185 | return FALSE; | 
|---|
|  | 2186 | } | 
|---|
|  | 2187 | return TRUE; | 
|---|
|  | 2188 | } | 
|---|
|  | 2189 |  | 
|---|
|  | 2190 |  | 
|---|
|  | 2191 | /* ------------------------------------------------------------------------- * | 
|---|
| [3] | 2192 | * WriteErrorCode                                                            * | 
|---|
|  | 2193 | *                                                                           * | 
|---|
|  | 2194 | * Writes an error code to a special variable in the calling REXX program    * | 
|---|
|  | 2195 | * using the REXX shared variable pool interface.  This is used to return    * | 
|---|
|  | 2196 | * API error codes to the REXX program, since the REXX functions themselves  * | 
|---|
|  | 2197 | * normally return string values.                                            * | 
|---|
|  | 2198 | *                                                                           * | 
|---|
|  | 2199 | * ARGUMENTS:                                                                * | 
|---|
|  | 2200 | *   ULONG ulError   : The error code returned by the failing API call.      * | 
|---|
|  | 2201 | *   PSZ   pszContext: A string describing the API call that failed.         * | 
|---|
|  | 2202 | *                                                                           * | 
|---|
|  | 2203 | * RETURNS: N/A                                                              * | 
|---|
|  | 2204 | * ------------------------------------------------------------------------- */ | 
|---|
|  | 2205 | void WriteErrorCode( ULONG ulError, PSZ pszContext ) | 
|---|
|  | 2206 | { | 
|---|
|  | 2207 | SHVBLOCK shvVar;                   // REXX shared variable pool block | 
|---|
|  | 2208 | ULONG    ulRc; | 
|---|
|  | 2209 | CHAR     szErrorText[ US_ERRSTR_MAXZ ]; | 
|---|
|  | 2210 |  | 
|---|
|  | 2211 | if ( pszContext == NULL ) | 
|---|
|  | 2212 | sprintf( szErrorText, "%X", ulError ); | 
|---|
|  | 2213 | else | 
|---|
|  | 2214 | sprintf( szErrorText, "%X: %s", ulError, pszContext ); | 
|---|
|  | 2215 | MAKERXSTRING( shvVar.shvname,  SZ_ERROR_NAME, strlen(SZ_ERROR_NAME) ); | 
|---|
|  | 2216 | MAKERXSTRING( shvVar.shvvalue, szErrorText,   strlen(szErrorText) ); | 
|---|
|  | 2217 | shvVar.shvnamelen  = RXSTRLEN( shvVar.shvname ); | 
|---|
|  | 2218 | shvVar.shvvaluelen = RXSTRLEN( shvVar.shvvalue ); | 
|---|
|  | 2219 | shvVar.shvcode     = RXSHV_SYSET; | 
|---|
|  | 2220 | shvVar.shvnext     = NULL; | 
|---|
|  | 2221 | ulRc = RexxVariablePool( &shvVar ); | 
|---|
|  | 2222 | if ( ulRc > 1 ) | 
|---|
|  | 2223 | printf("Unable to set %s: rc = %d\n", shvVar.shvname.strptr, shvVar.shvret ); | 
|---|
|  | 2224 | } | 
|---|
|  | 2225 |  | 
|---|
| [32] | 2226 | #endif | 
|---|