| 1 | #ifndef OS2_INCLUDED
 | 
|---|
| 2 |     #include <os2.h>
 | 
|---|
| 3 | #endif
 | 
|---|
| 4 | #include <stdio.h>
 | 
|---|
| 5 | #include <stdlib.h>
 | 
|---|
| 6 | #include <string.h>
 | 
|---|
| 7 | #include <ctype.h>
 | 
|---|
| 8 | #include <lvm_intr.h>
 | 
|---|
| 9 | 
 | 
|---|
| 10 | #define INCL_RXSHV
 | 
|---|
| 11 | #define INCL_RXFUNC
 | 
|---|
| 12 | #include <rexxsaa.h>
 | 
|---|
| 13 | 
 | 
|---|
| 14 | 
 | 
|---|
| 15 | // CONSTANTS
 | 
|---|
| 16 | 
 | 
|---|
| 17 | #define US_VERSION_MAJOR    0                       // Major version number of this library
 | 
|---|
| 18 | #define US_VERSION_MINOR    5                       // Minor version number of this library
 | 
|---|
| 19 | #define US_VERSION_REFRESH  1                       // Refresh level of this library
 | 
|---|
| 20 | 
 | 
|---|
| 21 | // (string length constants ending in 'Z' include space for the null terminator)
 | 
|---|
| 22 | #define US_INTEGER_MAXZ     12                      // Maximum length of an integer string
 | 
|---|
| 23 | #define US_ERRSTR_MAXZ    ( 10 + US_INTEGER_MAXZ )  // Maximum length of a SZ_ENGINE_ERROR string
 | 
|---|
| 24 | #define US_DEVTYPE_MAXZ     4                       // Maximum length of a device-type string
 | 
|---|
| 25 | #define US_BMINFO_MAXZ      32                      // Maximum length of a Boot Manager information string
 | 
|---|
| 26 | #define US_SZINFO_MAXZ      255                     // Maximum length of an information string (used for stem values)
 | 
|---|
| 27 | #define US_STEM_MAXZ        238                     // Maximum length of a stem variable (no extension)
 | 
|---|
| 28 | #define US_COMPOUND_MAXZ  ( US_STEM_MAXZ + US_INTEGER_MAXZ ) // Maximum length of a compound variable (stem+extension)
 | 
|---|
| 29 | 
 | 
|---|
| 30 | #define UL_SECTORS_PER_MB ( 1048576 / BYTES_PER_SECTOR )     // Used to convert sector sizes to MB
 | 
|---|
| 31 | 
 | 
|---|
| 32 | #define SZ_ENGINE_ERROR     "ERROR: %d"             // Template for LVM error string
 | 
|---|
| 33 | #define SZ_LIBRARY_NAME     "RXLVM"                 // Name of this library
 | 
|---|
| 34 | 
 | 
|---|
| 35 | // Device type constants
 | 
|---|
| 36 | #define SZ_DEVICE_HDD       "HDD"                   // Hard disk drive
 | 
|---|
| 37 | #define SZ_DEVICE_PRM       "PRM"                   // Partitioned removeable media
 | 
|---|
| 38 | #define SZ_DEVICE_CDROM     "CD"                    // CD/DVD drive
 | 
|---|
| 39 | #define SZ_DEVICE_NETWORK   "LAN"                   // Network drive
 | 
|---|
| 40 | #define SZ_DEVICE_OTHER     "?"                     // Unrecognized non-LVM device (e.g. RAM disk)
 | 
|---|
| 41 | 
 | 
|---|
| 42 | // Partition status constants
 | 
|---|
| 43 | #define CH_PTYPE_FREESPACE  'F'                     // Free space
 | 
|---|
| 44 | #define CH_PTYPE_AVAILABLE  'A'                     // Available (not part of a volume)
 | 
|---|
| 45 | #define CH_PTYPE_CVOLUME    'C'                     // Belongs to a compatibility volume
 | 
|---|
| 46 | #define CH_PTYPE_LVOLUME    'L'                     // Belongs to an LVM-type (advanced) volume
 | 
|---|
| 47 | #define CH_PTYPE_INUSE      'U'                     // Marked 'in use' but not part of a volume
 | 
|---|
| 48 | #define CH_PTYPE_UNKNOWN    '?'                     // Unknown/error condition (should be impossible)
 | 
|---|
| 49 | 
 | 
|---|
| 50 | // Boot flag constants
 | 
|---|
| 51 | #define CH_FBOOT_BOOTABLE   'B'                     // Bootable (on Boot Manager menu)
 | 
|---|
| 52 | #define CH_FBOOT_STARTABLE  'S'                     // Startable (directly bootable)
 | 
|---|
| 53 | #define CH_FBOOT_INSTABLE   'I'                     // Installable (specific to IBM installer)
 | 
|---|
| 54 | #define CH_FBOOT_NONE       'N'                     // None (not bootable)
 | 
|---|
| 55 | 
 | 
|---|
| 56 | // Removeable media type flags
 | 
|---|
| 57 | #define US_RMEDIA_PRM       1                       // Partitionable removeable media
 | 
|---|
| 58 | #define US_RMEDIA_BIGFLOPPY 2                       // "Big floppy" style removeable media
 | 
|---|
| 59 | 
 | 
|---|
| 60 | // List of functions to be registered by RxLvmAddFuncs
 | 
|---|
| 61 | static PSZ RxLvmFunctionTbl[] = {
 | 
|---|
| 62 |     "RxLvmDropFuncs",
 | 
|---|
| 63 |     "RxLvmVersion",
 | 
|---|
| 64 |     "RxLvmBootMgrInfo",
 | 
|---|
| 65 |     "RxLvmBootMgrMenu",
 | 
|---|
| 66 |     "RxLvmEngineClose",
 | 
|---|
| 67 |     "RxLvmEngineOpen",
 | 
|---|
| 68 |     "RxLvmGetDisks",
 | 
|---|
| 69 |     "RxLvmGetPartitions",
 | 
|---|
| 70 |     "RxLvmGetVolumes",
 | 
|---|
| 71 |     "RxLvmRediscoverPRM"
 | 
|---|
| 72 | };
 | 
|---|
| 73 | 
 | 
|---|
| 74 | 
 | 
|---|
| 75 | // FUNCTION DECLARATIONS
 | 
|---|
| 76 | 
 | 
|---|
| 77 | // Exported REXX functions
 | 
|---|
| 78 | RexxFunctionHandler RxLvmLoadFuncs;
 | 
|---|
| 79 | RexxFunctionHandler RxLvmDropFuncs;
 | 
|---|
| 80 | RexxFunctionHandler RxLvmVersion;
 | 
|---|
| 81 | RexxFunctionHandler RxLvmBootMgrInfo;
 | 
|---|
| 82 | RexxFunctionHandler RxLvmEngineClose;
 | 
|---|
| 83 | RexxFunctionHandler RxLvmEngineOpen;
 | 
|---|
| 84 | RexxFunctionHandler RxLvmGetDisks;
 | 
|---|
| 85 | RexxFunctionHandler RxLvmGetPartitions;
 | 
|---|
| 86 | RexxFunctionHandler RxLvmGetVolumes;
 | 
|---|
| 87 | RexxFunctionHandler RxLvmRediscoverPRM;
 | 
|---|
| 88 | 
 | 
|---|
| 89 | // Private internal functions
 | 
|---|
| 90 | PSZ  FixedVolumeFileSystem( ADDRESS volume, PSZ pszReportedFS );
 | 
|---|
| 91 | PSZ  FixedPartitionFileSystem( BYTE fOS, PSZ pszReportedFS );
 | 
|---|
| 92 | void EngineError( PRXSTRING prsResult, ULONG ulErrorCode );
 | 
|---|
| 93 | void WriteStemElement( PSZ pszStem, ULONG ulIndex, PSZ pszValue );
 | 
|---|
| 94 | 
 | 
|---|
| 95 | 
 | 
|---|
| 96 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 97 |  * RxLvmLoadFuncs                                                            *
 | 
|---|
| 98 |  *                                                                           *
 | 
|---|
| 99 |  * Should be self-explanatory...                                             *
 | 
|---|
| 100 |  *                                                                           *
 | 
|---|
| 101 |  * REXX ARGUMENTS:    none                                                   *
 | 
