Changeset 16 for rxutilex/trunk/rxutilex.c
- Timestamp:
- Sep 20, 2014, 1:17:51 PM (11 years ago)
- File:
-
- 1 edited
-
rxutilex/trunk/rxutilex.c (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
rxutilex/trunk/rxutilex.c
r4 r16 1 1 /****************************************************************************** 2 2 * REXX Utility Functions - Extended (RXUTILEX.DLL) * 3 * (C) 2011 Alex Taylor.*3 * (C) 2011, 2014 Alex Taylor. * 4 4 * * 5 5 * LICENSE: * … … 43 43 #define INCL_WINCLIPBOARD 44 44 #define INCL_WINERRORS 45 #define INCL_DOSERRORS 45 46 #define INCL_DOSMISC 47 #define INCL_DOSMODULEMGR 48 #define INCL_DOSNMPIPES 46 49 #define INCL_DOSPROCESS 47 50 #define INCL_DOSPROFILE 48 #define INCL_DOSERRORS49 #define INCL_DOSMODULEMGR50 51 #ifndef OS2_INCLUDED 51 52 #include <os2.h> … … 72 73 #define SZ_LIBRARY_NAME "RXUTILEX" // Name of this library 73 74 #define SZ_ERROR_NAME "SYS2ERR" // REXX variable used to store error codes 74 #define SZ_VERSION "0.0. 4" // Current version of this library75 #define SZ_VERSION "0.0.5" // Current version of this library 75 76 76 77 // Maximum string lengths... 77 78 #define US_COMPOUND_MAXZ 250 // ...of a compound variable 78 #define US_INTEGER_MAXZ 12 // ...of an integer string 79 #define US_INTEGER_MAXZ 12 // ...of a 32-bit integer string 80 #define US_LONGLONG_MAXZ 21 // ...of a 64-bit integer string 79 81 #define US_STEM_MAXZ ( US_COMPOUND_MAXZ - US_INTEGER_MAXZ ) // ...of a stem 80 82 #define US_ERRSTR_MAXZ 250 // ...of an error string 81 83 #define US_PIDSTR_MAXZ ( CCHMAXPATH + 100 ) // ...of a process information string 82 84 #define US_TIMESTR_MAXZ 256 // ...of a formatted time string 85 #define US_PIPESTATUS_MAXZ 128 // ...of a pipe status string 83 86 84 87 #define UL_SSBUFSIZE 0xFFFF // Buffer size for the DosQuerySysState() data … … 104 107 "Sys2ReplaceModule", 105 108 "Sys2LocateDLL", 109 "Sys2CreateNamedPipe", 110 "Sys2ConnectNamedPipe", 111 "Sys2DisconnectNamedPipe", 112 "Sys2CheckNamedPipe", 113 "Sys2Open", 114 "Sys2Close", 115 "Sys2Seek", 116 "Sys2Read", 117 "Sys2Write", 106 118 "Sys2Version" 107 119 }; … … 120 132 RexxFunctionHandler Sys2GetClipboardText; 121 133 RexxFunctionHandler Sys2PutClipboardText; 122 // RexxFunctionHandler Sys2GetClipboardData;123 // RexxFunctionHandler Sys2PutClipboardData;124 134 125 135 RexxFunctionHandler Sys2QueryProcess; … … 133 143 RexxFunctionHandler Sys2ReplaceModule; 134 144 135 RexxFunctionHandler Sys2ReplaceObjectClass; 145 // RexxFunctionHandler Sys2ReplaceObjectClass; 146 147 RexxFunctionHandler Sys2CreateNamedPipe; 148 RexxFunctionHandler Sys2ConnectNamedPipe; 149 RexxFunctionHandler Sys2DisconnectNamedPipe; 150 RexxFunctionHandler Sys2CheckNamedPipe; 151 152 RexxFunctionHandler Sys2Open; 153 RexxFunctionHandler Sys2Close; 154 RexxFunctionHandler Sys2Seek; 155 RexxFunctionHandler Sys2Read; 156 RexxFunctionHandler Sys2Write; 136 157 137 158 … … 301 322 if ( ulRC == 0 ) { 302 323 memset( pszShareMem, 0, ulBytes ); 303 strncpy( pszShareMem, argv[0].strptr , ulBytes - 1 );324 strncpy( pszShareMem, argv[0].strptr, ulBytes - 1 ); 304 325 if ( ! WinSetClipbrdData( hab, (ULONG) pszShareMem, CF_TEXT, CFI_POINTER )) 305 326 WriteErrorCode( ERRORIDERROR(WinGetLastError(hab)), "WinSetClipbrdData"); … … 1137 1158 WriteErrorCode( timeval, "time"); 1138 1159 MAKERXSTRING( *prsResult, "0", 1 ); 1160 free( pszSetTZ ); 1139 1161 return 0; 1140 1162 } … … 1153 1175 WriteErrorCode( timeval, "mktime"); 1154 1176 MAKERXSTRING( *prsResult, "0", 1 ); 1177 free( pszSetTZ ); 1155 1178 return 0; 1156 1179 } … … 1224 1247 } 1225 1248 1249 1250 /* ------------------------------------------------------------------------- * 1251 * Sys2CreateNamedPipe * 1252 * * 1253 * Create a named pipe with the specified name and parameters. Only byte * 1254 * mode is supported; message mode is not. * 1255 * * 1256 * REXX ARGUMENTS: * 1257 * 1. The name of the pipe, in the form "\PIPE\something". (REQUIRED) * 1258 * 2. The size of the outbound buffer, in bytes. (REQUIRED) * 1259 * 3. The size of the inbound buffer, in bytes. (REQUIRED) * 1260 * 4. The pipe's timeout value, in milliseconds. (DEFAULT: 3000) * 1261 * 5. The number of simultaneous instances of this pipe which are allowed. * 1262 * Must be between 1 and 254, or 0 indicating no limit. (DEFAULT: 1) * 1263 * 6. Pipe blocking mode, one of: * 1264 * W = WAIT mode, read and write block waiting for data. (DEFAULT) * 1265 * N = NOWAIT mode, read and write return immediately. * 1266 * 7. Pipe mode, one of: * 1267 * I = Inbound pipe (DEFAULT) * 1268 * O = Outbound pipe * 1269 * D = Duplex (inbound/outbound) pipe * 1270 * 8. Privacy/inheritance flag, one of: * 1271 * 0 = The pipe handle is inherited by child processes. (DEFAULT) * 1272 * 1 = The pipe handle is private to the current process. * 1273 * 9. Write-through flag, one of: * 1274 * 0 = Allow delayed writes (write-behind) to remote pipes. (DEFAULT) * 1275 * 1 = Force immediate writes (write-through) to remote pipes. * 1276 * * 1277 * REXX RETURN VALUE: * 1278 * A four-byte pipe handle. * 1279 * ------------------------------------------------------------------------- */ 1280 ULONG APIENTRY Sys2CreateNamedPipe( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) 1281 { 1282 HPIPE hp; 1283 PSZ pszNPName; 1284 LONG iLimit; 1285 ULONG ulBufOut, 1286 ulBufIn, 1287 ulTimeout = 3000, 1288 flOpen = 0, 1289 flPipe = 1; 1290 CHAR achHandle[ 9 ]; 1291 APIRET rc; 1292 1293 // Reset the error indicator 1294 WriteErrorCode( 0, NULL ); 1295 1296 // Make sure we have at least three valid arguments (pipe name and sizes) 1297 if ( argc < 3 || ( !RXVALIDSTRING(argv[0]) ) || 1298 ( !RXVALIDSTRING(argv[1]) ) || ( !RXVALIDSTRING(argv[2]) )) 1299 return ( 40 ); 1300 1301 // (Validate the first argument last to simplify error processing) 1302 1303 // Second argument: pipe outbound buffer size 1304 if (( sscanf( argv[1].strptr, "%u", &ulBufOut )) != 1 ) return ( 40 ); 1305 1306 // Third argument: pipe outbound buffer size 1307 if (( sscanf( argv[2].strptr, "%u", &ulBufIn )) != 1 ) return ( 40 ); 1308 1309 // Fourth argument: pipe timeout value 1310 if ( argc >= 4 && RXVALIDSTRING(argv[3]) ) { 1311 if (( sscanf( argv[3].strptr, "%u", &ulTimeout )) != 1 ) return ( 40 ); 1312 } 1313 1314 // Fifth argument: instances limit 1315 if ( argc >= 5 && RXVALIDSTRING(argv[4]) ) { 1316 if (( sscanf( argv[4].strptr, "%d", &iLimit )) != 1 ) return ( 40 ); 1317 if (( iLimit > 1 ) && ( iLimit < 255 )) 1318 flPipe = iLimit; 1319 else if ( !iLimit || ( iLimit == -1 )) 1320 flPipe = NP_UNLIMITED_INSTANCES; 1321 else 1322 return ( 40 ); 1323 } 1324 1325 // Sixth argument: blocking mode 1326 if ( argc >= 6 && RXVALIDSTRING(argv[5]) ) { 1327 strupr( argv[5].strptr ); 1328 if ( argv[5].strptr[0] == 'N' ) 1329 flPipe |= NP_NOWAIT; 1330 else if ( argv[5].strptr[0] != 'W' ) 1331 return ( 40 ); 1332 } 1333 1334 // Seventh argument: pipe mode (direction) 1335 if ( argc >= 7 && RXVALIDSTRING(argv[6]) ) { 1336 strupr( argv[6].strptr ); 1337 if (strcspn(argv[6].strptr, "IOD") > 0 ) return ( 40 ); 1338 switch ( argv[6].strptr[0] ) { 1339 case 'O': flOpen |= NP_ACCESS_OUTBOUND; break; 1340 case 'D': flOpen |= NP_ACCESS_DUPLEX; break; 1341 default : break; // default is 0 1342 } 1343 } 1344 1345 // Eighth argument: inheritance mode 1346 if ( argc >= 8 && RXVALIDSTRING(argv[7]) ) { 1347 strupr( argv[7].strptr ); 1348 if ( argv[7].strptr[0] == '1' ) 1349 flOpen |= NP_NOINHERIT; 1350 else if ( argv[7].strptr[0] != '0' ) 1351 return ( 40 ); 1352 } 1353 1354 // Ninth argument: write mode 1355 if ( argc >= 9 && RXVALIDSTRING(argv[8]) ) { 1356 strupr( argv[8].strptr ); 1357 if ( argv[8].strptr[0] == '1' ) 1358 flOpen |= NP_NOWRITEBEHIND; 1359 else if ( argv[8].strptr[0] != '0' ) 1360 return ( 40 ); 1361 } 1362 1363 // Now the first argument: pipe name 1364 pszNPName = (PSZ) calloc( RXSTRLEN(argv[0]) + 1, sizeof(UCHAR) ); 1365 if ( pszNPName == NULL ) { 1366 WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "calloc"); 1367 MAKERXSTRING( *prsResult, "0", 1 ); 1368 return ( 0 ); 1369 } 1370 strncpy( pszNPName, argv[0].strptr, RXSTRLEN(argv[0]) ); 1371 1372 // All good, now create the pipe 1373 rc = DosCreateNPipe( pszNPName, &hp, flOpen, flPipe, ulBufOut, ulBufIn, ulTimeout ); 1374 if (rc) { 1375 WriteErrorCode( rc, "DosCreateNPipe"); 1376 MAKERXSTRING( *prsResult, "", 0 ); 1377 return 0; 1378 } 1379 1380 // Return the handle as the REXX result string 1381 sprintf( achHandle, "%8X", hp ); 1382 MAKERXSTRING( *prsResult, achHandle, strlen( achHandle )); 1383 1384 free( pszNPName ); 1385 return ( 0 ); 1386 } 1387 1388 1389 /* ------------------------------------------------------------------------- * 1390 * Sys2ConnectNamedPipe * 1391 * * 1392 * Start 'listening' by allowing clients to connect to a previously-created * 1393 * named pipe. * 1394 * * 1395 * REXX ARGUMENTS: * 1396 * 1. The pipe handle, as returned by Sys2CreateNamedPipe. (REQUIRED) * 1397 * * 1398 * REXX RETURN VALUE: * 1399 * 1 on success, or 0 if an error occurred. * 1400 * ------------------------------------------------------------------------- */ 1401 ULONG APIENTRY Sys2ConnectNamedPipe( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) 1402 { 1403 HPIPE hp; 1404 APIRET rc; 1405 1406 // Reset the error indicator 1407 WriteErrorCode( 0, NULL ); 1408 1409 // Parse the handle 1410 if ( !(argc == 1 && RXVALIDSTRING(argv[0])) ) return ( 40 ); 1411 if (( sscanf( argv[0].strptr, "%8X", &hp )) != 1 ) return ( 40 ); 1412 1413 // Connect the pipe 1414 rc = DosConnectNPipe( hp ); 1415 if ( rc != NO_ERROR ) { 1416 WriteErrorCode( rc, "DosConnectNPipe"); 1417 MAKERXSTRING( *prsResult, "0", 1 ); 1418 return ( 0 ); 1419 } 1420 1421 // Return 1 on success 1422 MAKERXSTRING( *prsResult, "1", 1 ); 1423 return ( 0 ); 1424 } 1425 1426 1427 /* ------------------------------------------------------------------------- * 1428 * Sys2DisconnectNamedPipe * 1429 * * 1430 * Unlocks a named pipe after a client has closed its connection. * 1431 * * 1432 * REXX ARGUMENTS: * 1433 * 1. The pipe handle, as returned by Sys2CreateNamedPipe. (REQUIRED) * 1434 * * 1435 * REXX RETURN VALUE: * 1436 * 1 on success, or 0 if an error occurred. * 1437 * ------------------------------------------------------------------------- */ 1438 ULONG APIENTRY Sys2DisconnectNamedPipe( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) 1439 { 1440 HPIPE hp; 1441 APIRET rc; 1442 1443 // Reset the error indicator 1444 WriteErrorCode( 0, NULL ); 1445 1446 // Parse the handle 1447 if ( !(argc == 1 && RXVALIDSTRING(argv[0])) ) return ( 40 ); 1448 if (( sscanf( argv[0].strptr, "%8X", &hp )) != 1 ) return ( 40 ); 1449 1450 // Connect the pipe 1451 rc = DosDisConnectNPipe( hp ); 1452 if ( rc != NO_ERROR ) { 1453 WriteErrorCode( rc, "DosDisConnectNPipe"); 1454 MAKERXSTRING( *prsResult, "0", 1 ); 1455 return ( 0 ); 1456 } 1457 1458 // Return 1 on success 1459 MAKERXSTRING( *prsResult, "1", 1 ); 1460 return ( 0 ); 1461 } 1462 1463 1464 /* ------------------------------------------------------------------------- * 1465 * Sys2CheckNamedPipe * 1466 * * 1467 * Check the status of a named pipe. * 1468 * * 1469 * REXX ARGUMENTS: * 1470 * 1. The pipe handle (from Sys2CreateNamedPipe or DosOpen). (REQUIRED) * 1471 * * 1472 * REXX RETURN VALUE: * 1473 * String of the format "bytes status", where bytes is the number of bytes * 1474 * currently waiting in the pipe, and status is one of: DISCONNECTED, * 1475 * LISTENING, CONNECTED, or CLOSING. * 1476 * ------------------------------------------------------------------------- */ 1477 ULONG APIENTRY Sys2CheckNamedPipe( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) 1478 { 1479 HPIPE hp; 1480 ULONG cbActual, ulState; 1481 AVAILDATA avd; 1482 CHAR szStatus[ US_PIPESTATUS_MAXZ ]; 1483 APIRET rc; 1484 1485 // Reset the error indicator 1486 WriteErrorCode( 0, NULL ); 1487 1488 // Parse the handle 1489 if ( !(argc == 1 && RXVALIDSTRING(argv[0])) ) return ( 40 ); 1490 if (( sscanf( argv[0].strptr, "%8X", &hp )) != 1 ) return ( 40 ); 1491 1492 rc = DosPeekNPipe( hp, NULL, 0, &cbActual, &avd, &ulState ); 1493 if ( rc != NO_ERROR ) { 1494 WriteErrorCode( rc, "DosPeekNPipe"); 1495 MAKERXSTRING( *prsResult, "", 0 ); 1496 return ( 0 ); 1497 } 1498 sprintf( szStatus, "%u ", avd.cbpipe ); 1499 switch ( ulState ) { 1500 case NP_STATE_DISCONNECTED: strncat( szStatus, "DISCONNECTED", US_PIPESTATUS_MAXZ-1 ); break; 1501 case NP_STATE_LISTENING: strncat( szStatus, "LISTENING", US_PIPESTATUS_MAXZ-1 ); break; 1502 case NP_STATE_CONNECTED: strncat( szStatus, "CONNECTED", US_PIPESTATUS_MAXZ-1 ); break; 1503 case NP_STATE_CLOSING: strncat( szStatus, "CLOSING", US_PIPESTATUS_MAXZ-1 ); break; 1504 default: strncat( szStatus, "UNKNOWN", US_PIPESTATUS_MAXZ-1 ); break; 1505 } 1506 1507 if ( ! SaveResultString( prsResult, szStatus, strlen( szStatus ))) { 1508 MAKERXSTRING( *prsResult, "", 0 ); 1509 } 1510 return ( 0 ); 1511 } 1512 1513 1514 /* ------------------------------------------------------------------------- * 1515 * Sys2Open * 1516 * * 1517 * Wrapper to DosOpenL: open a file or stream (with >2GB support). * 1518 * Direct-DASD mode is not supported by this function, nor is setting the * 1519 * initial extended attributes. * 1520 * * 1521 * REXX ARGUMENTS: * 1522 * 1. Name of file or stream to open. (REQUIRED) * 1523 * 2. Open action flags, must be either "O" (open if exists), "R" (replace * 1524 * if exists), or nothing (fail if exists), optionally followed by "C" * 1525 * (create if file does not exist). If "C" is not specified, the * 1526 * operation will fail if the file does not exist. Note that a value * 1527 * of "" alone will therefore fail automatically. (DEFAULT: "O") * 1528 * In summary, the possible combinations are: * 1529 * O = Open only (if file exists, open it; if not, fail) * 1530 * OC= Open/create (if file exists, open it; if not, create it) * 1531 * R = Replace only (if file exists, replace it; if not, fail) * 1532 * RC= Replace/create (if file exists, replace it; if not, create it) * 1533 * C = Create only (if file exists, fail; if not, create it) * 1534 * (empty) = No-op (if file exists, fail; if not, fail) * 1535 * 3. Access mode flags, one or both of: (DEFAULT: "RW") * 1536 * R = Open file with read access. * 1537 * W = Open file with write access. * 1538 * 4. Sharing mode flags, any combination of: (DEFAULT: "W") * 1539 * R = Deny read access to other processes * 1540 * W = Deny write access to other processes * 1541 * 5. Deny legacy DosOpen access, one of: * 1542 * 0 = Allow DosOpen to access the file (DEFAULT) * 1543 * 1 = Deny access using the DosOpen API * 1544 * 6. Privacy/inheritance flag, one of: * 1545 * 0 = The file handle is inherited by child processes. (DEFAULT) * 1546 * 1 = The file handle is private to the current process. * 1547 * 7. Initial file attributes when creating a file: (DEFAULT: "") * 1548 * A = Archive attribute set * 1549 * D = Directory attribute set * 1550 * S = System attribute set * 1551 * H = Hidden attribute set * 1552 * R = Read-only attribute set * 1553 * 8. Initial file size when creating or replacing a file; ignored if * 1554 * access mode is read-only. (DEFAULT: 0) * 1555 * 9. I/O mode flags, any or all of: (DEFAULT: "") * 1556 * T = Write-through mode (default is normal write) * 1557 * N = No-cache mode (default is to use filesystem cache) * 1558 * S = Sequential access * 1559 * R = Random access * 1560 * * S and R can combine as follows: * 1561 * Neither: No locality known (default) * 1562 * S only: Mainly sequential access * 1563 * R only: Mainly random access * 1564 * Both: Random/sequential (i.e. random with some locality) * 1565 * * 1566 * REXX RETURN VALUE: * 1567 * File handle, or "" in case of error. * 1568 * ------------------------------------------------------------------------- */ 1569 ULONG APIENTRY Sys2Open( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) 1570 { 1571 PSZ pszFile; 1572 HFILE hf; 1573 ULONG fsAction = 0, 1574 fsMode = 0, 1575 ulResult = 0, 1576 ulAttr = FILE_NORMAL; 1577 LONGLONG llSize = {0}; 1578 CHAR achHandle[ 9 ]; 1579 APIRET rc; 1580 1581 1582 // Reset the error indicator 1583 WriteErrorCode( 0, NULL ); 1584 1585 // Make sure we have at least one valid argument (the file name) 1586 if ( argc < 1 || ( !RXVALIDSTRING(argv[0]) )) 1587 return ( 40 ); 1588 1589 // (Validate the first argument last to simplify error processing) 1590 1591 // Second argument: open action 1592 if ( argc >= 2 && RXVALIDSTRING(argv[1]) ) { 1593 strupr( argv[1].strptr ); 1594 if ( strcspn(argv[1].strptr, "OCR") > 0 ) return ( 40 ); 1595 if ( strchr(argv[1].strptr, 'O')) 1596 fsAction |= OPEN_ACTION_OPEN_IF_EXISTS; 1597 else if ( strchr(argv[1].strptr, 'R')) 1598 fsAction |= OPEN_ACTION_REPLACE_IF_EXISTS; 1599 if ( strchr(argv[1].strptr, 'C')) 1600 fsAction |= OPEN_ACTION_CREATE_IF_NEW; 1601 } 1602 else 1603 fsAction = OPEN_ACTION_OPEN_IF_EXISTS; 1604 1605 // Third argument: access mode 1606 if ( argc >= 3 && RXVALIDSTRING(argv[2]) ) { 1607 strupr( argv[2].strptr ); 1608 if ( strcspn(argv[2].strptr, "RW") > 0 ) return ( 40 ); 1609 if ( strchr(argv[2].strptr, 'R')) { 1610 if (strchr(argv[2].strptr, 'W')) 1611 fsMode = OPEN_ACCESS_READWRITE; 1612 else 1613 fsMode = OPEN_ACCESS_READONLY; 1614 } 1615 else if (strchr(argv[2].strptr, 'W')) 1616 fsMode = OPEN_ACCESS_WRITEONLY; 1617 else 1618 return ( 40 ); 1619 } 1620 else 1621 fsMode = OPEN_ACCESS_READWRITE; 1622 1623 // Fourth argument: sharing mode 1624 if ( argc >= 4 && RXVALIDSTRING(argv[3]) ) { 1625 strupr( argv[3].strptr ); 1626 if ( strcspn(argv[3].strptr, "RW") > 0 ) return ( 40 ); 1627 if ( strchr(argv[3].strptr, 'R')) { 1628 if (strchr(argv[3].strptr, 'W')) 1629 fsMode |= OPEN_SHARE_DENYREADWRITE; 1630 else 1631 fsMode |= OPEN_SHARE_DENYREAD; 1632 } 1633 else if (strchr(argv[3].strptr, 'W')) 1634 fsMode |= OPEN_SHARE_DENYWRITE; 1635 else 1636 fsMode |= OPEN_SHARE_DENYNONE; 1637 } 1638 else 1639 fsMode |= OPEN_SHARE_DENYWRITE; 1640 1641 // Fifth argument: deny legacy mode 1642 if ( argc >= 5 && RXVALIDSTRING(argv[4]) ) { 1643 strupr( argv[4].strptr ); 1644 if ( argv[4].strptr[0] == '1' ) 1645 fsMode |= OPEN_SHARE_DENYLEGACY; 1646 else if ( argv[4].strptr[0] != '0' ) 1647 return ( 40 ); 1648 } 1649 1650 // Sixth argument: inheritance mode 1651 if ( argc >= 6 && RXVALIDSTRING(argv[5]) ) { 1652 strupr( argv[5].strptr ); 1653 if ( argv[5].strptr[0] == '1' ) 1654 fsMode |= OPEN_FLAGS_NOINHERIT; 1655 else if ( argv[5].strptr[0] != '0' ) 1656 return ( 40 ); 1657 } 1658 1659 // Seventh argument: attributes 1660 if ( argc >= 7 && RXVALIDSTRING(argv[6]) ) { 1661 strupr( argv[6].strptr ); 1662 if (strcspn(argv[6].strptr, "ADSHR") > 0 ) return ( 40 ); 1663 if ( strchr(argv[6].strptr, 'A')) ulAttr |= FILE_ARCHIVED; 1664 if ( strchr(argv[6].strptr, 'D')) ulAttr |= FILE_DIRECTORY; 1665 if ( strchr(argv[6].strptr, 'S')) ulAttr |= FILE_SYSTEM; 1666 if ( strchr(argv[6].strptr, 'H')) ulAttr |= FILE_HIDDEN; 1667 if ( strchr(argv[6].strptr, 'R')) ulAttr |= FILE_READONLY; 1668 } 1669 1670 // Eighth argument: initial size 1671 if ( argc >= 8 && RXVALIDSTRING(argv[7]) ) { 1672 if (( sscanf( argv[7].strptr, "%lld", &llSize )) != 1 ) return ( 40 ); 1673 } 1674 1675 // Ninth argument: I/O mode flags 1676 if ( argc >= 9 && RXVALIDSTRING(argv[8]) ) { 1677 strupr( argv[8].strptr ); 1678 if (strcspn(argv[8].strptr, "TNSR") > 0 ) return ( 40 ); 1679 if ( strchr(argv[8].strptr, 'T')) fsMode |= OPEN_FLAGS_WRITE_THROUGH; 1680 if ( strchr(argv[8].strptr, 'N')) fsMode |= OPEN_FLAGS_NO_CACHE; 1681 if ( strchr(argv[8].strptr, 'S')) fsMode |= OPEN_FLAGS_SEQUENTIAL; 1682 if ( strchr(argv[8].strptr, 'R')) fsMode |= OPEN_FLAGS_RANDOM; 1683 } 1684 1685 // Now the first argument: file name 1686 pszFile = (PSZ) calloc( RXSTRLEN(argv[0]) + 1, sizeof(UCHAR) ); 1687 if ( pszFile == NULL ) { 1688 WriteErrorCode( ERROR_NOT_ENOUGH_MEMORY, "calloc"); 1689 MAKERXSTRING( *prsResult, "0", 1 ); 1690 return ( 0 ); 1691 } 1692 strncpy( pszFile, argv[0].strptr, RXSTRLEN(argv[0]) ); 1693 1694 // Try and open the file 1695 rc = DosOpenL( pszFile, &hf, &ulResult, llSize, ulAttr, fsAction, fsMode, NULL ); 1696 if (rc) { 1697 WriteErrorCode( rc, "DosOpenL"); 1698 MAKERXSTRING( *prsResult, "", 0 ); 1699 free( pszFile ); 1700 return ( 0 ); 1701 } 1702 1703 // Return the handle as the REXX result string 1704 sprintf( achHandle, "%8X", hf ); 1705 MAKERXSTRING( *prsResult, achHandle, strlen( achHandle )); 1706 1707 free( pszFile ); 1708 return ( 0 ); 1709 } 1710 1711 1712 /* ------------------------------------------------------------------------- * 1713 * Sys2Close * 1714 * * 1715 * Wrapper to DosWrite: write bytes to a previously-opened stream. * 1716 * * 1717 * REXX ARGUMENTS: * 1718 * 1. File handle (returned by Sys2Open) (REQUIRED) * 1719 * * 1720 * REXX RETURN VALUE: * 1721 * 1 on success, or 0 if an error occurred. * 1722 * ------------------------------------------------------------------------- */ 1723 ULONG APIENTRY Sys2Close( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) 1724 { 1725 HFILE hf; 1726 APIRET rc; 1727 1728 // Reset the error indicator 1729 WriteErrorCode( 0, NULL ); 1730 1731 // Make sure we have exactly one valid argument (the file handle) 1732 if ( argc != 1 || ( !RXVALIDSTRING(argv[0]) )) 1733 return ( 40 ); 1734 if (( sscanf( argv[0].strptr, "%8X", &hf )) != 1 ) return ( 40 ); 1735 1736 // Close the file 1737 rc = DosClose( hf ); 1738 if ( rc != NO_ERROR ) { 1739 WriteErrorCode( rc, "DosClose"); 1740 MAKERXSTRING( *prsResult, "0", 1 ); 1741 } 1742 else { 1743 MAKERXSTRING( *prsResult, "1", 1 ); 1744 } 1745 1746 return ( 0 ); 1747 } 1748 1749 1750 /* ------------------------------------------------------------------------- * 1751 * Sys2Seek * 1752 * * 1753 * Wrapper to DosSetFilePtrL: move the read/write pointer to the specified * 1754 * location in a stream. * 1755 * * 1756 * REXX ARGUMENTS: * 1757 * 1. File handle (returned by Sys2Open) (REQUIRED) * 1758 * 2. The signed distance in bytes to move (REQUIRED) * 1759 * 3. Move method, one of: * 1760 * B = Beginning of file * 1761 * C = Current position (DEFAULT) * 1762 * E = End of file * 1763 * * 1764 * REXX RETURN VALUE: * 1765 * The new file position, in bytes. * 1766 * ------------------------------------------------------------------------- */ 1767 ULONG APIENTRY Sys2Seek( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) 1768 { 1769 HFILE hf; 1770 LONGLONG llPos, 1771 llActual; 1772 ULONG ulMethod = FILE_CURRENT; 1773 CHAR achActual[ US_LONGLONG_MAXZ ]; 1774 APIRET rc; 1775 1776 // Reset the error indicator 1777 WriteErrorCode( 0, NULL ); 1778 1779 // Make sure we have at least two valid arguments 1780 if ( argc < 2 || ( !RXVALIDSTRING(argv[0]) ) || ( !RXVALIDSTRING(argv[1]) )) 1781 return ( 40 ); 1782 1783 // First argument: file handle 1784 if (( sscanf( argv[0].strptr, "%8X", &hf )) != 1 ) return ( 40 ); 1785 1786 // Second argument: requested offset 1787 if (( sscanf( argv[1].strptr, "%lld", &llPos )) != 1 ) return ( 40 ); 1788 1789 // Third argument: starting position 1790 if ( argc >= 3 && RXVALIDSTRING(argv[2]) ) { 1791 strupr( argv[2].strptr ); 1792 if ( strcspn(argv[2].strptr, "BCE") > 0 ) return ( 40 ); 1793 switch ( argv[1].strptr[0] ) { 1794 case 'B': ulMethod = FILE_BEGIN; break; 1795 case 'E': ulMethod = FILE_END; break; 1796 default : ulMethod = FILE_CURRENT; break; 1797 } 1798 } 1799 1800 rc = DosSetFilePtrL( hf, llPos, ulMethod, &llActual ); 1801 if ( rc != NO_ERROR ) { 1802 WriteErrorCode( rc, "DosSetFilePtrL"); 1803 MAKERXSTRING( *prsResult, "", 0 ); 1804 return ( 0 ); 1805 } 1806 1807 // Return the new position as the REXX result string 1808 sprintf( achActual, "%lld", llActual ); 1809 MAKERXSTRING( *prsResult, achActual, strlen( achActual )); 1810 1811 return ( 0 ); 1812 } 1813 1814 1815 /* ------------------------------------------------------------------------- * 1816 * Sys2Read * 1817 * * 1818 * Wrapper to DosRead: read bytes from a previously-opened stream. * 1819 * * 1820 * REXX ARGUMENTS: * 1821 * 1. File handle (returned by Sys2Open or Sys2CreateNamedPipe) (REQUIRED) * 1822 * 2. Number of bytes to read (REQUIRED) * 1823 * * 1824 * REXX RETURN VALUE: * 1825 * String containing the bytes read, or "" in case of error. * 1826 * ------------------------------------------------------------------------- */ 1827 ULONG APIENTRY Sys2Read( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) 1828 { 1829 HFILE hf; 1830 ULONG cb, 1831 cbActual; 1832 PSZ pszData; 1833 APIRET rc; 1834 1835 // Reset the error indicator 1836 WriteErrorCode( 0, NULL ); 1837 1838 // Make sure we have two valid arguments 1839 if ( argc != 2 || ( !RXVALIDSTRING(argv[0]) ) || ( !RXVALIDSTRING(argv[1]) )) 1840 return ( 40 ); 1841 1842 // First argument: handle 1843 if (( sscanf( argv[0].strptr, "%8X", &hf )) != 1 ) return ( 40 ); 1844 1845 // Second argument: number of bytes to read 1846 if (( sscanf( argv[1].strptr, "%u", &cb )) != 1 ) return ( 40 ); 1847 if ( cb < 1 ) return ( 40 ); 1848 pszData = (PSZ) malloc( cb ); 1849 1850 rc = DosRead( hf, pszData, cb, &cbActual ); 1851 if ( rc || !cbActual ) { 1852 WriteErrorCode( rc, "DosRead"); 1853 MAKERXSTRING( *prsResult, "", 0 ); 1854 goto cleanup; 1855 } 1856 if ( ! SaveResultString( prsResult, pszData, cbActual )) { 1857 MAKERXSTRING( *prsResult, "", 0 ); 1858 } 1859 1860 cleanup: 1861 free( pszData ); 1862 return ( 0 ); 1863 } 1864 1865 1866 /* ------------------------------------------------------------------------- * 1867 * Sys2Write * 1868 * * 1869 * Wrapper to DosWrite: write bytes to a previously-opened stream. * 1870 * * 1871 * REXX ARGUMENTS: * 1872 * 1. File handle (returned by Sys2Open or Sys2CreateNamedPipe) (REQUIRED) * 1873 * 2. Data to be written (REQUIRED) * 1874 * * 1875 * REXX RETURN VALUE: * 1876 * 1 on success, or 0 if an error occurred. * 1877 * ------------------------------------------------------------------------- */ 1878 ULONG APIENTRY Sys2Write( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult ) 1879 { 1880 HFILE hf; 1881 ULONG cbActual; 1882 APIRET rc; 1883 1884 // Reset the error indicator 1885 WriteErrorCode( 0, NULL ); 1886 1887 // Make sure we have two valid arguments 1888 if ( argc != 2 || ( !RXVALIDSTRING(argv[0]) ) || ( !RXVALIDSTRING(argv[1]) )) 1889 return ( 40 ); 1890 1891 // First argument: handle 1892 if (( sscanf( argv[0].strptr, "%8X", &hf )) != 1 ) return ( 40 ); 1893 1894 // (Second argument can be left in standard RXSTRING form) 1895 1896 rc = DosWrite( hf, argv[0].strptr, argv[0].strlength, &cbActual ); 1897 if ( rc != NO_ERROR ) { 1898 WriteErrorCode( rc, "DosWrite"); 1899 MAKERXSTRING( *prsResult, "0", 1 ); 1900 } 1901 else { 1902 MAKERXSTRING( *prsResult, "1", 1 ); 1903 } 1904 1905 return ( 0 ); 1906 } 1226 1907 1227 1908
Note:
See TracChangeset
for help on using the changeset viewer.