|---|
| 102 |  * REXX RETURN VALUE: ""                                                     *
 | 
|---|
| 103 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 104 | ULONG APIENTRY RxLvmLoadFuncs( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 105 | {
 | 
|---|
| 106 |     int entries,
 | 
|---|
| 107 |         i;
 | 
|---|
| 108 | 
 | 
|---|
| 109 |     if ( argc > 0 ) return ( 40 );
 | 
|---|
| 110 |     entries = sizeof(RxLvmFunctionTbl) / sizeof(PSZ);
 | 
|---|
| 111 |     for ( i = 0; i < entries; i++ )
 | 
|---|
| 112 |         RexxRegisterFunctionDll( RxLvmFunctionTbl[i], SZ_LIBRARY_NAME, RxLvmFunctionTbl[i] );
 | 
|---|
| 113 | 
 | 
|---|
| 114 |     MAKERXSTRING( *prsResult, "", 0 );
 | 
|---|
| 115 |     return ( 0 );
 | 
|---|
| 116 | }
 | 
|---|
| 117 | 
 | 
|---|
| 118 | 
 | 
|---|
| 119 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 120 |  * RxLvmDropFuncs                                                            *
 | 
|---|
| 121 |  *                                                                           *
 | 
|---|
| 122 |  * Ditto.                                                                    *
 | 
|---|
| 123 |  *                                                                           *
 | 
|---|
| 124 |  * REXX ARGUMENTS:    none                                                   *
 | 
|---|
| 125 |  * REXX RETURN VALUE: ""                                                     *
 | 
|---|
| 126 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 127 | ULONG APIENTRY RxLvmDropFuncs( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 128 | {
 | 
|---|
| 129 |     int entries,
 | 
|---|
| 130 |         i;
 | 
|---|
| 131 | 
 | 
|---|
| 132 |     if ( argc > 0 ) return ( 40 );
 | 
|---|
| 133 |     entries = sizeof(RxLvmFunctionTbl) / sizeof(PSZ);
 | 
|---|
| 134 |     for ( i = 0; i < entries; i++ )
 | 
|---|
| 135 |         RexxDeregisterFunction( RxLvmFunctionTbl[i] );
 | 
|---|
| 136 | 
 | 
|---|
| 137 |     MAKERXSTRING( *prsResult, "", 0 );
 | 
|---|
| 138 |     return ( 0 );
 | 
|---|
| 139 | }
 | 
|---|
| 140 | 
 | 
|---|
| 141 | 
 | 
|---|
| 142 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 143 |  * RxLvmVersion                                                              *
 | 
|---|
| 144 |  *                                                                           *
 | 
|---|
| 145 |  * Returns the current version string.                                       *
 | 
|---|
| 146 |  *                                                                           *
 | 
|---|
| 147 |  * REXX ARGUMENTS:    none                                                   *
 | 
|---|
| 148 |  * REXX RETURN VALUE: current version in the form "major.minor.refresh"      *
 | 
|---|
| 149 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 150 | ULONG APIENTRY RxLvmVersion( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 151 | {
 | 
|---|
| 152 |     CHAR szVersion[ 12 ];
 | 
|---|
| 153 | 
 | 
|---|
| 154 |     if ( argc > 0 ) return ( 40 );
 | 
|---|
| 155 |     sprintf( szVersion, "%d.%d.%d", US_VERSION_MAJOR, US_VERSION_MINOR, US_VERSION_REFRESH );
 | 
|---|
| 156 |     MAKERXSTRING( *prsResult, szVersion, strlen(szVersion) );
 | 
|---|
| 157 |     return ( 0 );
 | 
|---|
| 158 | }
 | 
|---|
| 159 | 
 | 
|---|
| 160 | 
 | 
|---|
| 161 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 162 |  * RxLvmRediscoverPRM()                                                      *
 | 
|---|
| 163 |  *                                                                           *
 | 
|---|
| 164 |  * Checks to see if any Partitionable Removeable Media (e.g. Zip disks) have *
 | 
|---|
| 165 |  * been inserted since the last check.  IMPORTANT: the LVM Engine must be    *
 | 
|---|
| 166 |  * CLOSED before this function may be called.  This function will fail if    *
 | 
|---|
| 167 |  * the LVM Engine is open.                                                   *
 | 
|---|
| 168 |  *                                                                           *
 | 
|---|
| 169 |  * REXX ARGUMENTS:    none                                                   *
 | 
|---|
| 170 |  * REXX RETURN VALUE: "" or error string                                     *
 | 
|---|
| 171 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 172 | ULONG APIENTRY RxLvmRediscoverPRM( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 173 | {
 | 
|---|
| 174 |     ULONG ulError;      // LVM.DLL error indicator
 | 
|---|
| 175 | 
 | 
|---|
| 176 |     if ( argc > 0 ) return ( 40 );
 | 
|---|
| 177 |     Rediscover_PRMs( &ulError );
 | 
|---|
| 178 |     if ( ulError != LVM_ENGINE_NO_ERROR ) EngineError( prsResult, ulError );
 | 
|---|
| 179 |     else MAKERXSTRING( *prsResult, "", 0 );
 | 
|---|
| 180 |     return ( 0 );
 | 
|---|
| 181 | }
 | 
|---|
| 182 | 
 | 
|---|
| 183 | 
 | 
|---|
| 184 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 185 |  * RxLvmEngineOpen                                                           *
 | 
|---|
| 186 |  *                                                                           *
 | 
|---|
| 187 |  * Opens the LVM engine (LVM.DLL), which is required for all LVM operations  *
 | 
|---|
| 188 |  * (except, for some reason, the Rediscover_PRMs operation).                 *
 | 
|---|
| 189 |  *                                                                           *
 | 
|---|
| 190 |  * REXX ARGUMENTS:    none                                                   *
 | 
|---|
| 191 |  * REXX RETURN VALUE: "" or error string                                     *
 | 
|---|
| 192 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 193 | ULONG APIENTRY RxLvmEngineOpen( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 194 | {
 | 
|---|
| 195 |     ULONG ulError;
 | 
|---|
| 196 | 
 | 
|---|
| 197 |     if ( argc > 0 ) return ( 40 );
 | 
|---|
| 198 |     Open_LVM_Engine( TRUE, &ulError );
 | 
|---|
| 199 |     if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 200 |         EngineError( prsResult, ulError );
 | 
|---|
| 201 |         return ( 0 );
 | 
|---|
| 202 |     }
 | 
|---|
| 203 |     MAKERXSTRING( *prsResult, "", 0 );
 | 
|---|
| 204 |     return ( 0 );
 | 
|---|
| 205 | }
 | 
|---|
| 206 | 
 | 
|---|
| 207 | 
 | 
|---|
| 208 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 209 |  * RxLvmEngineClose                                                          *
 | 
|---|
| 210 |  *                                                                           *
 | 
|---|
| 211 |  * Closes the LVM engine.                                                    *
 | 
|---|
| 212 |  *                                                                           *
 | 
|---|
| 213 |  * REXX ARGUMENTS:    none                                                   *
 | 
|---|
| 214 |  * REXX RETURN VALUE: "" or error string                                     *
 | 
|---|
| 215 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 216 | ULONG APIENTRY RxLvmEngineClose( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 217 | {
 | 
|---|
| 218 |     if ( argc > 0 ) return ( 40 );
 | 
|---|
| 219 |     Close_LVM_Engine();
 | 
|---|
| 220 |     MAKERXSTRING( *prsResult, "", 0 );
 | 
|---|
| 221 |     return ( 0 );
 | 
|---|
| 222 | }
 | 
|---|
| 223 | 
 | 
|---|
| 224 | 
 | 
|---|
| 225 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 226 |  * RxLvmBootMgrInfo                                                          *
 | 
|---|
| 227 |  *                                                                           *
 | 
|---|
| 228 |  * REXX ARGUMENTS: none                                                      *
 | 
|---|
| 229 |  *                                                                           *
 | 
|---|
| 230 |  * REXX RETURN VALUE:                                                        *
 | 
|---|
| 231 |  *   "" if Boot Manager is not installed.  If an LVM error occurs, an error  *
 | 
|---|
| 232 |  *   string is returned.  Otherwise, the returned string is in the format:   *
 | 
|---|
| 233 |  *   "<disk> <active> <timeout> <default-type> <default-handle>".  As usual, *
 | 
|---|
| 234 |  *   can also return an error string if an LVM error occurs.                 *
 | 
|---|
| 235 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 236 | ULONG APIENTRY RxLvmBootMgrInfo( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 237 | {
 | 
|---|
| 238 |     // Data structures defined by LVM.DLL that we use for our queries
 | 
|---|
| 239 |     Partition_Information_Record enginePartitionInfo;
 | 
|---|
| 240 |     Drive_Control_Array          engineDisks;
 | 
|---|
| 241 |     Drive_Control_Record         engineCurrentDisk;
 | 
|---|
| 242 | 
 | 
|---|
| 243 |     ULONG   ulDisk = 0,     // Number of the physical disk Boot Manager is on
 | 
|---|
| 244 |             i,              // Guess :)
 | 
|---|
| 245 |             ulTimeout,      // Indicates the timeout value for a timeout boot
 | 
|---|
| 246 |             ulError;        // LVM.DLL error indicator
 | 
|---|
| 247 |     ADDRESS partition,      // LVM handle of physical Boot Manager partition
 | 
|---|
| 248 |             drive,          // LVM handle of the disk drive Boot Manager is on
 | 
|---|
| 249 |             defaultEntry;   // LVM handle of the default boot menu entry
 | 
|---|
| 250 |     BOOLEAN fVolume,        // Indicates whether said entry is a volume rather just than a partition
 | 
|---|
| 251 |             fAdvanced,      // Indicates whether Advanced (verbose) view mode is used
 | 
|---|
| 252 |             fTimeout,       // Indicates whether a timeout boot will occur
 | 
|---|
| 253 |             fActive;        // Indicates whether the Boot Manager partition is 'active'
 | 
|---|
| 254 |     CHAR    szInfo[ US_BMINFO_MAXZ ];   // Buffer used to build the final return string
 | 
|---|
| 255 | 
 | 
|---|
| 256 | 
 | 
|---|
| 257 |     if ( argc > 0 ) return ( 40 );
 | 
|---|
| 258 | 
 | 
|---|
| 259 |     // Query the Boot Manager partition handle
 | 
|---|
| 260 |     partition = Get_Boot_Manager_Handle( &ulError );
 | 
|---|
| 261 |     if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 262 |         EngineError( prsResult, ulError );
 | 
|---|
| 263 |         return ( 0 );
 | 
|---|
| 264 |     }
 | 
|---|
| 265 | 
 | 
|---|
| 266 |     // Return '' if Boot Manager is not installed
 | 
|---|
| 267 |     if ( partition == NULL ) {
 | 
|---|
| 268 |         MAKERXSTRING( *prsResult, "", 0 );
 | 
|---|
| 269 |         return ( 0 );
 | 
|---|
| 270 |     }
 | 
|---|
| 271 | 
 | 
|---|
| 272 |     // Find out what disk drive the Boot Manager partition resides on
 | 
|---|
| 273 |     enginePartitionInfo = Get_Partition_Information( partition, &ulError );
 | 
|---|
| 274 |     if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 275 |         EngineError( prsResult, ulError );
 | 
|---|
| 276 |         return ( 0 );
 | 
|---|
| 277 |     }
 | 
|---|
| 278 |     drive = enginePartitionInfo.Drive_Handle;
 | 
|---|
| 279 |     engineDisks = Get_Drive_Control_Data( &ulError );
 | 
|---|
| 280 |     if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 281 |         EngineError( prsResult, ulError );
 | 
|---|
| 282 |         return ( 0 );
 | 
|---|
| 283 |     }
 | 
|---|
| 284 |     for ( i = 0; i < engineDisks.Count; i++ ) {
 | 
|---|
| 285 |         engineCurrentDisk = engineDisks.Drive_Control_Data[ i ];
 | 
|---|
| 286 |         if ( engineCurrentDisk.Drive_Handle == drive )
 | 
|---|
| 287 |             ulDisk = engineCurrentDisk.Drive_Number;
 | 
|---|
| 288 |     }
 | 
|---|
| 289 | 
 | 
|---|
| 290 |     // Get the current Boot Manager configuration
 | 
|---|
| 291 |     Get_Boot_Manager_Options( &defaultEntry, &fVolume,
 | 
|---|
| 292 |                               &fTimeout,     &ulTimeout,
 | 
|---|
| 293 |                               &fAdvanced,    &ulError   );
 | 
|---|
| 294 |     if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 295 |         EngineError( prsResult, ulError );
 | 
|---|
| 296 |         return ( 0 );
 | 
|---|
| 297 |     }
 | 
|---|
| 298 | 
 | 
|---|
| 299 |     // Figure out if Boot Manager is 'active'
 | 
|---|
| 300 |     if ( enginePartitionInfo.Active_Flag == ACTIVE_PARTITION )
 | 
|---|
| 301 |         fActive = TRUE;
 | 
|---|
| 302 |     else
 | 
|---|
| 303 |         fActive = FALSE;
 | 
|---|
| 304 | 
 | 
|---|
| 305 |     // Now return all the nice data
 | 
|---|
| 306 |     sprintf( szInfo, "%d %d %d %d %X", ulDisk, fActive, ulTimeout, fVolume, defaultEntry );
 | 
|---|
| 307 |     MAKERXSTRING( *prsResult, szInfo, strlen(szInfo) );
 | 
|---|
| 308 |     return ( 0 );
 | 
|---|
| 309 | }
 | 
|---|
| 310 | 
 | 
|---|
| 311 | 
 | 
|---|
| 312 | 
 | 
|---|
| 313 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 314 |  * RxLvmBootMgrMenu()                                                        *
 | 
|---|
| 315 |  *                                                                           *
 | 
|---|
| 316 |  * Returns the list of volumes and/or partitions on the Boot Manager menu    *
 | 
|---|
| 317 |  * (i.e. have the 'bootable' flag set).                                      *
 | 
|---|
| 318 |  *                                                                           *
 | 
|---|
| 319 |  * Data representing the menu entries is written to the specified REXX       *
 | 
|---|
| 320 |  * variable.  stem.0 contains the number of entries, and each other item is: *
 | 
|---|
| 321 |  * "<handle> <type> <name>"                                                  *
 | 
|---|
| 322 |  * e.g. menu.1 == "0C0FB884 V OS/2 System"                                   *
 | 
|---|
| 323 |  *                                                                           *
 | 
|---|
| 324 |  * REXX ARGUMENTS:    name of the REXX stem variable to populate             *
 | 
|---|
| 325 |  *                                                                           *
 | 
|---|
| 326 |  * REXX RETURN VALUE: "1" or error string                                    *
 | 
|---|
| 327 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 328 | ULONG APIENTRY RxLvmBootMgrMenu( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 329 | {
 | 
|---|
| 330 |     // Data structures defined by LVM.DLL that we use for our queries
 | 
|---|
| 331 |     Boot_Manager_Menu            engineBootMenu;
 | 
|---|
| 332 |     Boot_Manager_Menu_Item       engineBootMenuEntry;
 | 
|---|
| 333 |     Volume_Information_Record    engineVolumeInfo;
 | 
|---|
| 334 |     Partition_Information_Record enginePartitionInfo;
 | 
|---|
| 335 | 
 | 
|---|
| 336 |     ULONG  ulError,                     // LVM Engine error code
 | 
|---|
| 337 |            i;
 | 
|---|
| 338 |     CHAR   szStem[ US_STEM_MAXZ ],      // Buffers used for building strings ...
 | 
|---|
| 339 |            szNumber[ US_INTEGER_MAXZ ],
 | 
|---|
| 340 |            szMenuItem[ US_SZINFO_MAXZ ];
 | 
|---|
| 341 |     USHORT usRemoveable = 0;
 | 
|---|
| 342 | 
 | 
|---|
| 343 | 
 | 
|---|
| 344 |     // Do some validity checking on the arguments
 | 
|---|
| 345 |     if (( argc != 1 ) ||                        // Make sure we have exactly one argument...
 | 
|---|
| 346 |         ( ! RXVALIDSTRING(argv[0]) ) ||         // ...which is a valid REXX string...
 | 
|---|
| 347 |         ( RXSTRLEN(argv[0]) > US_STEM_MAXZ ))   // ...and isn't too long.
 | 
|---|
| 348 |         return ( 40 );
 | 
|---|
| 349 | 
 | 
|---|
| 350 |     engineBootMenu = Get_Boot_Manager_Menu( &ulError );
 | 
|---|
| 351 |     if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 352 |         EngineError( prsResult, ulError );
 | 
|---|
| 353 |         return ( 0 );
 | 
|---|
| 354 |     }
 | 
|---|
| 355 | 
 | 
|---|
| 356 |     // Generate the stem variable name from the argument (stripping any final dot)
 | 
|---|
| 357 |     if ( argv[0].strptr[ argv[0].strlength-1 ] == '.') argv[0].strlength--;
 | 
|---|
| 358 |     strncpy( szStem, argv[0].strptr, RXSTRLEN(argv[0]) );
 | 
|---|
| 359 |     szStem[ RXSTRLEN(argv[0]) ] = '\0';
 | 
|---|
| 360 | 
 | 
|---|
| 361 |     // Create a stem.0 element containing the number of disks
 | 
|---|
| 362 |     sprintf( szNumber, "%d", engineBootMenu.Count );
 | 
|---|
| 363 |     WriteStemElement( szStem, 0, szNumber );
 | 
|---|
| 364 | 
 | 
|---|
| 365 |     for ( i = 0; i < engineBootMenu.Count; i++ ) {
 | 
|---|
| 366 |         engineBootMenuEntry = engineBootMenu.Menu_Items[ i ];
 | 
|---|
| 367 |         if ( engineBootMenuEntry.Volume ) {
 | 
|---|
| 368 |             engineVolumeInfo = Get_Volume_Information( engineBootMenuEntry.Handle, &ulError );
 | 
|---|
| 369 |             if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 370 |                 EngineError( prsResult, ulError );
 | 
|---|
| 371 |                 return ( 0 );
 | 
|---|
| 372 |             }
 | 
|---|
| 373 |             sprintf( szMenuItem, "%08X 1 %s", engineBootMenuEntry.Handle, engineVolumeInfo.Volume_Name );
 | 
|---|
| 374 |         } else {
 | 
|---|
| 375 |             enginePartitionInfo = Get_Partition_Information( engineBootMenuEntry.Handle, &ulError );
 | 
|---|
| 376 |             if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 377 |                 EngineError( prsResult, ulError );
 | 
|---|
| 378 |                 return ( 0 );
 | 
|---|
| 379 |             }
 | 
|---|
| 380 |             sprintf( szMenuItem, "%08X 0 %s", engineBootMenuEntry.Handle, enginePartitionInfo.Partition_Name );
 | 
|---|
| 381 |         }
 | 
|---|
| 382 |         // Create a stem variable item for the current disk
 | 
|---|
| 383 |         WriteStemElement( szStem, i+1, szMenuItem );
 | 
|---|
| 384 |     }
 | 
|---|
| 385 | 
 | 
|---|
| 386 |     // Always return a standard value (1) on success
 | 
|---|
| 387 |     MAKERXSTRING( *prsResult, "1", 1 );
 | 
|---|
| 388 |     return ( 0 );
 | 
|---|
| 389 | }
 | 
|---|
| 390 | 
 | 
|---|
| 391 | 
 | 
|---|
| 392 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 393 |  * RxLvmGetDisks                                                             *
 | 
|---|
| 394 |  *                                                                           *
 | 
|---|
| 395 |  * Data representing all disk drives is written to the specified REXX        *
 | 
|---|
| 396 |  * variable.  stem.0 contains the number of disks, and each other item is:   *
 | 
|---|
| 397 |  * "<handle> <num> <size> <unusable> <corrupt> <removable> <serial> <name>"  *
 | 
|---|
| 398 |  * e.g. disks.1 == "0C0FB884 1 156327 0 0 0 485209174 [ D1 ]"                *
 | 
|---|
| 399 |  *                                                                           *
 | 
|---|
| 400 |  * REXX ARGUMENTS:    name of the REXX stem variable to populate             *
 | 
|---|
| 401 |  *                                                                           *
 | 
|---|
| 402 |  * REXX RETURN VALUE: "1" or error string                                    *
 | 
|---|
| 403 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 404 | ULONG APIENTRY RxLvmGetDisks( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 405 | {
 | 
|---|
| 406 |     // Data structures defined by LVM.DLL that we use for our queries
 | 
|---|
| 407 |     Drive_Control_Array      engineDrives;
 | 
|---|
| 408 |     Drive_Control_Record     engineDriveRecord;
 | 
|---|
| 409 |     Drive_Information_Record engineDriveInfo;
 | 
|---|
| 410 | 
 | 
|---|
| 411 |     ULONG  ulError,
 | 
|---|
| 412 |            i,
 | 
|---|
| 413 |            ulSize,
 | 
|---|
| 414 |            ulSerial;
 | 
|---|
| 415 |     CHAR   szStem[ US_STEM_MAXZ ],      // Buffers used for building strings ...
 | 
|---|
| 416 |            szNumber[ US_INTEGER_MAXZ ],
 | 
|---|
| 417 |            szDiskInfo[ US_STEM_MAXZ ];
 | 
|---|
| 418 |     USHORT usRemoveable = 0;
 | 
|---|
| 419 |     BOOL   fUnuseable = FALSE,
 | 
|---|
| 420 |            fCorrupt   = FALSE;
 | 
|---|
| 421 | 
 | 
|---|
| 422 | 
 | 
|---|
| 423 |     // Do some validity checking on the arguments
 | 
|---|
| 424 |     if (( argc != 1 ) ||                        // Make sure we have exactly one argument...
 | 
|---|
| 425 |         ( ! RXVALIDSTRING(argv[0]) ) ||         // ...which is a valid REXX string...
 | 
|---|
| 426 |         ( RXSTRLEN(argv[0]) > US_STEM_MAXZ ))   // ...and isn't too long.
 | 
|---|
| 427 |         return ( 40 );
 | 
|---|
| 428 | 
 | 
|---|
| 429 |     // Get the list of disks from LVM.DLL
 | 
|---|
| 430 |     engineDrives = Get_Drive_Control_Data( &ulError );
 | 
|---|
| 431 |     if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 432 |         EngineError( prsResult, ulError );
 | 
|---|
| 433 |         return ( 0 );
 | 
|---|
| 434 |     }
 | 
|---|
| 435 | 
 | 
|---|
| 436 |     // Generate the stem variable name from the argument (stripping any final dot)
 | 
|---|
| 437 |     if ( argv[0].strptr[ argv[0].strlength-1 ] == '.') argv[0].strlength--;
 | 
|---|
| 438 |     strncpy( szStem, argv[0].strptr, RXSTRLEN(argv[0]) );
 | 
|---|
| 439 |     szStem[ RXSTRLEN(argv[0]) ] = '\0';
 | 
|---|
| 440 | 
 | 
|---|
| 441 |     // Create a stem.0 element containing the number of disks
 | 
|---|
| 442 |     sprintf( szNumber, "%d", engineDrives.Count );
 | 
|---|
| 443 |     WriteStemElement( szStem, 0, szNumber );
 | 
|---|
| 444 | 
 | 
|---|
| 445 |     // Now generate the information for each disk
 | 
|---|
| 446 |     for ( i = 0; i < engineDrives.Count; i++ ) {
 | 
|---|
| 447 | 
 | 
|---|
| 448 |         // Get the current drive information
 | 
|---|
| 449 |         engineDriveRecord = engineDrives.Drive_Control_Data[ i ];
 | 
|---|
| 450 |         engineDriveInfo = Get_Drive_Status( engineDriveRecord.Drive_Handle, &ulError );
 | 
|---|
| 451 |         if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 452 |             EngineError( prsResult, ulError );
 | 
|---|
| 453 |             return ( 0 );
 | 
|---|
| 454 |         }
 | 
|---|
| 455 | 
 | 
|---|
| 456 |         if ( engineDriveRecord.Drive_Is_PRM ) usRemoveable = US_RMEDIA_PRM;
 | 
|---|
| 457 |         if ( engineDriveInfo.Is_Big_Floppy  ) usRemoveable = US_RMEDIA_BIGFLOPPY;
 | 
|---|
| 458 | 
 | 
|---|
| 459 |         if (( engineDriveInfo.Is_Big_Floppy ) || ( engineDriveInfo.Unusable )) {
 | 
|---|
| 460 |             fUnuseable = TRUE;
 | 
|---|
| 461 |             ulSize     = 0;
 | 
|---|
| 462 |             ulSerial   = 0;
 | 
|---|
| 463 |         } else {
 | 
|---|
| 464 |             if ( engineDriveInfo.Corrupt_Partition_Table ) fCorrupt = TRUE;
 | 
|---|
| 465 |             ulSize   = ( engineDriveRecord.Drive_Size ) / UL_SECTORS_PER_MB;
 | 
|---|
| 466 |             ulSerial = engineDriveRecord.Drive_Serial_Number;
 | 
|---|
| 467 |         }
 | 
|---|
| 468 | 
 | 
|---|
| 469 |         sprintf( szDiskInfo, "%08X %d %d %d %d %d %d %s",
 | 
|---|
| 470 |                  engineDriveRecord.Drive_Handle,
 | 
|---|
| 471 |                  engineDriveRecord.Drive_Number,
 | 
|---|
| 472 |                  ulSize,
 | 
|---|
| 473 |                  fUnuseable,
 | 
|---|
| 474 |                  fCorrupt,
 | 
|---|
| 475 |                  usRemoveable,
 | 
|---|
| 476 |                  ulSerial,
 | 
|---|
| 477 |                  engineDriveInfo.Drive_Name             );
 | 
|---|
| 478 | 
 | 
|---|
| 479 |         // Create a stem variable item for the current disk
 | 
|---|
| 480 |         WriteStemElement( szStem, i+1, szDiskInfo );
 | 
|---|
| 481 | 
 | 
|---|
| 482 |     }
 | 
|---|
| 483 |     // Free the LVM data structures
 | 
|---|
| 484 |     Free_Engine_Memory( engineDrives.Drive_Control_Data );
 | 
|---|
| 485 | 
 | 
|---|
| 486 |     // Always return a standard value (1) on success
 | 
|---|
| 487 |     MAKERXSTRING( *prsResult, "1", 1 );
 | 
|---|
| 488 |     return ( 0 );
 | 
|---|
| 489 | }
 | 
|---|
| 490 | 
 | 
|---|
| 491 | 
 | 
|---|
| 492 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 493 |  * RxLvmGetPartitions                                                        *
 | 
|---|
| 494 |  *                                                                           *
 | 
|---|
| 495 |  * Data representing all partitions belonging to the specified object is     *
 | 
|---|
| 496 |  * written to the specified REXX variable.  stem.0 contains the number of    *
 | 
|---|
| 497 |  * disks, and each other item is:                                            *
 | 
|---|
| 498 |  * "<phandle> <dhandle> <vhandle> <status> <fs> <size> <os> <boot> <name>"   *
 | 
|---|
| 499 |  * e.g. parts.1 == "FC177C67 FC177717 FC179B17 C HPFS 2047 07 N OS/2"        *
 | 
|---|
| 500 |  *                                                                           *
 | 
|---|
| 501 |  * REXX ARGUMENTS:    1 - handle of the object to query                      *
 | 
|---|
| 502 |  *                    2 - name of the REXX stem variable to populate         *
 | 
|---|
| 503 |  *                                                                           *
 | 
|---|
| 504 |  * REXX RETURN VALUE: "1" or error string                                    *
 | 
|---|
| 505 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 506 | ULONG APIENTRY RxLvmGetPartitions( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 507 | {
 | 
|---|
| 508 |     // Data structures defined by LVM.DLL that we use for our queries
 | 
|---|
| 509 |     Partition_Information_Array  enginePartitions;
 | 
|---|
| 510 |     Partition_Information_Record enginePartInfo;
 | 
|---|
| 511 |     Volume_Information_Record    engineVolumeInfo;
 | 
|---|
| 512 | 
 | 
|---|
| 513 |     ADDRESS ulHandle;                    // requested handle
 | 
|---|
| 514 |     ULONG   ulError,                     // LVM.DLL error indicator
 | 
|---|
| 515 |             i,                           // Duh
 | 
|---|
| 516 |             ulRc;                        // Used for return code
 | 
|---|
| 517 |     PSZ     pszCompound,                 // The current compound variable name
 | 
|---|
| 518 |             pszPartInfo;                 // The current partition info string
 | 
|---|
| 519 |     CHAR    szStem[ US_STEM_MAXZ ],      // Buffers used for building strings ...
 | 
|---|
| 520 |             szNumber[ US_INTEGER_MAXZ ],
 | 
|---|
| 521 |             szDevice[ US_DEVTYPE_MAXZ ],
 | 
|---|
| 522 |             szPartInfo[ US_STEM_MAXZ ],
 | 
|---|
| 523 |             cStatus,                     // adjusted partition status flag
 | 
|---|
| 524 |             cBootable;                   // Partition bootable flag (N/B/S/I)
 | 
|---|
| 525 | 
 | 
|---|
| 526 | 
 | 
|---|
| 527 |     // Do some validity checking on the arguments
 | 
|---|
| 528 |     if (( argc != 2 ) ||                        // Make sure we have exactly two arguments...
 | 
|---|
| 529 |         ( ! RXVALIDSTRING(argv[0]) ) ||         // ...which are valid REXX strings...
 | 
|---|
| 530 |         ( ! RXVALIDSTRING(argv[1]) ) ||
 | 
|---|
| 531 |         ( RXSTRLEN(argv[1]) > US_STEM_MAXZ )    // ...and the stem name isn't too long.
 | 
|---|
| 532 |        )
 | 
|---|
| 533 |         return ( 40 );
 | 
|---|
| 534 | 
 | 
|---|
| 535 |     // Parse the handle argument
 | 
|---|
| 536 |     if ( sscanf( argv[0].strptr, "%X", &ulHandle ) < 1 )
 | 
|---|
| 537 |         return ( 40 );
 | 
|---|
| 538 | 
 | 
|---|
| 539 |     // Get the list of partitions from LVM.DLL
 | 
|---|
| 540 |     enginePartitions = Get_Partitions( ulHandle, &ulError );
 | 
|---|
| 541 |     if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 542 |         EngineError( prsResult, ulError );
 | 
|---|
| 543 |         return ( 0 );
 | 
|---|
| 544 |     }
 | 
|---|
| 545 | 
 | 
|---|
| 546 |     // Generate the stem variable name from the argument
 | 
|---|
| 547 |     // (and strip any terminating dot while we're at it)
 | 
|---|
| 548 |     if ( argv[1].strptr[ argv[1].strlength-1 ] == '.') argv[1].strlength--;
 | 
|---|
| 549 |     strncpy( szStem, argv[1].strptr, RXSTRLEN(argv[1]) );
 | 
|---|
| 550 |     szStem[ RXSTRLEN(argv[1]) ] = '\0';
 | 
|---|
| 551 | 
 | 
|---|
| 552 |     // Create a stem.0 element containing the number of volumes
 | 
|---|
| 553 |     sprintf( szNumber, "%d", enginePartitions.Count );
 | 
|---|
| 554 |     WriteStemElement( szStem, 0, szNumber );
 | 
|---|
| 555 | 
 | 
|---|
| 556 |     // Now generate the information for each partition
 | 
|---|
| 557 |     for ( i = 0; i < enginePartitions.Count; i++ ) {
 | 
|---|
| 558 |         enginePartInfo = enginePartitions.Partition_Array[ i ];
 | 
|---|
| 559 | 
 | 
|---|
| 560 |         switch ( enginePartInfo.Partition_Status ) {
 | 
|---|
| 561 |             case PARTITION_IS_FREE_SPACE:
 | 
|---|
| 562 |                 cStatus   = CH_PTYPE_FREESPACE;
 | 
|---|
| 563 |                 cBootable = CH_FBOOT_NONE;
 | 
|---|
| 564 |                 break;
 | 
|---|
| 565 | 
 | 
|---|
| 566 |             case PARTITION_IS_IN_USE:
 | 
|---|
| 567 |                 if ( enginePartInfo.Volume_Handle == NULL ) {
 | 
|---|
| 568 |                     // Marked "in use", but not part of a volume - probably Boot Manager
 | 
|---|
| 569 |                     cStatus = CH_PTYPE_INUSE;
 | 
|---|
| 570 |                     if ( enginePartInfo.Active_Flag == ACTIVE_PARTITION )
 | 
|---|
| 571 |                         cBootable = CH_FBOOT_STARTABLE;
 | 
|---|
| 572 |                     else if ( enginePartInfo.On_Boot_Manager_Menu )
 | 
|---|
| 573 |                         cBootable = CH_FBOOT_BOOTABLE;
 | 
|---|
| 574 |                     else
 | 
|---|
| 575 |                         cBootable = CH_FBOOT_NONE;
 | 
|---|
| 576 |                 } else {
 | 
|---|
| 577 |                     // Partition belongs to a volume
 | 
|---|
| 578 |                     switch ( enginePartInfo.Partition_Type ) {
 | 
|---|
| 579 |                         case 0 : cStatus = CH_PTYPE_FREESPACE;  break;  // Free space
 | 
|---|
| 580 |                         case 1 : cStatus = CH_PTYPE_LVOLUME;    break;  // (Part of) LVM volume
 | 
|---|
| 581 |                         case 2 : cStatus = CH_PTYPE_CVOLUME;    break;  // Compatibility volume
 | 
|---|
| 582 |                         default: cStatus = CH_PTYPE_UNKNOWN;    break;  // Unknown/error
 | 
|---|
| 583 |                     }
 | 
|---|
| 584 |                     engineVolumeInfo = Get_Volume_Information( enginePartInfo.Volume_Handle, &ulError );
 | 
|---|
| 585 |                     if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 586 |                         EngineError( prsResult, ulError );
 | 
|---|
| 587 |                         return ( 0 );
 | 
|---|
| 588 |                     }
 | 
|---|
| 589 |                     switch ( engineVolumeInfo.Status ) {
 | 
|---|
| 590 |                         case 1 : cBootable = CH_FBOOT_BOOTABLE;   break;
 | 
|---|
| 591 |                         case 2 : cBootable = CH_FBOOT_STARTABLE;  break;
 | 
|---|
| 592 |                         case 3 : cBootable = CH_FBOOT_INSTABLE;   break;
 | 
|---|
| 593 |                         default: cBootable = CH_FBOOT_NONE;       break;
 | 
|---|
| 594 |                     }
 | 
|---|
| 595 |                 }
 | 
|---|
| 596 |                 break;
 | 
|---|
| 597 | 
 | 
|---|
| 598 |             case PARTITION_IS_AVAILABLE:
 | 
|---|
| 599 |                 cStatus = CH_PTYPE_AVAILABLE;
 | 
|---|
| 600 |                 if ( enginePartInfo.Active_Flag == ACTIVE_PARTITION ) cBootable = CH_FBOOT_STARTABLE;
 | 
|---|
| 601 |                 else if ( enginePartInfo.On_Boot_Manager_Menu )       cBootable = CH_FBOOT_BOOTABLE;
 | 
|---|
| 602 |                 else                                                  cBootable = CH_FBOOT_NONE;
 | 
|---|
| 603 |                 break;
 | 
|---|
| 604 | 
 | 
|---|
| 605 |             default:
 | 
|---|
| 606 |                 // Fall-through; should be unreachable
 | 
|---|
| 607 |                 cStatus   = CH_PTYPE_UNKNOWN;
 | 
|---|
| 608 |                 cBootable = CH_FBOOT_NONE;
 | 
|---|
| 609 |                 break;
 | 
|---|
| 610 |         }
 | 
|---|
| 611 | 
 | 
|---|
| 612 |         sprintf( szPartInfo, "%08X %08X %08X %c %s %d %02X %c %s",
 | 
|---|
| 613 |                  enginePartInfo.Partition_Handle,
 | 
|---|
| 614 |                  enginePartInfo.Drive_Handle,
 | 
|---|
| 615 |                  enginePartInfo.Volume_Handle,
 | 
|---|
| 616 |                  cStatus,
 | 
|---|
| 617 |                  FixedPartitionFileSystem( enginePartInfo.OS_Flag, enginePartInfo.File_System_Name ),
 | 
|---|
| 618 |                  enginePartInfo.Usable_Partition_Size / UL_SECTORS_PER_MB,
 | 
|---|
| 619 |                  enginePartInfo.OS_Flag,
 | 
|---|
| 620 |                  cBootable,
 | 
|---|
| 621 |                  enginePartInfo.Partition_Name );
 | 
|---|
| 622 | 
 | 
|---|
| 623 |         // Create a stem variable item for the current partition
 | 
|---|
| 624 |         WriteStemElement( szStem, i+1, szPartInfo );
 | 
|---|
| 625 | 
 | 
|---|
| 626 |     }
 | 
|---|
| 627 | 
 | 
|---|
| 628 |     // Free the LVM data structures
 | 
|---|
| 629 |     Free_Engine_Memory( enginePartitions.Partition_Array );
 | 
|---|
| 630 | 
 | 
|---|
| 631 |     // Always return a standard value (1) on success
 | 
|---|
| 632 |     MAKERXSTRING( *prsResult, "1", 1 );
 | 
|---|
| 633 |     return ( 0 );
 | 
|---|
| 634 | }
 | 
|---|
| 635 | 
 | 
|---|
| 636 | 
 | 
|---|
| 637 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 638 |  * RxLvmGetVolumes                                                           *
 | 
|---|
| 639 |  *                                                                           *
 | 
|---|
| 640 |  * Data representing all logical volumes is written to the specified REXX    *
 | 
|---|
| 641 |  * variable.  stem.0 contains the number of volumes, and each other item is: *
 | 
|---|
| 642 |  * "<handle> <letter> <pref> <fs> <size> <dev> <type> <bootable> <name>"     *
 | 
|---|
| 643 |  * e.g. volumes.1 == "0A00CDB1 C C HPFS 2047 HDD 0 B eComStation"            *
 | 
|---|
| 644 |  *                                                                           *
 | 
|---|
| 645 |  * REXX ARGUMENTS:    name of the REXX stem variable to populate             *
 | 
|---|
| 646 |  *                                                                           *
 | 
|---|
| 647 |  * REXX RETURN VALUE: "1" or error string                                    *
 | 
|---|
| 648 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 649 | ULONG APIENTRY RxLvmGetVolumes( PSZ pszName, ULONG argc, RXSTRING argv[], PSZ pszQueue, PRXSTRING prsResult )
 | 
|---|
| 650 | {
 | 
|---|
| 651 |     // Data structures defined by LVM.DLL that we use for our queries
 | 
|---|
| 652 |     Volume_Control_Array         engineVolumes;
 | 
|---|
| 653 |     Volume_Information_Record    engineVolumeInfo;
 | 
|---|
| 654 |     Partition_Information_Array  enginePartitions;
 | 
|---|
| 655 |     Partition_Information_Record enginePartInfo;
 | 
|---|
| 656 | 
 | 
|---|
| 657 |     ULONG     ulError,                  // LVM.DLL error indicator
 | 
|---|
| 658 |               i,                        // Duh
 | 
|---|
| 659 |               ulRc;                     // Used for return code
 | 
|---|
| 660 |     USHORT    usVolType;                // Volume type flag (0 or 1)
 | 
|---|
| 661 |     PSZ       pszCompound,              // The current compound variable name
 | 
|---|
| 662 |               pszVolInfo;               // The current volume info string
 | 
|---|
| 663 |     CHAR      szStem[ US_STEM_MAXZ ],   // Buffers used for building strings ...
 | 
|---|
| 664 |               szNumber[ US_INTEGER_MAXZ ],
 | 
|---|
| 665 |               szDevice[ US_DEVTYPE_MAXZ ],
 | 
|---|
| 666 |               szVolInfo[ US_STEM_MAXZ ],
 | 
|---|
| 667 |               cCurrent,                 // A volume's current drive letter
 | 
|---|
| 668 |               cPreference,              // A volume's preferred drive letter
 | 
|---|
| 669 |               cBootable;                // Volume bootable flag (N/B/S/I)
 | 
|---|
| 670 |     BOOLEAN   fCompatible;              // Use to query volume type from LVM.DLL
 | 
|---|
| 671 | 
 | 
|---|
| 672 | 
 | 
|---|
| 673 |     // Do some validity checking on the arguments
 | 
|---|
| 674 |     if (( argc != 1 ) ||                        // Make sure we have exactly one argument...
 | 
|---|
| 675 |         ( ! RXVALIDSTRING(argv[0]) ) ||         // ...which is a valid REXX string...
 | 
|---|
| 676 |         ( RXSTRLEN(argv[0]) > US_STEM_MAXZ )    // ...and isn't too long.
 | 
|---|
| 677 |        )
 | 
|---|
| 678 |         return ( 40 );
 | 
|---|
| 679 | 
 | 
|---|
| 680 |     // Get the list of volumes from LVM.DLL
 | 
|---|
| 681 |     engineVolumes = Get_Volume_Control_Data( &ulError );
 | 
|---|
| 682 |     if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 683 |         EngineError( prsResult, ulError );
 | 
|---|
| 684 |         return ( 0 );
 | 
|---|
| 685 |     }
 | 
|---|
| 686 | 
 | 
|---|
| 687 |     // Generate the stem variable name from the argument
 | 
|---|
| 688 |     // (and strip any terminating dot while we're at it)
 | 
|---|
| 689 |     // if ( argv[0].strlength > US_STEM_MAXZ - 5 ) argv[0].strlength = US_STEM_MAXZ - 5;
 | 
|---|
| 690 |     if ( argv[0].strptr[ argv[0].strlength-1 ] == '.') argv[0].strlength--;
 | 
|---|
| 691 |     strncpy( szStem, argv[0].strptr, RXSTRLEN(argv[0]) );
 | 
|---|
| 692 |     szStem[ RXSTRLEN(argv[0]) ] = '\0';
 | 
|---|
| 693 | 
 | 
|---|
| 694 |     // Create a stem.0 element containing the number of volumes
 | 
|---|
| 695 |     sprintf( szNumber, "%d", engineVolumes.Count );
 | 
|---|
| 696 |     WriteStemElement( szStem, 0, szNumber );
 | 
|---|
| 697 | 
 | 
|---|
| 698 |     // Now generate the information for each volume
 | 
|---|
| 699 |     for ( i = 0; i < engineVolumes.Count; i++ ) {
 | 
|---|
| 700 | 
 | 
|---|
| 701 |         // Get the current volume information record
 | 
|---|
| 702 |         engineVolumeInfo = Get_Volume_Information( engineVolumes.Volume_Control_Data[ i ].Volume_Handle, &ulError );
 | 
|---|
| 703 |         if ( ulError != LVM_ENGINE_NO_ERROR ) {
 | 
|---|
| 704 |             EngineError( prsResult, ulError );
 | 
|---|
| 705 |             return ( 0 );
 | 
|---|
| 706 |         }
 | 
|---|
| 707 | 
 | 
|---|
| 708 |         // Now build our info-string that will be returned to the REXX program
 | 
|---|
| 709 |         switch ( engineVolumes.Volume_Control_Data[ i ].Device_Type ) {
 | 
|---|
| 710 |             case LVM_HARD_DRIVE : strcpy( szDevice, SZ_DEVICE_HDD );     break;
 | 
|---|
| 711 |             case LVM_PRM        : strcpy( szDevice, SZ_DEVICE_PRM );     break;
 | 
|---|
| 712 |             case NON_LVM_CDROM  : strcpy( szDevice, SZ_DEVICE_CDROM );   break;
 | 
|---|
| 713 |             case NETWORK_DRIVE  : strcpy( szDevice, SZ_DEVICE_NETWORK ); break;
 | 
|---|
| 714 |             default             : strcpy( szDevice, SZ_DEVICE_OTHER );   break;
 | 
|---|
| 715 |         }
 | 
|---|
| 716 |         usVolType = ! engineVolumeInfo.Compatibility_Volume;
 | 
|---|
| 717 |         if ( engineVolumes.Volume_Control_Data[ i ].Device_Type >= NON_LVM_CDROM ) cBootable = CH_FBOOT_NONE;
 | 
|---|
| 718 |         else switch ( engineVolumeInfo.Status ) {
 | 
|---|
| 719 |             case 1 : cBootable = CH_FBOOT_BOOTABLE;  break;
 | 
|---|
| 720 |             case 2 : cBootable = CH_FBOOT_STARTABLE; break;
 | 
|---|
| 721 |             case 3 : cBootable = CH_FBOOT_INSTABLE;  break;
 | 
|---|
| 722 |             default: cBootable = CH_FBOOT_NONE;      break;
 | 
|---|
| 723 |         }
 | 
|---|
| 724 |         if ( isalpha(engineVolumeInfo.Current_Drive_Letter) | engineVolumeInfo.Current_Drive_Letter == '*')
 | 
|---|
| 725 |             cCurrent = engineVolumeInfo.Current_Drive_Letter;
 | 
|---|
| 726 |         else cCurrent = '?';
 | 
|---|
| 727 |         if ( isalpha(engineVolumeInfo.Drive_Letter_Preference) | engineVolumeInfo.Drive_Letter_Preference == '*')
 | 
|---|
| 728 |             cPreference = engineVolumeInfo.Drive_Letter_Preference;
 | 
|---|
| 729 |         else cPreference = '?';
 | 
|---|
| 730 | 
 | 
|---|
| 731 |         sprintf( szVolInfo, "%08X %c %c %s %d %s %d %c %s",
 | 
|---|
| 732 |                  engineVolumes.Volume_Control_Data[ i ].Volume_Handle,
 | 
|---|
| 733 |                  cCurrent,
 | 
|---|
| 734 |                  cPreference,
 | 
|---|
| 735 |                  FixedVolumeFileSystem( engineVolumes.Volume_Control_Data[ i ].Volume_Handle, engineVolumeInfo.File_System_Name ),
 | 
|---|
| 736 |                  engineVolumeInfo.Volume_Size / UL_SECTORS_PER_MB,
 | 
|---|
| 737 |                  szDevice,
 | 
|---|
| 738 |                  usVolType,
 | 
|---|
| 739 |                  cBootable,
 | 
|---|
| 740 |                  engineVolumeInfo.Volume_Name );
 | 
|---|
| 741 | 
 | 
|---|
| 742 |         // Create a stem variable item for the current volume
 | 
|---|
| 743 |         WriteStemElement( szStem, i+1, szVolInfo );
 | 
|---|
| 744 | 
 | 
|---|
| 745 |     }
 | 
|---|
| 746 | 
 | 
|---|
| 747 |     // Free the LVM data structures
 | 
|---|
| 748 |     Free_Engine_Memory( engineVolumes.Volume_Control_Data );
 | 
|---|
| 749 | 
 | 
|---|
| 750 |     // Always return a standard value (1) on success
 | 
|---|
| 751 |     MAKERXSTRING( *prsResult, "1", 1 );
 | 
|---|
| 752 |     return ( 0 );
 | 
|---|
| 753 | }
 | 
|---|
| 754 | 
 | 
|---|
| 755 | 
 | 
|---|
| 756 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 757 |  * FixedVolumeFileSystem                                                     *
 | 
|---|
| 758 |  *                                                                           *
 | 
|---|
| 759 |  * Double-checks the given volume's filesystem-type string in order to work  *
 | 
|---|
| 760 |  * around a bug in the LVM.DLL's reporting of Linux partition types.         *
 | 
|---|
| 761 |  * OS Flag 0x82 is Linux Swap, but LVM.DLL reports it as 'Linux'; 0x83 is    *
 | 
|---|
| 762 |  * Linux Native, but LVM.DLL reports it as '????'.                           *
 | 
|---|
| 763 |  *                                                                           *
 | 
|---|
| 764 |  * ARGUMENTS:                                                                *
 | 
|---|
| 765 |  *     ADDRESS volume        : Handle to the volume being queried            *
 | 
|---|
| 766 |  *     PSZ     pszReportedFS : FS name as reported by LVM.DLL                *
 | 
|---|
| 767 |  *                                                                           *
 | 
|---|
| 768 |  * RETURNS: PSZ                                                              *
 | 
|---|
| 769 |  *     The "fixed" filesystem string.                                        *
 | 
|---|
| 770 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 771 | PSZ FixedVolumeFileSystem( ADDRESS volume, PSZ pszReportedFS )
 | 
|---|
| 772 | {
 | 
|---|
| 773 |     Partition_Information_Array enginePartitions;
 | 
|---|
| 774 | 
 | 
|---|
| 775 |     ULONG ulError;
 | 
|---|
| 776 |     BYTE  fOS;
 | 
|---|
| 777 |     PSZ   s,
 | 
|---|
| 778 |           pszFixed;
 | 
|---|
| 779 | 
 | 
|---|
| 780 |     // Get the OS flag reported by the (first) underlying partition
 | 
|---|
| 781 |     enginePartitions = Get_Partitions( volume, &ulError );
 | 
|---|
| 782 |     if (( ulError != LVM_ENGINE_NO_ERROR ) || ( enginePartitions.Count == 0 )) {
 | 
|---|
| 783 |         if ( strlen(pszReportedFS) == 0 ) return "?";
 | 
|---|
| 784 |         while (( s = strchr( pszReportedFS, ' ')) != NULL ) *s = 0xFF;
 | 
|---|
| 785 |         return pszReportedFS;
 | 
|---|
| 786 |     }
 | 
|---|
| 787 | 
 | 
|---|
| 788 |     // Now fix the reported file system based on the OS flag
 | 
|---|
| 789 |     pszFixed = FixedPartitionFileSystem( enginePartitions.Partition_Array[ 0 ].OS_Flag,
 | 
|---|
| 790 |                                          pszReportedFS                                  );
 | 
|---|
| 791 | 
 | 
|---|
| 792 |     // Free the LVM data structure
 | 
|---|
| 793 |     Free_Engine_Memory( enginePartitions.Partition_Array );
 | 
|---|
| 794 | 
 | 
|---|
| 795 |     return ( pszFixed );
 | 
|---|
| 796 | }
 | 
|---|
| 797 | 
 | 
|---|
| 798 | 
 | 
|---|
| 799 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 800 |  * FixedPartitionFileSystem                                                  *
 | 
|---|
| 801 |  *                                                                           *
 | 
|---|
| 802 |  * Double-checks the given partition's filesystem-type string in order to    *
 | 
|---|
| 803 |  * work around a bug in the LVM.DLL's reporting of Linux partition types;    *
 | 
|---|
| 804 |  * see FixedVolumeFileSystem() description.                                  *
 | 
|---|
| 805 |  *                                                                           *
 | 
|---|
| 806 |  * ARGUMENTS:                                                                *
 | 
|---|
| 807 |  *     BYTE fOS           : OS flag reported by the partition                *
 | 
|---|
| 808 |  *     PSZ  pszReportedFS : FS name as reported by LVM.DLL                   *
 | 
|---|
| 809 |  *                                                                           *
 | 
|---|
| 810 |  * RETURNS: PSZ                                                              *
 | 
|---|
| 811 |  *     The "fixed" filesystem string.                                        *
 | 
|---|
| 812 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 813 | PSZ FixedPartitionFileSystem( BYTE fOS, PSZ pszReportedFS )
 | 
|---|
| 814 | {
 | 
|---|
| 815 |     PSZ s;
 | 
|---|
| 816 | 
 | 
|---|
| 817 |     if ( strlen(pszReportedFS) == 0 ) return "?";
 | 
|---|
| 818 |     while (( s = strchr( pszReportedFS, ' ')) != NULL ) *s = 0xFF;
 | 
|---|
| 819 |     switch ( fOS ) {
 | 
|---|
| 820 |         case 0x82 : return ("Linux_Swap");
 | 
|---|
| 821 |         case 0x83 : return ("Linux");
 | 
|---|
| 822 |         default   : return ( pszReportedFS );
 | 
|---|
| 823 |     }
 | 
|---|
| 824 | }
 | 
|---|
| 825 | 
 | 
|---|
| 826 | 
 | 
|---|
| 827 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 828 |  * EngineError                                                               *
 | 
|---|
| 829 |  *                                                                           *
 | 
|---|
| 830 |  * Writes a standardized error message to an RXSTRING, in the event that an  *
 | 
|---|
| 831 |  * error code is returned by LVM.DLL during an operation.                    *
 | 
|---|
| 832 |  *                                                                           *
 | 
|---|
| 833 |  * ARGUMENTS:                                                                *
 | 
|---|
| 834 |  *   PRXSTRING prsResult   : Pointer to the RXSTRING in which the message    *
 | 
|---|
| 835 |  *                           will be written.  Must be allocated already.    *
 | 
|---|
| 836 |  *   ULONG     ulErrorCode : The error code returned by LVM.DLL.             *
 | 
|---|
| 837 |  *                                                                           *
 | 
|---|
| 838 |  * RETURNS: N/A                                                              *
 | 
|---|
| 839 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 840 | void EngineError( PRXSTRING prsResult, ULONG ulErrorCode )
 | 
|---|
| 841 | {
 | 
|---|
| 842 |     CHAR szError[ US_ERRSTR_MAXZ ];
 | 
|---|
| 843 | 
 | 
|---|
| 844 |     sprintf( szError, SZ_ENGINE_ERROR, ulErrorCode );
 | 
|---|
| 845 |     if ( prsResult->strptr == NULL )
 | 
|---|
| 846 |         DosAllocMem( (PPVOID) &(prsResult->strptr), strlen(szError), PAG_COMMIT | PAG_WRITE );
 | 
|---|
| 847 |     MAKERXSTRING( *prsResult, szError, strlen(szError) );
 | 
|---|
| 848 | }
 | 
|---|
| 849 | 
 | 
|---|
| 850 | 
 | 
|---|
| 851 | /* ------------------------------------------------------------------------- *
 | 
|---|
| 852 |  * WriteStemElement                                                          *
 | 
|---|
| 853 |  *                                                                           *
 | 
|---|
| 854 |  * Creates a stem element (compound variable) in the calling REXX program    *
 | 
|---|
| 855 |  * using the REXX shared variable pool interface.                            *
 | 
|---|
| 856 |  *                                                                           *
 | 
|---|
| 857 |  * ARGUMENTS:                                                                *
 | 
|---|
| 858 |  *   PSZ   pszStem  : The name of the stem (before the '.')                  *
 | 
|---|
| 859 |  *   ULONG ulIndex  : The number of the stem element (after the '.')         *
 | 
|---|
| 860 |  *   PSZ   pszValue : The value to write to the compound variable.           *
 | 
|---|
| 861 |  *                                                                           *
 | 
|---|
| 862 |  * RETURNS: N/A                                                              *
 | 
|---|
| 863 |  * ------------------------------------------------------------------------- */
 | 
|---|
| 864 | void WriteStemElement( PSZ pszStem, ULONG ulIndex, PSZ pszValue )
 | 
|---|
| 865 | {
 | 
|---|
| 866 |     SHVBLOCK shvVar;                   // REXX shared variable pool block
 | 
|---|
| 867 |     ULONG    ulRc;
 | 
|---|
| 868 |     CHAR     szCompoundName[ US_COMPOUND_MAXZ ],
 | 
|---|
| 869 |              szValue[ US_SZINFO_MAXZ ];
 | 
|---|
| 870 | 
 | 
|---|
| 871 |     sprintf( szCompoundName, "%s.%d", pszStem, ulIndex );
 | 
|---|
| 872 |     strncpy( szValue, pszValue, US_SZINFO_MAXZ );
 | 
|---|
| 873 |     MAKERXSTRING( shvVar.shvname,  szCompoundName, strlen(szCompoundName) );
 | 
|---|
| 874 |     MAKERXSTRING( shvVar.shvvalue, szValue,        strlen(szValue) );
 | 
|---|
| 875 |     shvVar.shvnamelen  = RXSTRLEN( shvVar.shvname );
 | 
|---|
| 876 |     shvVar.shvvaluelen = RXSTRLEN( shvVar.shvvalue );
 | 
|---|
| 877 |     shvVar.shvcode     = RXSHV_SYSET;
 | 
|---|
| 878 |     shvVar.shvnext     = NULL;
 | 
|---|
| 879 |     ulRc = RexxVariablePool( &shvVar );
 | 
|---|
| 880 |     if ( ulRc > 1 )
 | 
|---|
| 881 |         printf("Unable to set %s: rc = %d\n", shvVar.shvname.strptr, shvVar.shvret );
 | 
|---|
| 882 | 
 | 
|---|
| 883 | }
 | 
|---|
| 884 | 
 | 
|---|
| 885 | 
 | 
|---|
| 886 | 
 | 
|---|