REXX Tips & Tricks:Change the WPS with REXX

This section contains hints for using REXX to change the WPS.

WPS class hierarchy
This section contains the class tree for WARP 3 and WARP 4.

To get a list of all registered classes on your system use the function SysQueryClassList.

To get a hierarchical list of the WPS classes registered on your system you can use the Search-Button of the LaunchPad (or the entry Find ... in the WPS context menu) as follows:
 * Open the Find dialog
 * Push the More ... button in the Find dialog to open the Find Criteria dialog
 * Push the Add button in the Find Criteria dialog to open the Add Criteria dialog
 * Select Object Class for the field Attribute in the Add Criteria dialog
 * Now you can scroll the hierarchical list of the registered classes in the list box Comparison value.

In der deutschen Version von WARP öffnet man hierfür den Suchen Dialog (über den Suchen Button der Klickstartleiste oder über den Eintrag Suchen im Kontextmenü der WPS. Dort klickt man den Button Weitere und in den daraufhin erscheinenden Dialog den Button Hinzufügen. In diesem Dialog nun setzt man das Feld Merkmal auf ObjektKlasse. Nun kann in der Listbox Vergleichswert die hierarchische Liste der registrierten WPS Klassen durch gerollt werden.

WARP Version 3 Class hierarchy
WPS Class hierarchy for WARP Version 3 (see also the WPS Class hierarchy for WARP 4). (except for the classes marked with *. These are no standard WPS classes.)

WARP Version 4 Class hierarchy
WPS Class hierarchy for WARP Version 4 (see also the WPS Class hierarchy for WARP 3).

Note: According to the REXX Reference Summary Handbook the class SmartCenter is a sub class of WPAbstract. I have not been able to verify this.

Extended Attributes used by the WPS
The Workplace Shell uses the following extended attributes: See the next section for the possible EA types.

Note: "Standard Extended Attributes (SEAs) have a dot (.) as a prefix. This identifies the extended attribute as a SEA. The leading dot is reserved, so applications should not define extended attributes that start with a dot. Also, extended attributes that start with the characters $, @, &, or + are reserved for system use."

Be aware that the information about the types of the Standard Extended Attributes in the Control Program Guide and Reference is not correct!

Extended Attribute Data Types
The first WORD of an EA specifies the type of the EA. The following EA types are defined (see Maintaining Multi-Value EAs in REXX for example REXX code to handle EAs):


 * Description:This EA contains ASCII text. The first WORD following the data type specifies the length of the data; the next bytes are the data.

Example: EAT_ASCII '0005'x 'Hello'


 * Description:This EA contains binary (non-text) data. The first WORD following the data type specifies the length of the data; the next bytes are the data.

Example: EAT_BINARY '0003'x '01'x '02'x '03'x


 * Description:This EA contains bit map data. The first WORD following the data type specifies the length of the data; the next bytes are the data.

Example: EAT_BITMAP '0203'x bitmap_data


 * Description:This EA contains metafile data. The first WORD following the data type specifies the length of the data; the next bytes are the data.

Example: EAT_METAFILE '0203'x metaFile_data


 * Description:This EA contains icon data. The first WORD following the data type specifies the length of the data; the next bytes are the data.

Example: EAT_ICON '1BF8'x icon_data


 * Description:This EA contains the ASCII name of another EA that is associated with the file. The contents of that EA are to be included in the current EA. The first WORD following the data type specifies the length of the name of the other EA; the next bytes are the name of the EA to include.

Example: EAT_EA '0008'x AB.STUFF

The first WORD following the data type specifies the codepage (0000 means default); the second WORD following the data type specifies the number of the following entries. The next bytes specify the EA values in the "normal" EA format (see the description for the other entries). Note that the Code page data is for use by the application; the operating system does not use it.
 * Description:This EA contains multi-valued, multi-typed data -- two or more consecutive extended attribute values. Each value has an explicitly specified type.

Example: EA_MVMT '0000'x '0003'x EAT_ASCII '0005'x Hello EAT_EA '0008'x AB.STUFF EAT_BINARY '0003'x '01'x '02'x '03'x

The first WORD following the data type specifies the codepage (0000 means default); the second WORD following the data type specifies the number of the following entries. The next word specifies the data type of the values and after that the data of the values follow.
 * Description:This EA contains multi-valued, single-typed data-two or more consecutive extended attribute values. All values have the same type.

Example: EAT_MVST 0000 0003 EAT_ASCII 0004 Mark 0005 Ellen 0003 Liz


 * Description:This EA contains ANS.1 field data; an ISO standard for describing multivalue data streams.


 * Description:These values are reserved for the Operating System.


 * Description:These values can be defined by the user. All user-defined data types should be length-preceded, meaning that a WORD indicating the length of the data (in bytes) precedes the data.

Source: Control Program Guide and Reference

Force the WPS to reRead the Extended Attributes
To force the WPS to reread the Extended Attributes (for example after changing the EA .LONGNAME) of a file you can use the following code (Source: Found in a public newsgroup):  /*  */  CALL RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs' CALL SysLoadFuncs

/* create a temporary file in the TEMP directory */ tempDir = value( 'TEMP',, 'OS2ENVIRONMENT' ) tempFile = time('S')

if right( tempDir,1 ) = '\' then tempFile = tempDir || tempFile else tempFile = tempDir || '\' || tempFile

/* now open the folder on the WPS                */ call SysSetObjectData tempDir, 'OPEN=DEFAULT;'

say 'Creating a file named "' || tempFile || '" ...'

/* create a temporary file                       */ '@ECHO. This is a test file ' '>'tempFile say ' ... done'

say 'Press any key after the file is shown in the folder ...' '@pause >NUL'

/* new value for the EA .LONGNAME                */ NewLongName = 'This is a very looong Name' || '00'x

/* create a valid EA                             */ typeinfo = 'FDFF'x || d2c(length(NewLongName)) || '00'x || NewLongName

say 'Now changing the EA .LONGNAME of the file to' say ' "' || newLongName || '" ...' say '(This should change the title used in the WPS!)'

/* change the EA                                  */ call SysPutEA tempFile, ".LONGNAME", typeinfo say ' ... done' say say 'Press any key to force the WPS to reRead the EAs' say '(and update the title in the folder) ...' '@pause >NUL'

/* force the WPS to reread the EAs                */ '@attrib -a ' tempFile '2>NUL 1>NUL' '@attrib +a ' tempFile '2>NUL 1>NUL'

say 'Now the WPS should show the new title for the object.'

say 'Press any key to delete the temporary file ...' '@pause >NUL'

/* delete the temporary file */ '@DEL ' tempFile '2>NUL 1>NUL' exit 0 

Format of the RC files for MAKEINI
A detailed description of the format of the RC files used by MAKEINI is included in the book OS/2 2.11 Power Techniques. (see also Predefined Object IDs)

Note: see Get the default object settings for an example for parsing an RC file.

Note: In OS/2 WARP, the UPDATE and REPLACE flags in the setup strings of some of the entries in the INI.RC have no effect on the options in the object's pop-up menu of existing objects. To get around this limitation, use SysSetObjectData to change the object properties (Source: APAR PJ18673).

Contents of the OS/2 INI files
OS/2 saves a big part of its configuration in the files OS2.INI and OS2SYS.INI. Therefore, many of the changes you might make to the WPS with REXX will involve changing some entries in these INI files.

The basic structure of OS/2 INI files is hierarchical, consisting of the following elements and order: Application Key Value Applications are the main entries. Each application must have at least one Key, and each Key must have a Value (Note that a lot of Values - but not all - include a trailing NULL byte ['00'x]). This byte may be needed for certain values to function properly. It should not be discarded when values are modified.)

To read or change INI file entries in REXX programs you can use the REXXUTIL function SysIni. For example, to read the value of the key PDR_DIR of the application PM_INSTALL in the file OS2.INI you can use the REXX statement: pdr_dir = SysIni( 'USER', 'PM_INSTALL', 'PDR_DIR' ) if pdr_dir = 'ERROR:' then say 'Error reading the key from the INI file!' To change the value of this key you can use: newPDR_DIR = 'I:\OS2IMAGE' || '00'x  thisRC = SysIni( 'USER', 'PM_INSTALL', 'PDR_DIR', newPDR_DIR ) if thisRC = 'ERROR:' then say 'Error reading the key from the INI file!' (BTW: The key used in the example above holds the name of the directory with the OS/2 image files (I:\OS2IMAGE) from which the system was installed. The value of this key is also the default value for the directory containing the OS/2 image if you do a Selective Install. The drive letter represents the drive that was used when the system was installed; therefore it can differ from one installation to another)

A detailed description of the contents of the OS/2 INI files (including many REXX samples to change the entries) is included in the book OS/2 2.11 Power Techniques. (Don't mind the version 2.11 in the title - the book is also useful for WARP 4).

Some useful entries are described in the next sections.

Note that, unless noted otherwise, all entries below have been tested only with OS/2 WARP Version 3.

You can use the program ConvIni.CMD to convert parts or all of an INI file into a REXX program to recreate the INI file entries.

Sample INI file entries
Following is a list of some useful entries in the OS/2 INI files. Warning:

Be aware that these entries are not documented by IBM! They may change in different releases of OS/2 without notice! (see Changing the Lockup page entries for an example)

Use this information with extreme care! Improper use could lead to unpredictable behavior of the system, possibly including problems booting and starting the WPS. Further Warning:

The names (!) of some keys in the INI files are language dependent! (see Font Size for text (VIO) windows for an example)!

Country dependent information
File OS2.INI

Application PM_National

Key (various, see below)

Value

Description This application contains the country-dependent information

Created -

Deleted -

Possible keys for this application (copied from the file \OS2\INI.RC. ): "iCountry"     "1"   /* Country code (phone ID of country)         */ "iDate"        "0"   /* Date mode (0:MDY, 1:DMY, 2:YMD)            */ "iCurrency"    "0"   /* Currency mode 0: prefix, no sep            */ /*   1: suffix, no separation                */ /*   2: prefix, 1 CHAR separation            */ /*   3: suffix, 1 CHAR separation            */ "iDigits"      "2"   /* Signif Decimal digits in Currency          */ "iTime"        "0"   /* time mode (0=12 hours clock, 1=24)         */ "iLzero"       "0"   /* Leading zeros (0: no, 1: yes)              */ "s1159"        "AM"  /* Trailing string 0:00 to 11:59              */ "s2359"        "PM"  /* Trailing string 12:00 to 23:59             */ "sCurrency"    "$"   /* Currency Symbol string                     */ "sThousand"    ","   /* Thousands separator string                 */ "sDecimal"     "." /* Decimal separator string                  */ "sDate"        "-"   /* Date separator string                      */ "sTime"        ":"   /* time separator string                      */ "sList"        ","   /* List separator string. */ "iMeasurement"  "1"   /* 1=English, 2=Metric, 3=Points, 4=Picaa     */

Font size for text (VIO) windows
File OS2.INI

Application Shield

Key ~Font Size...

Value "ccrr"x

cc = number of cols

rr = number of rows (hexadecimal values)

Description contains the default font size for new text windows

Created After pressing the Save button in the font dialog of a text window

Deleted ?

Example Use "080E"x for the font size 14*8

The value of this key is only used for new text windows. To open a window with a specific size you may
 * save the current value of the key
 * set the key to the needed value
 * open the text window
 * and restore the value of the key

see Start a VIO session with a specific font size for an example)

Warning: The name of this key is language dependent! For example in German OS/2 versions, the name of this key is Schrif~tartgröße...; in Spanish OS/2 versions, it's Tamaqo del ~font...! (The name seems to be equal to the menu entry for the popup menu.)

/*                                                                   */ /* Sample program to start an OS/2 session or a DOS box with a        */ /* specific font size                                                */ /*                                                                   */ /* Usage:                                                             */ /*                                                                   */ /*   StartVio {fontSize} {prog_parameter}                             */ /*                                                                   */ /* where:                                                             */ /*                                                                   */ /*   fontSize                                                         */ /*                                                                   */ /*     Font for the window in the format 'HHxWW'                      */ /*    where HH = font height as decimal value                        */ /*    and   WW = font width as decimal value                         */ /*    (def.: Use default font size)                                  */ /*                                                                   */ /*   prog_parameter                                                   */ /*                                                                   */ /*     Further parameter for the START command                        */ /*    (e.g /DOS to start a DOS box)                                  */ /*                                                                   */ /*                                                                    */ /*                                                                    */ /* Example:                                                           */ /*                                                                   */ /*   Start an OS/2 Session with a 14x8 Font                           */ /*                                                                   */ /*      StartVIO 14x8                                                 */ /*                                                                   */ /*   Start a DOS Box with a 10x6 Font                                 */ /*                                                                   */ /*      StartVIO 14x8 /DOS                                            */ /*                                                                   */ /*                                                                    */ /* History                                                            */ /*  10.07.1997 v1.00 /bs                                             */ /*    - initial release (for RXT&T v2.60)                            */ /*                                                                   */ /*                                                                    */ /* Note:                                                              */ /*  Change the value for the variable "FontMenuEntry" if you're not  */ /*  using a non-english version of OS/2! */ /*                                                                   */ /*                                                                    */ /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */ /*                                                                   */
 * Start a VIO session with a specific font size

/* Warning:  The name of this key is language                */ /*           dependent! For example in German OS/2          */ /*           versions, the name of this key is               */ /*           Schrif~tartgröße...; in Spanish OS/2            */ /*           version, it's Tamaqo del ~font...! (The        */        /*            name seems to be equal to the menu entry        */        /*            for the popup menu.)                            */ /* (see Font size for text (VIO) windows)                    */

FontMenuEntry = '~Font Size...'

/* process the parameter                         */ parse arg thisArgs

parse var thisArgs thisFont furtherArgs

NewFontSize = '' OldFontSize = ''

if thisFont <> '' then do   parse var thisFont height 'x' width

if datatype( height ) <> 'NUM' | datatype( width ) <> 'NUM' then do     furtherArgs = thisArgs end /* if datatype( height ) <> 'NUM' ... */   else do     NewFontSize = d2c( width ) || d2c( height ) end /* else */

end /* if thisFont <> '' then */

/* load the necessary REXXUTIL function                     */ if newFontSize <> '' then do   call rxFuncAdd 'SysIni', 'REXXUTIL', 'SysIni'

/* save the old font size                                   */ oldFontSize = SysIni( 'USER', 'Shield', FontMenuEntry )

if oldFontSize = 'ERROR:' then oldFontSize = ''

/* set the new font size                                    */ call SysIni 'USER', 'Shield', FontMenuEntry, newFontSize

end /* if newFontSize <> '' then */

/* start a new OS/2 session or DOS window                   */ '@start /win' furtherArgs

/* restore the old font size or delete the font size entry  */ /* if no font size entry was set                            */ if newFontSize <> '' then do   if oldFontSize <> '' then call SysIni 'USER', 'Shield', FontMenuEntry, oldFontSize else call SysIni 'USER', 'Shield', FontMenuEntry, 'DELETE:' end /* if newFontSize <> '' then */

exit

Open text windows in a maximized stated
File OS2.INI

Application Shield

Key fMaximize

Value "0100"x (on)

"0000"x (off)

Description Open text windows maximized

if on

Created ?

Deleted ?

The value of this key is only used for new text windows. To open a window maximized you may
 * save the current value of the key
 * set the key to "0100"x
 * open the text window
 * and restore the value of the key.

Changing the "Save Desktop Settings" page entry
File OS2.INI

Application PM_Workplace

Key PreserveDTSettings

Value "01000000"x (on)

"00000000"x (off)

Description save the desktop at

shutdown if on

Created ?

Deleted ?

This entry represents the check box "Save Desktop Settings" on the "Desktop" page of the WPS context menu.

Changing the default font
File OS2.INI

Application PM_SystemFonts

Key DefaultFont

Value font name "00"x

Description Default font for the WPS

Created manuell

Deleted manuell

You can use this entry to change the default font for the WPS. Example:

/* REXX cmd to set the default font for the WPS                      */ /*                                                                   */ /* note: WarpSans is the new default font of WARP 4 (Merlin). To use */ /*      this font in WARP 3, copy the file DSPRES.DLL from WARP 4    */ /*      to \OS2\DLL and reboot. */ /*      Be careful, though! Some video drivers require a specific   */ /*      version of DSPRES.DLL to work properly. */ /*      If the DLL is locked (i.e., in use), just unlock it with the */ /*      Unlock program from LX lite. */ /*                                                                   */

call rxFuncAdd "SysIni", "REXXUTIL", "SysIni"

call SysIni "USER", "PM_SystemFonts", "DefaultFont",, "9.WarpSans" || "00"x

Get the display resolution
File OS2.INI

Application PM_DISPLAYDRIVERS

Key DEFAULTSYSTEMRESOLUTION

Value "xxxxyyyydddd????????"x

xxxx = horizontal resolution

yyyy = vertical resolution

dddd = color depth

???? = unknown value

(all values in LSB format)

Description contains the current display resolution

Created ?

Deleted ?

File OS2.INI

Application PM_DISPLAYDRIVERS

Key RESOLUTION_CHANGED

Value "3100"x

Description display resolution change is pending if this key exists

Created after changing the current resolution using the System object

Deleted after the next reboot

Following is an example program using the known values of these entries to get the current display resolution.

/* -- */ /* sample program to get the current display resolution              */ /*                                                                   */

/* load the necessary REXXUTIL function          */ call rxFuncAdd "SysIni", "REXXUTIL", "SysIni"

/* get the resolution                            */ parse value GetDisplayResolution with , xResolution yResolution ColorDepth resolutionChangePending

/* display the results                           */ say "Your current display resolution is " || , XResolution || "x" || YResolution || "x" || ColorDepth

/* check if the resolution is already valid      */ if resolutionChangePending = 1 then do   say "" say "Note: You've changed the resolution but not rebooted until now." say "     So maybe the resolution mentioned above is only valid after" say "     the next reboot!" end /* if */

exit 0

/* -- */ /* function: Get the current display resolution                      */ /*                                                                   */ /* call:     GetDisplayResolution                                     */ /*                                                                   */ /* returns:  xValue yValue depth changePending                        */ /*                                                                   */ /* where:    xValue - horizontal size                                 */ /*          yValue - vertical size                                   */ /*          depth  - colorDepth                                      */ /*          changePending - 1 : the resolution was changed but no    */ /*                              reboot occurred until now            */ /*                          0 : the resolution is active             */ /*                                                                   */ /* note:     unknown1 and unknown2 are unknown values in the INI file */ /*          entry (see below). */ /*          This routine needs the REXXUTIL function SYSINI and the  */ /*          subroutine LSB2MSB                                       */ /*                                                                   */ GetDisplayResolution: PROCEDURE

/* init the return code                          */ parse value 0 0 0 0 with xValue yValue colorDepth changePending

/* install a local error handler                 */ signal on syntax name GetDisplayValueError /* get the current resolution     */ resolutionEntryInBin = SysIni( "USER" ,,                                "PM_DISPLAYDRIVERS" ,,                                 "DEFAULTSYSTEMRESOLUTION" )

/* check, if a resolution change is pending      */ resolutionChangePending = SysIni( "USER" ,,                                   "PM_DISPLAYDRIVERS" ,,                                    "RESOLUTION_CHANGED" ) if resolutionChangePending = "1" || "00"x then resolutionChangePending = 1 else resolutionChangePending = 0

/* convert the value into a hex string           */ resolutionEntryInHex = c2x( resolutionEntryInBin )

parse var resolutionEntryInHex 1 xValue  , 9 yValue , 17 ColorDepth , 25 unknown1 , 33 unknown2

/* convert the values into decimal values        */ xValue    = x2d( LSB2MSB( xValue ) ) yValue    = x2d( LSB2MSB( yValue ) ) ColorDepth = x2d( LSB2MSB( ColorDepth ) )

/* not returned or used in this version          */ unknown1  = x2d( LSB2MSB( unknown1 ) ) unknown2  = x2d( LSB2MSB( unknown2 ) )

/* this label is only used by the local error    */ /* handler                                       */ GetDisplayValueError: return xValue yValue colorDepth resolutionChangePending

/* -- */ /* function: Convert a WORD or DWORD from LSB format to MSB format   */ /*          and vice versa                                           */ /*                                                                   */ /* call:     LSB2MSB inputHexString                                   */ /*                                                                   */ /* where:    inputHexstring - input value as hexstring                */ /*                           (e.g. "3412", "78563412")               */ /*                                                                   */ /* output:   value in MSB format as hexstring                         */ /*          (e.g. "1234", "12345678")                                */ /*                                                                   */ LSB2MSB: PROCEDURE HexZiffer = arg(1)                                        /* v3.00 */ Len = Length(HexZiffer)                                   /* v3.00 */ If (Len // 2) then                                        /* v3.00 */ HexZiffer = Right(HexZiffer, Len + 1, '0')             /* v3.00 */ RETURN strip( translate( "12345678",,                     /* v3.00 */ HexZiffer, "78563412" ) )        /* v3.00 */

List all WPS known object IDs
File OS2.INI

Application PM_Workplace:Location

Keys {known object ids}

Value ?

Description This application contains the object IDs of all known objects

Created ?

Deleted ?

You can use this application to get a list of all known object IDs (see also GETOBJ and List all objects):

/* Sample code to display all object ids known to the WPS. */ /* Captured from a message in a public CompuServe Forum              */ /*                                                                   */

/* load the necessary REXXUTIL function          */ call rxFuncAdd "SysIni", "REXXUTIL", "SysIni"

/* get the list of the known object IDs          */ call SysIni "USER", "PM_Workplace:Location", "All:", "ids."

/* and print them to the screen                  */ say ids.0 || " known object IDs found." j = 1 do i = 1 to ids.0 j = j + 1 say ids.i   if j = 23 then do     say "Press RETURN to continue" parse pull j = 1 end /* if j = 23 then */ end /* do i = 1 to ids.0 */ exit

Icons saved in the file OS2.INI
File OS2.INI

Application PM_Abstract:Icons

Keys {object handles}

Value icon data

Description The keys of this application contain the icons for the objects

Created ?

Deleted ?

See Get icons from the OS2.INI file for an example of using this application. (see also List all objects)

List all objects
File OS2.INI

Application PM_Abstract:Objects

Keys {object handles}

Value ?

Description This application contains the handles of all known objects

Created ?

Deleted ?

You can use the DLL WPTOOLS.DLL to create a list of all known objects using this application (see also List all WPS known object IDs and GETOBJ):

Note: This program needs the routines from the section General routines for the samples!

/*                                                                   */    /* Sample program to display a list of all known objects              */ /*                                                                   */    /* Usage: ShowObj {>logfile}                                          */ /*                                                                   */    /* Note:  This program needs Henk Kelders excellent DLL WPTOOLS.DLL! */   /*                                                                    */    /*        Tested under OS/2 WARP Connect. May not work on other OS/2 */ /*       versions! */   /*                                                                    */    /* History                                                            */ /*  14.01.1996 v1.00 /bs                                             */ /*    - initial release (for RXT&T v2.00)                            */ /*                                                                   */    /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */ /*                                                                   */

/* turn on the NOVALUE condition                 */ signal on NOVALUE

/* load WPTOOLS functions                        */ call RxFuncAdd "WPToolsLoadFuncs", "WPTOOLS", "WPToolsLoadFuncs" call WPToolsLoadFuncs

/* load REXXUTIL functions                       */ call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs" call SysLoadFuncs

/* get all object handles                        */ thisRC = SysIni( "USER", "PM_Abstract:Objects", "ALL:", "handleList" )

call lineOut, "Object list" call LineOut, "===========" call LineOut, ""

/* display the object data                       */ do i = 1 to handleList.0 curHandle = handleList.i

call CharOut, " " || curHandle || ": "

cur2Indent = length( curHandle ) + 4 +2 curIndent = 0

/* show the data of the object                   */ call ShowObjectData "#2" || right( "0000" || curHandle, 4 ) ,, cur2Indent, curIndent

call LineOut, ""

end /* do i = 1 to handleList.0 */

exit

/* - insert the routines from the section - */ /*                General routines for the samples                 */ /* here! - */

List all associations
File OS2.INI

Application PMWP_ASSOC_TYPE

Keys {association types}

(e.g. "Plain Text")

Value "00"x (no association)

or a list of object

handles separated with

zero bytes ("00"x)

Description This application contains all known associations by type Created ?

Deleted ?

File OS2.INI

Application PMWP_ASSOC_FILTER

Keys {association filters} (e.g. "*.CMD")

Value "00"x (no association) or a list of object handles separated with zero bytes ("00"x)

Description This application contains all known associations by filter

Created ?

Deleted ?

You can use the keys of these applications to get the known associations and the data of the associated objects.

Note: This program needs the routines from the section General routines for the samples!

/*                                                                   */    /* Sample program to display a list of the associations               */ /*                                                                   */    /* Usage: ShowAsso {>logfile}                                         */ /*                                                                   */    /*                                                                    */    /* Note:  This program needs Henk Kelders excellent DLL WPTOOLS.DLL! */   /*                                                                    */    /*        Tested under OS/2 WARP Connect. May not work under other   */ /*       OS/2 versions! */   /*                                                                    */    /* History                                                            */ /*  14.01.1996 v1.00 /bs                                             */ /*    - initial release (for RXT&T v2.00)                            */ /*                                                                   */    /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */ /*                                                                   */

/* turn on the NOVALUE condition                 */ signal on NOVALUE

/* load REXXUTIL functions                       */ call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs" call SysLoadFuncs

/* get all filter associations                   */ thisRC = SysIni( "USER", "PMWP_ASSOC_FILTER", "ALL:", "assoc_filter" )

/* get all type associations                     */ thisRC = SysIni( "USER", "PMWP_ASSOC_TYPE", "ALL:", "assoc_type" )

call lineOut, "Associations by filter" call LineOut, "======================" call LineOut, ""

/* display filter associations                   */ do i = 1 to assoc_filter.0 curFilter = assoc_filter.i       curHandle = SysIni( "USER", "PMWP_ASSOC_FILTER", curFilter )

select

when curHandle = "ERROR:" then call lineOut, " " || curFilter || , ": Error retrieving the value for this key!"

when curHandle = "00"x then call lineOut, " " || curFilter || , ": No association for this filter."

otherwise do           call CharOut, "  " || curFilter || ": "

cur2Indent = length( curFilter ) + 4 +2 curIndent = 0

/* show the data of the associated objects       */ do until curHandle = ""

/* handle multiple associations                  */ parse var curHandle curSubHandle "00"x curHandle call ShowObjectData "#" || d2x( curSubHandle ) ,, cur2Indent, curIndent curIndent = cur2Indent -2 end /* until curHandle = "" */

end /* otherwise */

end /* select */ call LineOut, ""

end /* do i = 1 to assoc_filter.0 */

call lineOut, "Associations by type" call LineOut, "====================" call LineOut, ""

/* display filter associations                   */ do i = 1 to assoc_type.0 curType = assoc_type.i       curHandle = SysIni( "USER", "PMWP_ASSOC_TYPE", curType )

select

when curHandle = "ERROR:" then call lineOut, " " || curType || , ": Error retrieving the value for this key!"

when curHandle = "00"x then call lineOut, " " || curType || , ": No association for this type."

otherwise do           call CharOut, "  " || curType || ": "

cur2Indent = length( curType ) + 4 +2 curIndent = 0

/* show the data of the associated objects       */ do until curHandle = "" /* handle multiple associations                  */ parse var curHandle curSubHandle "00"x curHandle call ShowObjectData "#" || d2x( curSubHandle ) ,, cur2Indent, curIndent curIndent = cur2Indent -2 end /* until curHandle = "" */

end /* otherwise */

end /* select */ call LineOut, ""

end /* do i = 1 to assoc_type.0 */

exit

/* - insert the routines from the section - */ /*                General routines for the samples                 */ /* here! - */

Get the desktop directory
/* captured from a message in a public CompuServe forum              */ /*                                                                   */ /* Note: Seems not to work in OS/2 WARP 4! */ /*                                                                   */

/**********************************************************************/ /*                                                                   */ /* GETDESK.CMD                                                        */ /*                                                                   */ /* Version: 1.2                                                       */ /*                                                                   */ /* Written by: Georg Haschek (see EMail Addresses)                    */ /*                                                                   */ /* Description: Return the desktop's directory name to the caller. */ /*                                                                   */ /* Note: If the debug parameter ("/D") is set, the output goes to the */ /*      terminal. */ /*                                                                   */ /**********************************************************************/

/**************/ /* Initialize */ /**************/

Parse Upper Arg argstring debug = 0 If Wordpos( "/D",argstring ) > 0 Then debug = 1

If RxFuncQuery( "SysLoadFuncs" ) Then Do   Call RxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs" Call SysLoadFuncs End

If debug = 0 Then Return Getpath( Substr( SysIni( "USER",,                  "PM_Workplace:Location", "" ),1,2 ) )

Call Charout ,"Your desktop directory is: " Say Getpath( Substr( SysIni( "USER", "PM_Workplace:Location",,              "" ),1,2 ) ) Exit 0

/***********************************************/ /* Loop through the nodes to get the path info */ /***********************************************/ Getpath: Procedure Expose nodes. If Getnodes <> 0 Then Return ""

gpinode = Arg( 1 )

If nodes.gpinode = "" Then Return ""

gp = Substr( nodes.gpinode,33,Length( nodes.gpinode )-33 ) gpparent = Substr( nodes.gpinode,9,2 )

If gpparent <> "0000"x Then Do   Do Until gpparent = "0000"x gp = Substr( nodes.gpparent,33,Length( nodes.gpparent )-33 ) || , "\" || gp     gpparent = Substr( nodes.gpparent,9,2 ) End End Return gp

/*****************/ /* Get the nodes */ /*****************/ Getnodes: Procedure Expose nodes. handlesapp = SysIni( "SYSTEM","PM_Workplace:ActiveHandles",,                      "HandlesAppName" )

If handlesapp = "ERROR:" Then handlesapp = "PM_Workplace:Handles"

block1 = "" Do i = 1 to 999 block = SysIni( "SYSTEM", handlesapp, "BLOCK" || i ) If block = "ERROR:" Then Do     If i = 1 Then Do       Say "Unable to locate the NODE table, you are probably", "using OS/2 2.0 without the Service Pack." Return 1 End Leave End block1 = block1 || block End

l = 0 nodes. = "" Do Until l >= Length( block1 ) If Substr( block1,l+5,4 ) = "DRIV" Then Do     xl = Pos( "00"x || "NODE" || "01"x, block1,l+5 )-l If xl <= 0 Then Leave l = l + xl     Iterate End Else Do     If Substr( block1,l+1,4 ) = "DRIV" Then Do       xl = Pos( "00"x || "NODE" || "01"x, block1,l+1 )-l If xl <= 0 Then Leave l = l + xl       Iterate End Else Do       data = Substr( block1,l+1,32 ) xl = C2D( Substr( block1,l+31,1 ) ) If xl <= 0 Then Leave data = data || Substr( block1,l+33,xl+1 ) l = l + Length( data ) End End xnode = Substr( data,7,2 ) nodes.xnode = data End Return 0

Get a list of all printers
(see also Add new LPT Ports)

/* captured from a message in a public IBM forum                     */

/**********************************************************************/ /*                                                                   */ /* List all printers                                                  */ /*                                                                   */ /* Written by: Georg Haschek (see EMail Addresses)                    */ /*                                                                   */ /* Description: Print a list of all printers to the display           */ /*                                                                   */ /**********************************************************************/

if RxFuncQuery( "SysLoadFuncs" ) then do   Call RxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs" Call SysLoadFuncs end /* if rxFuncQuery( ... */

call SysIni "BOTH", "PM_SPOOLER_PRINTER", "ALL:", "printers" parse value SysIni( "BOTH", "PM_SPOOLER", "PRINTER" ) with default ";".

default = strip( default ) maxlen = 8

do i = 1 to printers.0 val = printers.i   parse value SysIni( "BOTH", "PM_SPOOLER_PRINTER_DESCR", val ) , With printerd.val ";". printerd.val = space( translate( printerd.val," ","0d0a"x ) ) if val == default then printerd.val = printerd.val "[default]" maxlen = max( maxlen ,length( printerd.val ) ) end /* do i = 1 to printers.0 */

title = "Name"||Copies( " ",maxlen-4 ) "Port     Queue    Printer driver" say title say copies( "-", length( title ) )

do i = 1 to printers.0 val = printers.i   parse value SysIni( "BOTH", "PM_SPOOLER_PRINTER", val ) , With port ";" driver ";" Queue ";". say left( printerd.val,maxlen ) left( strip( port ),8 ) , left( strip( queue ),8) strip( driver ) end /* do i = 1 to printers.0 */

exit 0

Changing the Lockup page entry
You cannot change the Lockup page entry using �SysSetObjectData in WARP 3. The book OS/2 2.11 Power Techniques contains some information about changing the lockup feature using the INI file entry (Partial/Full Screen Lockup, Setting Automatic Lockup and the Timeout Value, Auto Dim/No AutoDim, Reset the password, change the lockup bitmap, change the lockup bitmap display options).

In WARP 4 you can change some of the Lockup page entries and activate the Lockup using �SysSetObjectData (see Setup strings for WPDesktop objects and also Activating Lockup now)

Another method to init the lockup page entries with default values (useful for setting default values, but see also Set or get the WPS lockup password ):

Change the lockup page entries of an installed OS/2 system to meet your needs. Then call the REXX program below to create a REXX cmd to copy the lockup options to another machine:

/*                                                                   */ /* sample program to create a CMD to copy the lockup options of this  */ /* machine to other machines. */ /*                                                                   */ /* This program creates a program called "SETLKUP.CMD" in the         */ /* current directory. Execute this program on other machines to copy */ /* the lockup options of this machine. */ /*                                                                   */ /* Note that this program only works on OS/2 WARP. To work under     */ /* OS/2 versions prior to WARP you must change the application name  */ /* PM_Lockup to 'Lock Up Workplace' (with the blanks but without the */ /* quotes) and the key name LockupOptions to 'Lockup_options3' (also  */ /* without the quotes). */ /*                                                                   */ /* To use the program under 2.11 and WARP you may use the REXXUTIL    */ /* function �SysOS2Ver to distinguish between the versions --        */ /* but please note that I did NOT test if it is possible to use the  */ /* same values for different OS/2 versions! */ /*                                                                   */ /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */ /*                                                                   */

/* load the necessary REXXUTIL function(s)       */ call rxFuncAdd "SysIni", "REXXUTIL", "SysIni"

/* name of the REXX cmd to copy the options      */ outFile = "SETLKUP.CMD"

/* carriage return and linefeed values           */ crLF   = "0D0A"x

/* show a little message                         */ call LineOut, "Creating the file" call LineOut, " " || outFile call CharOut, "to copy the lockup options of this machine to other", "machines ... "

/* delete an existing target file                 */ "@del " outFile "2>NUl 1>NUL"

/* get the current lockup options                */ curLockupOptions = SysIni( "USER", "PM_Lockup", "LockupOptions" )

/* create the REXX cmd to copy this options to   */ /* another machine                               */ call LineOut outFile ,, "/* REXX cmd to set the lockup options */"            || crLF || , "/* created on " || date || " at " || time || " */"|| crLF || , ""                                                    || crLF || , " call rxFuncAdd 'SysIni', 'REXXUTIL', 'SysIni'"      || crLF || , ""                                                    || crLF || , " call SysIni 'USER', 'PM_Lockup', 'LockupOptions',," || crLF || , "           '" || c2x( curLockupOptions ) || "'x"     || crLF || , ""                                                    || crLF || , " '@setboot /IBD:C:'"                                 || crLF || , ""

call lineOut, " done."

Note that the reboot is necessary to make the changes active!

Set or get the WPS lockup password
/*                                                                   */ /* sample REXX functions to set and get the password for the WPS      */ /* lockup feature                                                    */ /*                                                                   */ /* Author: Ned Konz (see EMail Addresses)                             */ /*                                                                   */ /* History:                                                           */ /*  12.12.1996 /bs                                                   */ /*  - added code to distinguish between OS/2 2.1(1) and OS/2 WARP    */ /*    (Tested with OS/2 WARP 3 and OS/2 WARP 4)                      */ /*  - added code to handle 'Password not yet set' situations         */ /*                                                                   */ /*                                                                    */ /* note:                                                              */ /*  see also Changing the Lockup page entry,                         */ /*  Setup strings for WPDesktop objects                              */ /*  and Activating Lockup now                                       */ /*                                                                   */

call rxfuncadd "SYSLOADFUNCS", "REXXUTIL", "SYSLOADFUNCS" call sysloadfuncs

/* check the OS/2 version                    */ if SysOS2Ver > "2.11" then do                       /* current OS/2 version is WARP 3 or newer    */ LockUpOptionString = "LockupOptions" LockUpApplication = "PM_Lockup" end /* if SysOS2Ver > "2.11" then */ else do                       /* current OS/2 version is v2.11 or older     */ LockUpOptionString = "Lockup_options3" LockUpApplication = "Lock Up Workplace" end /* else */

inival = SysIni( "USER", LockupApplication, LockUpOptionString )

if iniVal = "ERROR:" then do                       /* Never opened the lockup page of the        */ /* desktop setup menu until now ->           */ /* The entry for the Lockup page is missing  */ /* in the INI file                           */ say "Error: No screen saver password set!" say "Hint: Use the setup menu of the desktop to set an" , "initial password." rc = 255 end /* if IniVal = "ERROR:" then */ else do   say "The current password is: '" || GetPassword(inival) || "'" say say "Enter the new password (blank line to quit)"

newpass = lineIn

if length( newpass ) <> 0 then do     inival = SetPassword( inival, newpass ) rc = SysIni( "USER", LockupApplication, LockupOptionString, inival )

say "Password changed. Re-boot is needed to make permanent." end /* if length( newPass ) <> 0 then */ end /* else */

EXIT rc

/* -- */ /* function: given a single character encrypted key, return          */ /*          decrypted key                                            */ /*                                                                   */ /* call:     DecrypKey encrypted_key                                  */ /*                                                                   */ /* where:    encrypted_key - encrypted character                      */ /*                                                                   */ /* returns:  decrypted key                                            */ /*                                                                   */ /* note:     called by GetPassword                                  */ /*                                                                   */ DecryptKey: PROCEDURE RETURN d2c( c2d( arg( 1 ) ) / 3 - 12 )

/* -- */ /* function: get the password from the INI file entry                */ /*                                                                   */ /* call:     GetPassword iniFileEntry                                 */ /*                                                                   */ /* where:    iniFileEntry - entry from the INI file                   */ /*                                                                   */ /* returns:  decrypted password                                       */ /*                                                                   */ /*                                                                    */ GetPassword: PROCEDURE

inival = arg( 1 ) /* encrypted key                             */ ekey = substr( inival, 7, 1 )

/* real key                                  */ key = DecryptKey( ekey )

/* NUL term. */ parse value substr( inival, 11, 16 ) WITH val "00"x

key = copies( key, length( val ) )

RETURN bitxor( val, key )

/* -- */ /* function: create an INI file entry to change the password         */ /*                                                                   */ /* call:     SetPassword iniFileEntry, newPassword                    */ /*                                                                   */ /* where:    iniFileEntry - entry from the INI file                   */ /*          newPassword - new password                               */ /*                                                                   */ /* returns:  new entry for the INI file                               */ /*                                                                   */ /*                                                                    */ SetPassword: PROCEDURE inival = arg( 1 )

parse upper value arg( 2 ) WITH newpass

/* encrypted key: "27"x                          */ ekey = "27"x

/* real key: "01"x                               */ key = copies( DecryptKey( ekey ), length( newpass ) )

key = overlay( bitxor( key,newpass ), copies( "00"x, 16 ) )

inival = overlay( key, inival, 11 )

RETURN overlay( ekey, inival, 7 )

Disable or enable the registration reminder
To disable or enable the registration reminder you may set the following keys (WARP 4 only!) : File OS2.INI

Application PM_Workplace:ART

Key DISABLED

Value fully qualified name of ARTCHRON.EXE with a trailing null byte

Description If this key is set, the registration reminder is disabled

Created ?

Deleted ?

Example "C:\OS2\ART\ARTCHRON.EXE"

File OS2.INI

Application PM_Workplace:ART

Key ENABLED

Value fully qualified name of ARTCHRON.EXE with a trailing null byte

Description If this key is set, the registration reminder is enabled

Created ?

Deleted ?

Example "C:\OS2\ART\ARTCHRON.EXE"

Source: Ralf Ulrich (see EMail Addresses)  Note: You can also delete the two keys to fully disable the registration reminder. Or use the Install Object - Inventory in the new folder "C:\OS2\INSTALL\Installed Features" (where C: is your boot drive) to uninstall it completely.

Double-Click on to open the parent folder of the "Install Object - Inventory" folder right now.

Default Settings for WPUrl Objects
The defaults for the WPUrl objects are saved in the application WPURLDEFAULTSETTINGS in the file OS2.INI (WARP 4 only!, see also WPUrl) File OS2.INI

Application WPURLDEFAULTSETTINGS

Key see WPUrl

Value see WPUrl

The values must have a trailing zero byte, NO is translated to "0" and YES is translated to "1"

Description defaults for the WPUrl objects

Created ?

Deleted ?

Example -

General routines for the samples
/* ================================================================== */ /*   This chapter contains various routines needed by the samples    */ /*                       from the WPS section                        */ /* ================================================================== */

/* -- */ /* function: show the data of an object                              */ /*                                                                   */ /* usage:    ShowObjectData [objectID | objectHandle] ,,              */ /*                         indent, indent1                           */ /*                                                                   */ /* where:    objectID - object ID (e.g. ""                */ /*           objectHandle - object Handle (e.g. "#340056")            */ /*           indent - indent for all lines except the first           */ /*           indent1 - indent for the first line                      */ /*                                                                    */ /* returns:  1 - ok                                                   */ /*           0 - object not found                                     */ /*          -1 - parameter missing                                    */ /*                                                                    */ /* Note:  This routine needs Henk Kelders excellent DLL WPTOOLS.DLL!  */ /*                                                                    */ /*              This routine only retrieves the setup strings         */ /*             supported by the DLL WPTOOLS.DLL (see the file        */ /*              WPTOOLS.TXT from the WPTOOLS package)!!! */ /*                                                                   */ /*                                                                    */ ShowObjectData: PROCEDURE parse arg curObjectHandle, indent , indent1

if rxFuncQuery( "WPToolsQueryObject" ) then do                   /*  load WPTOOLS functions                        */ call RxFuncAdd "WPToolsLoadFuncs", "WPTOOLS", "WPToolsLoadFuncs" call WPToolsLoadFuncs end /* if rxFuncQuery( ... */

iRetCo = -1 if curObjectHandle <> 0 then do   iRetco = WPToolsQueryObject( curObjectHandle,,                                 "szClass",,                                 "szTitle",,                                 "szSetupString",,                                 "szLocation" ) if iRetco then do               /* get the object ID of this object (if it exists)    */ parse value ( szSetupString || ";" ) WITH "OBJECTID=" objectID ";" if objectID = "" then objectID = "[no object ID, the object handle is " || , curObjectHandle || "]" call lineOut, copies( " " ,indent1 ) || objectID

call lineOut, copies( " ", indent ) || "Classname   : " || szClass call lineOut, copies( " ", indent ) || "Title       : " || szTitle call lineOut, copies( " ", indent ) || "Location    : " || szLocation

/* use formatted output for the setup string     */ call SplitSetupString 80 - ( indent + 15 ), szSetupString

call LineOut, copies( " ", indent ) || "Setupstring : " || , SetupStrStem.1

do n = 2 to SetupStrStem.0 if n <> SetupStrStem.0 then call LineOut, copies( " " ,indent + 14 ) || SetupStrStem.n     end /* do n = 2 to SetupStrStem.0 */

end /* if iRetCo then */ else call lineOut, copies( " ", indent1 ) || "Error: Object " || , curObjectHandle || " not found!"

end /* if curObjectHandle <> 0 then */

RETURN iRetCo

/* -- */ /* Function: split a setup string into parts with a maximum length   */ /*                                                                   */ /* call:     SplitSetupString length, setupString                    */ /*                                                                   */ /* where:    length - max. length for the parts                      */ /*          setupString - setup String                               */ /*                                                                   */ /* returns:  1                                                        */ /*                                                                   */ /*           SetupStrStem.0 - no. of parts                            */ /*          SetupStrStem.# - part 1 to n                             */ /*                                                                   */ /* Note:     The setup string is split at semicolons. If a       */ /*          part of the setup string is too long, it is split at     */ /*          commas. */ /*          Setupstrings (and parts of them) without a semicolon and */ /*          a comma are not split. */ /*                                                                   */ SplitSetupString: PROCEDURE expose setupStrStem. parse arg thisLength, setupString

SetupStrStem. = "" SetupStrStem.0 = 0 j = 1

do until setupString = ""

parse var setupString curPart ";" setupString

select when length( curPart ) >= thisLength then do

if length( SetupStrStem.j ) <> 0 then j = j + 1

curPart = curPart || ";"

do until curPart = "" parse var curPart curTPart "," curPart

if ( length( SetupStrStem.j ) + length( curTPart ) + 1 >= thisLength ) & , length( SetupStrStem.j ) <> 0 then j = j +1

if curPart = "" then SetupStrStem.j = SetupStrStem.j || curTPart else SetupStrStem.j = SetupStrStem.j || curTPart || ","

end /* until curPart = "" */

end /* when */

when length( SetupStrStem.j ) + 1 + length( curPart ) > thisLength then do       j = j + 1 SetupStrStem.j = curPart || ";" end /* when */

otherwise do       SetupStrStem.j = SetupStrStem.j || curPart || ";" end /* otherwise */

end /* select */ end /* do until setupString = "" */

setupStrStem.0 = j

RETURN 1

OS2SYS.INI
This section contains information about some entries of the file OS2SYS.INI.

Print to a file
To print to a file bypassing the prompt for the filename you can create a new port in your OS2SYS.INI file:

/* add an output file port into OS2SYS.INI                           */ call RxFuncAdd "SysIni", "RexxUtil", "SysIni" call SysIni "SYSTEM", "PM_SPOOLER_PORT", "c:\prtout.prn",, ";" || "00"x After the execution of this little program you can assign the newly created port to any printer object.

Note: Every new print output overwrites the existing file - you can't append the output to the file. Well, at least I haven't found a way to do this.

Source: OS/2 2.11 Power Techniques

Add new LPT Ports
Following is a sample REXX program to create additional LPT ports for the print spooler. This code is from a program called LPT49.cmd from the Keller Group.

(see also Get a list of all printers) call charout, 'Adding LPT4 through LPT9 to system ini ' call RxFuncAdd 'SysIni', 'RexxUtil', 'SysIni' do i = 4 to 9 call charout, '.' call SysIni 'SYSTEM', 'PM_SPOOLER_PORT', 'LPT' || i, ';' || '00'x end /* do i = 4 to 9 */ say ' done.' To use the ports in WinOS/2 also add the lines LPT4:= LPT5:= LPT6:= LPT7:= LPT8:= LPT9:= LPT4.OS2= LPT5.OS2= LPT6.OS2= LPT7.OS2= LPT8.OS2= LPT9.OS2= to the section [ports] of the file \OS2\MDOS\WINOS2\WIN.INI.

Add new COM Ports
Following is a sample REXX program to create additional COM ports for the print spooler. (based on Add new LPT Ports found in a public news group) call charout, 'Adding COM5 through COM8 to system ini ' call RxFuncAdd 'SysIni', 'RexxUtil', 'SysIni'

do i = 5 to 8 call charout, '.' call SysIni 'SYSTEM', 'PM_SPOOLER_PORT', 'COM' || i, ';' || '00'x end /* do i = 5 to 8 */ say ' done.' It maybe(!) possible to use the ports in WinOS/2 also if you add the lines COM5:=9600,n,8,1,x COM6:=9600,n,8,1,x COM7:=9600,n,8,1,x COM8:=9600,n,8,1,x COM9:=9600,n,8,1,x

to the section [ports] of the file \OS2\MDOS\WINOS2\WIN.INI.

Add new sound schemes in WARP 4
Following is a sample REXX program to create a new sound scheme (see also Add new sound schemes in WARP 4): /* -- */ /* SetSound.CMD                                                      */ /*   Sets up a sound scheme by writing the appropriate               */ /*   entries into the specified system INI file. */ /*                                                                   */ /*  Syntax:                                                           */ /*   SetSound  {filespec}                                            */ /*                                                                   */ /*  Source:                                                           */ /*  Personal Systems Issue 11/96 (online edition)                    */ /*                                                                   */ /* -- */ /* Set the sound scheme variables                                     */ /* -- */
 * REXX program to create new sound schemes in WARP 4

Title =  "MySoundScheme" KeyName = "PM_SOUNDS_MYSOUNDS"

Event.0 = 13 Event.1 = "?:\mmos2\sounds\mysounds\my_warn.wav" Event.2 = "?:\mmos2\sounds\mysounds\my_info.wav" Event.3 = "?:\mmos2\sounds\mysounds\my_err.wav" Event.4 = "?:\mmos2\sounds\mysounds\my_opnw.wav" Event.5 = "?:\mmos2\sounds\mysounds\my_clsw.wav" Event.6 = "?:\mmos2\sounds\mysounds\my_drag.wav" Event.7 = "?:\mmos2\sounds\mysounds\my_drop.wav" Event.8 = "?:\mmos2\sounds\mysounds\my_sstr.wav" Event.9 = "?:\mmos2\sounds\mysounds\my_ssht.wav" Event.10 = "?:\mmos2\sounds\mysounds\my_shrd.wav" Event.11 = "?:\mmos2\sounds\mysounds\my_lock.wav" Event.12 = "?:\mmos2\sounds\mysounds\my_alck.wav" Event.13 = "?:\mmos2\sounds\mysounds\my_prer.wav"

/* -- */ /* Get the input arguments                                           */ /* -- */

Parse Upper Arg fSpec

/* -- */ /* Check if the REXX external functions are registered. */ /* If not, then register them so we can use them                     */ /* -- */

if RxFuncQuery("SysLoadFuncs") then do   Call RxFuncAdd "SysLoadFuncs", "RexxUtil", "SysLoadFuncs" Call SysLoadFuncs end /* if */

/* -- */ /* Set up the filespec for the INI file                              */ /* -- */ if fSpec = "" then do   IniFile = "SYSTEM" end /* if fSpec = "" then */ else do

/* -- */ /* Parse the input filespec into its component parts                 */ /* -- */

tDrive = filespec("drive",fSpec) tPath = filespec("path",fSpec) tName = filespec("name",fSpec)

/* -- */ /* Get the local drive and current directory                         */ /* -- */

LocalCurDir = directory LocalDrive = substr( LocalCurDir, 1, 1 ) lDrive = LocalDrive||":"

LocalDir = substr(LocalCurDir, 3) lDir = LocalDir||"\"

/* -- */ /* Set the INI file spec                                             */ /* -- */

if tDrive = "" then tDrive = lDrive

if tPath = "" then tPath = lDir

IniFile = tDrive||tPath||tName end /* else */

/* -- */ /* Set the keys for the new sound scheme we're adding                */ /* -- */

results = SysIni( IniFile, "PM_SOUND_SCHEMES_LIST", Title, KeyName )

if results = "ERROR:" then do   say "SetSound ERROR:" , "Unable to set PM_SOUND_SCHEMES_LIST in the INI file" exit end /* if */ else do   say "SetSound: The following keywords have been set in the INI file:" , IniFile say "SetSound: PM_SOUND_SCHEMES_LIST ," Title "," KeyName end /* else */

/* -- */ /* For the KeyName, set the sounds for the events                    */ /* -- */

do i=1 to Event.0

Type = i-1 results = SysIni( IniFile, KeyName, Type, Event.i )

if results = "ERROR:" then do     say "SetSound ERROR: Unable to set Type" Type "for the file" , Event.i "in the INI file" end /* if */ else do     say "SetSound: System Event Type" Type " = " Event.i    end /* else */

end /* do i=1 to Event.0 */

exit 0

/* -- */ /* End of REXX script                                                */ /* -- */

How to wait in the STARTUP.CMD until the WPS is up
If you're using WPS-related code in your STARTUP.CMD, you should use the following code (or use the function �SysWaitForShell from the new REXXUTIL DLL) to wait until the WPS is up:

call rxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs' call SysLoadFuncs

rc = SysIni('USER', 'PM_InstallObject', 'ALL:', 'stem') do while rc \= 'ERROR:' call SysSleep 2 rc = SysIni('USER', 'PM_InstallObject', 'ALL:', 'stem') end /* do while rc \= 'ERROR:' */

/* add WPS related code here */

Change the WPS archive flag
The WPS archive flag is saved in the file \OS2\BOOT\ARCHBASE.$$$ at the offset 0xCF (Use 208 dec. for CharOut in REXX programs. This is necessary because REXX counts beginning with 1). To turn the ARCHIVE feature on, set this byte to 0x01; to turn it off set it to 0x00 (tested with OS/2 WARP and OS/2 WARP Connect, see example program below).

The name of the path for the archive is saved as ASCIIZ string in the same file at the offset 0x06 (use 7 dec for CharOut in REXX programs). The maximum length for the path is 200. (see also Change the OS/2 recovery screen options)

Source: Peter Bunney (see EMail Addresses)

Note: According to some messages on Usenet, the offset of these bytes is different in various versions of WARP with Fixpacks applied. I can't say if that is true or not - but don't forget that the format of this file is not documented! /*                                                                   */    /* Program Title: swBackup.CMD                                        */ /*                                                                   */    /* Program Purpose: get, set or clear the archive bit in the          */ /*                 desktop settings                                  */ /*                                                                   */    /* Author: Peter Bunney 100411.20@compuserve.com                      */ /*        (see EMail Addresses)                                      */ /*                                                                   */    /* History                                                            */ /*  Date Written: 16 dec 95                                          */ /*                                                                   */    /*   Date Updated: 18 dec 95                                          */ /*   - added parameter /bs                                           */ /*   - added some error checking /bs                                 */ /*   - changed the name to the 8.3 convention                        */ /*                                                                   */    /* Usage:                                                             */ /*  swBackup {ON|OFF|STATUS} {bootDrive}                             */ /*                                                                   */    /* Where:                                                             */ /*  ON        = switch archive feature ON                            */ /*  OFF       = switch archive feature OFF                           */ /*  STATUS    = get the current status of the archive feature (def.) */ /*  bootDrive = boot drive (e.g. "C:")                               */ /*              def.: use environment variable RUNWORKPLACE          */ /*                                                                   */    /* Returns:                                                           */ /*  parameter ON or OFF: 0 if successful                             */ /*  parameter STATUS: 0 - archive feature is off,                    */ /*                    1 - archive feature is on                      */ /*  else                                                             */ /*    255 - error                                                    */ /*                                                                   */

/* init the return code                      */ retCode = 255

/* get the parameter                         */ parse arg action bootdrive.

/* check the parameter, use defaults if      */ /* necessary                                 */ if bootDrive = "" then bootDrive = left( value( "RUNWORKPLACE",, "OS2ENVIRONMENT" ),1 ) bootDrive = left( bootDrive,1 ) || ":"

if action = "" then action = "STATUS" action = translate( action )

/* file used by the WPS to save the current  */ /* status                                    */ Archivefilename = bootDrive || "\os2\boot\archbase.$$$"

if stream( ArchiveFileName, "c", "QUERY EXISTS" ) <> "" then do                           /* change file attributes                     */ "@attrib -r " ArchiveFilename "2>NUL 1>NUL" if rc = 0 then do

/* process the appropriate action            */ select

when action = "ON" then do                           /* turn the archive feature ON                */ if stream( ArchiveFileName, "c", "OPEN WRITE" ) = "READY:" then if charout( ArchiveFilename, x2c( 01 ), 208 ) = 0 then retCode = 0 call stream ArchiveFileName, "c", "CLOSE" end /* when */

when action = "OFF" then do                           /* turn the archive feature OFF               */ if stream( ArchiveFileName, "c", "OPEN WRITE" ) = "READY:" then if charout( ArchiveFilename, x2c( 00 ), 208 ) = 0 then retCode = 0 call stream ArchiveFileName, "c", "CLOSE" end /* when */

when action = "STATUS" then do                           /* get the status of the archive feature      */ if stream( ArchiveFileName, "c", "OPEN READ" ) = "READY:" then retCode = c2x( charin( ArchiveFilename,208,1 ) ) call stream ArchiveFileName, "c", "CLOSE" end /* when */

otherwise do             say "Error: Invalid action parameter <" || action "> found!" retCode = 255 end /* otherwise */

end /* select */

/* reset file attributes                     */ "@attrib +r " ArchiveFilename "2>NUL 1>NUL" end /* if rc = 0 then */ else say "Error changing the attributes of <" || ArchiveFileName || ">!"

end /* if stream( ... */     else        say "File <" || ArchiveFileName || "> not found!"

exit retCode

Change the OS/2 recovery screen options
The flag indicating the status of the Display recovery choices at each restart checkbox (this is the Archive system files checkbox on the Archive page in the Desktop setup menu) is saved in the file \OS2\BOOT\ARCHBASE.$$$ in the byte at the offset 0xD9. Set this byte to 0x01 to turn the feature on; 0x00 turns the feature off.

The number of seconds to wait is saved as word in the same file at the offset 0xDD. (tested with OS/2 WARP and OS/2 WARP Connect, see example program below). (see also ) /*                                                                   */ /* Name:     Archive.CMD                                              */ /*                                                                   */ /* Function:                                                          */ /*  Get, set or clear the                                            */ /*    "Display recovery choices at each restart"                     */ /*  feature of OS/2                                                  */ /*                                                                   */ /* Usage:                                                             */ /*  archive  {ON{:time}|OFF{:time}|STATUS} {bootDrive}               */ /*                                                                   */ /* Where:                                                             */ /*  ON        = switch the feature ON                                */ /*  OFF       = switch the feature OFF                               */ /*              time - time to wait in seconds                       */ /*                     (def. use the current setting)                */ /*  STATUS    = get the current status of the feature (default)      */ /*  bootDrive = bootDrive (default: uset the environment variable    */ /*               RUNWORKPLACE)                                        */ /*                                                                   */ /* Returns:                                                           */ /*  parameter ON or OFF:                                             */ /*    0 - successful                                                 */ /*    else error                                                     */ /*                                                                   */ /*   parameter STATUS:                                                */ /*    if called from the command line:                               */ /*      0 - feature is off                                           */ /*      1 - feature is on                                            */ /*    else error                                                     */ /*                                                                   */ /*     if called from another REXX program:                           */ /*      x n                                                          */ /*    where                                                          */ /*      x - 0 - feature is off                                       */ /*          1 - feature is on                                        */ /*        else error                                                 */ /*      n - timeout value in seconds                                 */ /*                                                                   */ /*                                                                    */ /*                                                                    */ /* Credits:                                                           */ /*  Thanks to Peter Bunney for pointing me to the file               */ /*  \OS2\BOOT\ARCHBASE.$$$. */ /*  (see EMail Addresses)                                            */ /*                                                                   */ /* History:                                                           */ /*  14.04.1996 /bs                                                   */ /*    - initial release for RXT&T v2.20                              */ /*                                                                   */ /* Notes:                                                             */ /*  -                                                                */ /*                                                                    */ /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */ /*                                                                   */                        /* init the return code                       */ retCode = 0

/* get the parameter                         */ parse arg action bootdrive.

/* check the parameter, use defaults if      */ /* necessary                                 */ if bootDrive = "" then bootDrive = left( value( "RUNWORKPLACE",, "OS2ENVIRONMENT" ),1 ) bootDrive = left( bootDrive,1 ) || ":"

/* default action is STATUS                  */ if action = "" then action = "STATUS"

/* check the timeout value                   */ parse var action action ":" newTimeOut action = translate( strip( action ) )

if newtimeOut <> "" then if datatype( newtimeOut ) = "NUM" then do     if NewtimeOut >= 0 & newtimeOut <= 999 then newtimeOut = translate( "12", d2c( newtimeOut,2 ), "21", "00"x ) else retCode = 255 "Error: Invalid timeout value <" || NewtimeOut || "> found!" end /* if */ else retCode = 255 "Error: Invalid timeout parameter <" || NewtimeOut || "> found!"

/* get the call type                         */ parse upper source. callType.

/* file used by the OS/2 to save the current */ /* status                                    */ Archivefilename = bootDrive || "\os2\boot\archbase.$$$"

if retCode = 0 then if stream( ArchiveFileName, "c", "QUERY EXISTS" ) <> "" then do                       /* change file attributes                     */ "@attrib -r " ArchiveFilename "2>NUL 1>NUL" if rc = 0 then do                       /* process the appropriate action             */ select

when action = "ON" | action = "OFF" then do                       /* turn the feature ON or OFF                */

if stream( ArchiveFileName, "c", "OPEN WRITE" ) = "READY:" then do             newFlagValue = x2c( ( action = "ON" ) )

/* change the flag                          */ retCode = charOut( ArchiveFilename, newFlagValue, 218 )

/* set the new timeout value                */ if NewtimeOut <> "" & retCode = 0 then retCode = charOut( ArchiveFileName, NewTimeOut, 222 )

end /* if stream( ArchiveFileName, ... */

call stream ArchiveFileName, "c", "CLOSE" end /* when */

when action = "STATUS" then do                       /* get the status of the feature             */ if stream( ArchiveFileName, "c", "OPEN READ" ) = "READY:" then do                       /* get the flag value                        */ flagValue = c2x( charin( ArchiveFilename,218,1 ) )

/* get & convert the timeout value          */ timeOut = translate( "12", charIn( ArchiveFileName,222,2 ), "21" ) timeOut = x2d( c2x( timeOut ) )

retCode = flagValue timeOut end /* if */

call stream ArchiveFileName, "c", "CLOSE" end /* when */

otherwise do           retCode = 255 "Error: Invalid action parameter <" || action || "> found!" end /* otherwise */

end /* select */

/* reset file attributes                    */ "@attrib +r " ArchiveFilename "2>NUL 1>NUL" end /* if rc = 0 then */ else retCode = 255 "Error changing the attributes of <" || ArchiveFileName || ">!"

end /* if stream( ... */   else      retCode = 255 "File <" || ArchiveFileName || "> not found!"

/* process the return code                  */ parse var retCode exitCode errorMessage

if exitCode > 1 then do                       /* display the error message                 */ say errorMessage /* remove the error message from the return */ /* code                                     */ retCode = exitCode end /* if exitCode > 1 then */

if callType = "COMMAND" then retCode = word( retCode,1 )

exit retCode

Object IDs
The functions


 * SysCreateObject,
 * SysDestroyObject,
 * SysSetObjectData,
 * SysMoveObject (OS/2 3.0),
 * SysCopyObject (OS/2 3.0),
 * SysSaveObject (OS/2 3.0),
 * SysOpenObject (OS/2 3.0) and
 * SysCreateShadow (OS/2 3.0)

are case-sensitive with regard to the Object IDs (see also New REXXUTIL functions in WARP).

Predefined Object IDs
The IDs for the predefined WPS objects are included in the file \OS2\INI.RC.

The ID of the object is the name after the string OBJECTID= in the line beginning with "PM_InstallObject".

Note: A detailed description of the format of the RC files is included in the book OS/2 2.11 Power Techniques.


 * see List all WPS known object IDs for an example program to get the list of all existing object IDs on a system)

Object IDs of Network applications
The following text is taken from the readme file from the FIXNETAP.ZIP package from Phil Dumitru with permission of the author (see EMail Addresses):

"The object ID of our Network Apps folder is this:

<\NETAPPS\NETAPPFLDR>

The object IDs inside the folder are in this format:

<\Primary Domain Contoller\Application name>

Example:

Primary Domain Controller is LSBUF165 Application name is TEST123

object ID for this program object in the Net Apps folder is <\LSBUF165\TEST123>

Note: Application name is defined at the top of the Identity page in the settings notebook for the Public Application definition.

Frankly, I don't know what happens if the folder is served up by the Backup Domain Controller rather than the primary. Maybe the first part of the object IDs change to the BDC name?

Also, note that if you're trying to change settings on a Windows app to Enhanced mode, this program alone will not do it. You must also take this step once (on the server if the .EXE is there), before this program will work: Drill down to the .EXE file itself using the DRIVES object, open it's setings notebook, and change the settings on the .EXE to Enhanced mode. If you haven't done this, the program object you're trying to manipulate will automatically be set to Standard mode. This bug is what drove me to ask the original question about whether a program could perform the same function.

The indispensable IBM Redbook IBM OS/2 REXX From Bark To Byte has a program for listing object IDs (see page 81.) On my PC it lists the objects in the Net Apps folder last. If you don't have this book, absolutely get it.

Hope this helps."

Assigning more than one object ID to an object
At this time, you can assign more than one object ID to a WPS object. To do this, create an object with a new object ID. After that assign one or more new object IDs to the object using SysSetObjectData. Now you can use the original object ID or one of the new object IDs to refer to the object.

The explanation for this from Greg Czaja (see EMail Addresses) is:

"What really happening is that WPS will assign a new ID (and it will be stored in the object's properties but the old one will NOT be removed from OS2.INI -> PM_Workplace:Location. This allows you to refer to an object using both - the old and the ID's. At least from a REXX or PM program - WPS will use only the new one."

Source: Gregory Czaja

Get the object ID for an object handle
/*                                                                   */ /*                                                                    */ /* Get the object ID for an object handle                             */ /*                                                                   */ /* Note:                                                              */ /*                                                                   */ /* The environment variable WP_OBJHANDLE contains the object handle   */ /* for an OS/2 session. Note also that all sessions started from     */ /* an OS/2 session with the START command will inherit the object    */ /* handle from that session. */ /*                                                                   */ /* Author: Wolfram Sperber (see EMail Addresses)                      */ /*                                                                   */ /* He has developed this method in his program iNFOMAN 2.1, where any */ /* number of WPS objects are all starting the same program, through a */ /* number of different jobs:                                         */ /*                                                                   */ /* By identifying the Id of the actual starting object, specific job  */ /* data can be selected, stored elsewhere, but dedicated to the      */ /* actual object's run. */ /*                                                                   */ /* In general:                                                        */ /*                                                                   */ /* If the unique object-Id is known, it can be used, f.e., as a link  */ /* to a unique set of parameters or data, not stored with the object */ /* (thus not in OS2.INI). */ /*                                                                   */ /* Advantages:                                                        */ /* - If a WPS object is lost or corrupt, the object-specific data    */ /*  survive. */ /* - This kind of association of a program with its data would also  */ /*  be more stable than using program parameters for data, or the    */ /*  object-title as a link to them. */ /*                                                                   */ /* iNFOMAN 2.1 is available at BMTMirco (http://www.bmtmicro.com),    */ /* The name of the archive is IMAN21L.ZIP. */ /*                                                                   */

/* load the REXXUTIL functions                   */ call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs" call SysLoadFuncs

/* get the parameter                             */ parse arg objHandle

/* default is the handle of this OS/2 session    */ if objhandle = '' then objHandle = strip( value( 'WP_OBJHANDLE', , 'OS2ENVIRONMENT' ) )

say 'Detecting the object id of the object with the handle "' ||,      objHandle || '" ...'

curID = GetObjectID( objHandle ) if curID = '' then say 'Error: Cannot detect the object ID!' else say 'The object ID is "' || curID || '".'

exit (curID = '')

/* -- */ /* function: Get the object ID for an object handle                  */ /*                                                                   */ /* call:     objectID = GetObjectID( objectHandle )                   */ /*                                                                   */ /* where:    objectHandle - object handle                             */ /*                                                                   */ /* returns:  either the object ID or "" if the object doesn't have    */ /*          an object ID                                             */ /*                                                                   */ /* Author:   Wolfram Sperber (see EMail Addresses)                    */ /*                                                                   */ /*                                                                    */ GetObjectID: PROCEDURE parse upper arg objectHandle

thisRC =""

if objectHandle <> "" & , verify( objectHandle, '0123456789ABCDEF', 'NOMATCH' ) = 0 then do

/* convert handle to HEX                         */ HexVal = strip( d2x( objectHandle ) )

/* If the handle is in the format "value@20"     */ /* we must remove the prefix                     */ if substr( HexVal,2,1 ) = '0' then HexVal = right( HexVal,3 ) else HexVal = right( HexVal,4 )

/* remove a trailing zero                        */ if left(HexVal,1) = '0' then HexVal = substr(HexVal,2)

/* Now we should have the Keyname for this object */ /* in the file OS2.INI                           */ KeyValue = Sysini( "USER", "PM_Abstract:Objects", HexVal )

select

when KeyValue = 'ERROR:' then do                   /* key not found in OS2.INI                       */ end /* when */

when lastpos( '<',KeyValue ) = 0 | lastpos( '>',KeyValue ) = 0 then do                   /* object has no object ID                        */ end /* when */

otherwise do       id = substr(KeyValue,lastpos('<',KeyValue), ,             (pos('>',KeyValue, lastpos('<',KeyValue) +1))-(lastpos('<',KeyValue))+1)

if id <> '' then thisRC = id

end /* otherwise */ end /* select */ end /* if */

return thisRC

Get default object settings
The default settings for the standard WPS objects are saved in the file \OS2\INI.RC. (see also GETOBJ.CMD; see the routine ShowObjectDate in the section General routines for the samples for an example on how to get the settings of an object). /* sample routine to get the default settings of an object           */ /* This routine reads the file INI.RC to get the default settings    */ /* of the object. */ /* Note that object IDs are case sensitive! */

/* path & name of the RC file for MAKEINI    */ INIRCFile = 'C:\OS2\INI.RC'

do forever call CharOut, 'Enter the object ID ( to exit): ' objectID = strip( lineIn )

if objectID = '' then leave

if left( ObjectID,1 ) <> '<' then objectID = '<' || objectID || '>'

say 'Detecting the data of the object "' || ObjectID || '" ...' rc = getObjectData( ObjectID, 'objectData', iniRCFile ) if rc = 0 then do     say 'title:     "' || objectData.title     || '"' say 'className: "' || objectData.className || '"' say 'location: "' || objectData.location  || '"' say 'setup:    "' || objectData.setup     || '"' end /* if rc = 0 */ else do     say 'Error ' || rc || ' detecing the object settings!' end end /* do forever */

exit

/* -- */ /* function: get the data of an object                               */ /*                                                                   */ /* call:     getObjectData objectID, resultStem, rcFile               */ /*                                                                   */ /* where:    objectID - the id of the object                          */ /*          resultStem - name of the stem for the result             */ /*          rcFile - name of the rc file with the object description */ /*                   The format of the rc file must be equal to the  */ /*                   format of the file \OS2\INI.RC. */ /*                                                                   */ /* returns:  0 - ok                                                   */ /*          1 - rc file not found                                    */ /*          2 - object not found in the RC file                      */ /*        255 - invalid call                                         */ /*                                                                   */ /* output:   "objectData".title     = title                           */ /*                      .className = className                       */ /*                      .location  = location                        */ /*                      .setup     = setup string                    */ /*                                                                   */ GetObjectData: parse arg god.__objectID, god.__resultStem, god.__thisRCFile.

/* constants for the comment begin and end   */ /* strings used in the RC files              */ god.__CommentBegin = '/' || '*' god.__CommentEnd  = '*' || '/'

/* init the return code                      */ thisRC = 255

if god.__objectID <>  & god.__objectData <>  then do   thisRC = 1 if stream( god.__thisRCFile, 'c', 'QUERY EXISTS' ) <> '' then do     thisRC = 2 god.__searchString = 'OBJECTID=' || god.__objectID

/* open the RC file in READ ONLY mode        */ call stream god.__ThisRCFile, 'c', 'OPEN READ'

/* search the object definition in the rc file   */ do god.__curRCLineNo = 1 while lines( god.__thisRCFile ) <> 0

god.__curRCFileLIne = strip( lineIn( god.__thisRCFile ) )

/* discard comments                              */ do until god.__curComment = '' parse var god.__curRCFileLine , god.__part1         , (god.__CommentBegin) , god.__curComment    , (god.__CommentEnd)  , god.__part2

god.__curRCFileLine = god.__part1 || god.__part2 end /* do until commentFound = '' */

/* ignore empty lines                        */ if god.__curRCFileLine = '' then iterate

if translate( word( god.__curRCFileLIne, 1 ) ) = '"PM_INSTALLOBJECT"' then do         if pos( god.__searchString, god.__curRCFileLIne) <> 0 then do                       /* object description found                   */ parse var god.__curRCFileLine , '"' . '"'          ,                      '"' ,                        god.__title . ';'       ,                        god.__className ';'     ,                        god.__location          ,                      '"'                  , '"'                ,                      god.__setup 'OBJECTID=' . ,                      '"'

parse var god.__location god.__location ';'.

/* fill the result stem                  */ interpret god.__resultStem || '.title = '    || , '"' || strip( god.__title )    || '"'

interpret god.__resultStem || '.className = ' || , '"' || strip( god.__className ) || '"'

interpret god.__resultStem || '.location = ' || , '"' || strip( god.__location ) || '"'

interpret god.__resultStem || '.setup = '    || , '"' || strip( god.__setup )    || '"'

thisRC = 0 leave god.__curRCLineNo end /* if pos( ... */

end /* if word( */      end /* do god.__CurRCLineNo = 1 while ... */    end /* if stream( ... */ end /* if god.__ObjectID <> '' ... */

/* close the RC file                         */ call stream god.__ThisRCFile, 'c', 'CLOSE'

/* delete local variables                    */ drop god. RETURN thisRC

Check if an object exists
There's no REXX function to check if an object exists. But if you know the object ID of the object you can use the code below to test if an object already exists. (see also List all WPS known object IDs) /* sample code to check if an object exists. Note that this code    */ /* works for objects with object IDs only! */

/* load the SysCreateObject function        */ call rxFuncAdd "SysCreateObject", "REXXUTIL", "SysCreateObject" /* load the SysDestroyObject function       */ call rxFuncAdd "SysDestroyObject", "REXXUTIL", "SysDestroyObject"

do until myInput = "" say "Enter the ID of the object to check (RETURN to exit): " myInput = strip( lineIn ) if myInput <> "" then do     objectExist = ObjectExist( myInput )

select when objectExist = 0 then say "The object """ || myInput || """ does not exist."

when objectExist = 1 then say "The object """ || myInput || """ exist."

otherwise say "Error """ || objectExist || """ executing ObjectExist!"

end /* select */

end /* if myInput <> "" then */ end /* do until myInput = "" */

exit 0

/* -- */ /* function: Check if an object with a given object ID exists        */ /*                                                                   */ /* Usage:    ObjectExist objectID                                     */ /*                                                                   */ /* where:    objectID = object ID of the object to test               */ /*                                                                   */ /* returns:  1 - the object exist                                     */ /*          0 - the object does not exist                            */ /*          else                                                     */ /*            error code of the SysCreateObject function             */ /*                                                                   */ ObjectExist: PROCEDURE parse arg objectID

/* init the return code                      */ rc = 43              /* error code 43 = routine not found          */

/* install a local error handler             */ SIGNAL ON SYNTAX NAME ObjectExistError

/* check the parameter                       */ if substr( objectID, 2, 1 ) <> ":" then if left( objectID,1 ) <> "<" & right( objectID,1 ) <> ">" then objectID = "<" || objectID || ">"

/* try to create an object with this ID      */ tempRC = SysCreateObject( "WPFolder"                    ,,                            "TestObject"                   ,,                            ""                 ,,                            "OBJECTID=" || objectID || ";" ,,                            "FAIL" )

if tempRC = 1 then do                       /* object created, delete it                  */ call SysDestroyObject objectID rc = 0             /* set return code to "Object does not exist" */ end /* if tempRC = 1 then */ else rc = 1             /* set return code to "Object does exist"     */

ObjectExistError:

RETURN rc

Transient Objects
Open the  folder to get a list of the existing transient objects on your system (see also WPS class hierarchy). Double-Click on to open the  folder right now.

Note: In WARP 4, the WP_VAULT class, which contains the WP_NOWHERE folder(s), tries to prevent the WP_NOWHERE folder(s) from being opened by anything other than the system itself. If you are unable to open the folder on a WARP 4 system, this is a normal protective measure built into the system

Therefore the link above does not work in WARP 4.

Creating drive objects
Captured from a message in a public CompuServe Forum

Author: Dick Goran, (see EMail Addresses)

/* TEST210.CMD - Build drives objects on the Desktop */ /* /--\             */ /* |  WARNING - drives objects are    |              */ /* | neither deletable nor shredable |              */ /* | --- the following was added --- |              */ /* |       Bernd Schemmer            |              */ /* | You need BlackHole or a similar |              */ /* | tool to delete drive objects. |             */ /* \--/              */ /*                                                   */

call RxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs" call SysLoadFuncs

boot_drive   = LEFT( VALUE( "RUNWORKPLACE",, "OS2ENVIRONMENT" ), 2 ) drive_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" local_drives = SysDriveMap( "A", "LOCAL" )

floppy_resource     = "32 " || boot_drive || "\OS2\DLL\PMWP.DLL;" local_disk_resource = "13 " || boot_drive || "\OS2\DLL\PMWP.DLL;" remote_disk_resource = "16 " || boot_drive || "\OS2\DLL\PMWP.DLL;"

location  = "" class     = "WPDISK" title     = "Test object^for drive "

new_drives = "E"                 /* may contain any number of drives */

do d = 1 to WORDS( new_drives )

drive_letter =, WORD( new_drives, d ) drive_number =, POS( drive_letter, drive_letters )

setup_string =, "DRIVENUM=" || drive_number || ";"

select when ( drive_number = 1 ) | ( drive_number = 2 ) then do       setup_string =, setup_string || "ICONRESOURCE=" || floppy_resource end /* when */

when drive_number <= WORDS( local_drives ) then do       setup_string =, setup_string || "ICONRESOURCE=" || local_disk_resource end /* when */

otherwise do       setup_string =, setup_string || "ICONRESOURCE=" || remote_disk_resource end /* otherwise */ end /* select */

setup_string =, setup_string ||, "OBJECTID=;"

call SysCreateObject class,, title || drive_letter,, location,, setup_string,, "R" if RESULT <> 1 then do     say "   Unable to crea object for drive" drive_letter end /* if RESULT <> 1 then */

end /* do d = 1 to ... */

Creating shadows of drive objects
There seems to be a problem creating shadows of the drive objects using the setting SHADOWID=x:. Therefore I strongly recommend to attach an object ID to a drive object before creating a shadow of it. (see also Creating drive objects)

In OS/2 WARP 4 all drive objects have an object ID by default. The format for the ID is  where x is the drive letter (A, B, ...).

Changing the LaunchPad
When using the REXX function SysSetObjectData to change the settings of the LaunchPad (called the Toolbar in WARP 4), you may find that the LauchnPad that is subsequently displayed appears to be corrupted (e.g., drawers might be positioned incorrectly or icons may overlay one another on the LaunchPad object). To properly display the LaunchPad and incorporate any changes you've made with SysSetObjectData, try closing the LaunchPad object and reopening it immediately after the call to SysSetObjectData.

See Setup strings for the Launchpad for the valid keywords for the LaunchPad object.

Source: Dave Hicks (see EMail Addresses)


 * see APAR PJ17466

Getting the filename of WPDatafile objects
Sometimes it is necessary to get the filename of an object that is only known by the Object ID. This is possible for all objects of type WPDatafile and its child classes.

For example, the classes WebExplorer_Url (WARP 3) and WPUrl (WARP 4) are children of the WPDatafile class. Therefore objects of both classes are represented by a file. The URL referenced in this objects is saved in this file as plain ASCII string and is identified by the WPS setup string LOCATOR. The only way to retrieve this URL using plain REXX is, as far as I know, to read the file.

To get the filename for an object referenced by an Object ID you can either use Henk Kelder's WPTOOLS.DLL or you can create an empty directory, copy the object into that directory (using SysCopyObject) and get the filename (using SysFileTree).

General information
This section covers only a limited number of WPS setup strings. It discusses some of the more unusual setup strings and includes tips for using these and other setup strings. To get a list of all WPS setup strings, I suggest you get a copy of the OS/2 Toolkit and also the REXX Reference Summary Handbook. A very good tool to examine the WPS is also XWorkplace.

General hints
Some setup strings for the functions SysCreateObject and SysSetObjectData are case-sensitive. Therefore, all setup strings should be entered in uppercase.

Source: REXX Reference Summary Handbook

Phantom setup strings in WARP 4
There are some setup strings for DOS and WinOS/2 sessions documented in the OS/2 WARP 4 Online help that make their way only into the online help.

A maybe incomplete list of these is: According to some information exchanged on the Internet, these are new DOS settings that were written for "OS/2 for the PowerPC" version. But they were never added to the Intel version of OS/2 (and probably never will be). Even though you can see the information in the online documentation, you won't find the settings in the settings notebook.
 * DOS_NUMLOCK
 * DOS_SWITCHES
 * DOS_BUFFERS
 * VIDEO_BUFFER_USAGE
 * BIOS_TYPE
 * DOS_CODEPAGE
 * DOS_COUNTRY
 * DOS_INSTALL
 * DOS_LANGUAGE
 * DOS_SET
 * DOS_STACKS
 * FEP_MODE
 * IDLE_MAX_SLEEP_TIME
 * IDLE_TIMEOUT
 * TRANSLATED_CACHE_SIZE

(WARP 4 only!, Source: Team OS/2 WEB pages)

New Setup strings for various objects in WARP 4
This section contains a (perhaps incomplete) list of new and changed setup strings for objects that already exist in WARP 3, listed by class.

(The fourth edition of REXX Reference Summary Handbook contains a complete list of all possible WPS Setup strings for OS/2 2+, WARP 3 and WARP 4)

Source: Personal Systems Issue 11/96, Online edition

IDs for the setup string MENUITEMSELECTED
This section contains a list of possible IDs for the setup string MENUITEMSELECTED. Please note that not all IDs work for all objects! Further note that you must use the numeric values from the last column in the table below!

(see also SendMsg) Source: OS/2 WARP 4 Toolkit
 * 1) define WPMENUID_USER 0x6500
 * 2) define WPMENUID_PRIMARY 0
 * 3) define WPMENUID_OPEN 1
 * 4) define WPMENUID_HELP 2
 * 5) define WPMENUID_PRINT 3
 * 6) define WPMENUID_SELECT 4
 * 7) define WPMENUID_SORT 5
 * 8) define WPMENUID_TREE 123
 * 9) define WPMENUID_FIND 8
 * 10) define WPMENUID_CREATEANOTHER 101
 * 11) define WPMENUID_MOVE 107
 * 12) define WPMENUID_COPY 108
 * 13) define WPMENUID_DELETE 109
 * 14) define WPMENUID_PROPERTIES 112
 * 15) define WPMENUID_SELALL 114
 * 16) define WPMENUID_DESELALL 115
 * 17) define WPMENUID_RESERVED1 118
 * 18) define WPMENUID_CLOSE 120
 * 19) define WPMENUID_FORMAT 124
 * 20) define WPMENUID_CHKDSK 128
 * 21) define WPMENUID_FIXDSK 129
 * 22) define WPMENUID_PROGRAM 132
 * 23) define WPMENUID_COPYDSK 182
 * 24) define WPMENUID_LOCKDISK 184
 * 25) define WPMENUID_EJECTDISK 185
 * 26) define WPMENUID_UNLOCKDISK 186
 * 27) define WPMENUID_PICKUP 188
 * 28) define WPMENUID_PUTDOWN 189
 * 29) define WPMENUID_PUTDOWN_COPY 190
 * 30) define WPMENUID_PUTDOWN_MOVE 191
 * 31) define WPMENUID_PUTDOWN_LINK 192
 * 32) define WPMENUID_PUTDOWN_CANCEL 193
 * 33) define WPMENUID_PUTDOWN_CREATE 194
 * 34) define WPMENUID_PUTDOWN_CREATEPROGRAMOBJECT 195
 * 35) define WPMENUID_ICON 303
 * 36) define WPMENUID_DETAILS 304
 * 37) define WPMENUID_ARRANGE 309
 * 38) define WPMENUID_RESERVED2 315
 * 39) define WPMENUID_CREATESHADOW 316
 * 40) define WPMENUID_PALETTE 317
 * 41) define WPMENUID_REFRESH 503
 * 42) define WPMENUID_HELP_FOR_HELP 601
 * 43) define WPMENUID_HOWTOGETHELP 601
 * 44) define WPMENUID_EXTENDEDHELP 602
 * 45) define WPMENUID_HELPKEYS 603
 * 46) define WPMENUID_HELPINDEX 604
 * 47) define WPMENUID_SHUTDOWN 704
 * 48) define WPMENUID_LOCKUP 705
 * 49) define WPMENUID_LOGIN 708
 * 50) define WPMENUID_LOGOUT 709
 * 51) define WPMENUID_ASSIGN 710
 * 52) define WPMENUID_UNASSIGN 711
 * 53) define WPMENUID_ACCESSNEW 712
 * 54) define WPMENUID_SYSTEMSETUP 713
 * 55) define WPMENUID_OPENPARENT 714

Please note that there is also a list of possible IDs in the XWorkplace documentation.

Additional IDs that work on my system: 310 - Undo Arrange 715 - Paste ( folders only ) 716 - Change current view to Icon view ( open folders only ) 717 - Change current view to Tree view ( open folders only ) 718 - Change current view to Details view ( open folders only ) 733 - Change Arrange to Standard ( folders only ) 734 - Change Arrange to from Top ( folders only ) 735 - Change Arrange to from Left ( folders only ) 736 - Change Arrange to from Right ( folders only ) 737 - Change Arrange to from Bottom ( folders only ) 739 - Change Arrange to Perimeter ( folders only ) 740 - Change Arrange to Selected Horizontal ( folders only ) 741 - Change Arrange to Selected Vertical ( folders only ) 5000 - first new menu entry ( added using properties, folders only ) 5001 - second new menu entry ( added using properties, folders only ) 5101 - enable spooler ( spooler object only ) 5102 - disable spooler ( spooler object only ) 9004 - hold a print queue ( print objects only ) 9005 - release a print queue ( print objects only ) 9100 + n - set default printer ( where n is the number ) 25988 - Manage Limits ( network folders if the LAN Server GUI is loaded ) 25989 - Manage Access ( network folders if the LAN Server GUI is loaded ) 25990 - Start sharing ( network folders if the LAN Server GUI is loaded ) You can use the tool XRay - a PM window peeker to get other IDs for this keyword.

Sample for SHOWALLINTREEVIEW
/* -- */ /* TREEVIEW.CMD - change the default view of a folder to the new tree */ /*               view of WARP 4                                      */ /*                                                                   */ /* Usage:                                                             */ /*  TREEVIEW folder                                                  */ /*                                                                   */ /*                                                                    */ /* Where:                                                             */ /*  folder the name or the object ID of a folder                     */ /*                                                                   */ /* Author:                                                            */ /*  Bernd Schemmer                                                   */ /*                                                                   */ /* Note:                                                              */ /*                                                                   */ /*   This program needs WARP 4! */ /*                                                                   */ /* History                                                            */ /*  29.05.1997 v1.00 /bs                                             */ /*    - initial release (for RXT&T v2.60)                            */ /*                                                                   */ /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */ /* -- */

/* get the name of this program                  */ parse source. . progName progName = fileSpec( 'N', progName )

/* get the parameter                             */ parse arg targetFolder targetFolder = strip( targetFolder )

/* check the parameter                           */ if targetFolder = '' then do    say 'Usage: ' || progName || ' folder' exit 255 end /* if */

if right( targetFolder,1 ) = '\' then targetFolder = dbrright( targetFolder, 1 )

/* load REXXUTIL functions                       */ call rxfuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs' call SysLoadFuncs

/* check the OS/2 version                        */ if SysOS2Ver < 2.40 then do    say 'Error: ' || progName || ' needs OS/2 WARP 4!' exit 254 end /* if */

/* get the subfolder inside the folder           */ call SysFileTree targetFolder || '\*', 'dirs.', 'DSO'

/* add the parent folder to the stem             */ i = dirs.0+1 dirs.i = targetFolder dirs.0 = i

call LineOut, 'Changing the default view of the directory ' call LineOut, ' ' || targetFolder call LineOut, 'to TREEVIEW ...'

do i = 1 to dirs.0 call LineOut, '  Processing the directory ' call LineOut, '    ' || dirs.i     call SysSetObjectData dirs.i, 'SHOWALLINTREEVIEW=YES;DEFAULTVIEW=TREE;' call LineOut, '  The result is ' || result end /* do i = 1 to dirs.0 */ call LineOut, '... done.'

exit 0

Sample code to create a LaunchPad
/* sample code to create a LaunchPad                                 */

/* load the necessary REXXUTIL function          */ call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs" call SysLoadFuncs

/* */

/* object ID for the new LaunchPad               */ curObjectID = ''

/* */

say "Creating an additional LaunchPad ..."

/* create a new LaunchPad with the objects       */ /* , , , and      */ /* <WP_PROMPTS>. */                   /* Also change the style of the LaunchPad         */ /* (see Setup strings for LaunchPad objects for  */                    /*  the meaning of the setup strings)             */ /*                                               */                    /* Hint: The drawer 0 is the LaunchPad. */                   /*                                                */

thisRC = SysCreateObject(,    "WPLaunchPad"         ,,     "My new LaunchPad"    ,,     "<WP_DESKTOP>"        ,,     "DRAWEROBJECTS=0,<WP_OS2SYS>,<WP_INFO>,<WP_CONFIG>,<WP_PROMPTS>;" || ,     "LPACTIONSTYLE=MINI;"             || ,     "LPCLOSEDRAWER=YES;"              || ,     "LPDRAWERTEXT=YES;"               || ,     "LPFLOAT=YES;"                    || ,     "LPHIDECTLS=NO;"                  || ,     "LPSMALLICONS=YES;"               || ,     "LPTEXT=YES;"                     || ,     "LPVERTICAL=YES;"                 || ,     "OBJECTID=" || curObjectID || ";" || ,     "" ,,     "F" )

say " Result of SysCreateObject is " || thisRC

if thisRC <> 1 then do   say "Oops, something went wrong!" say "" say "If you've already executed this program the LaunchPad already exist." say "You should delete the existing Test LaunchPad before" say "running this program again" say "" exit 255 end /* if thisRC <> 1 then */

/* */  say "Now adding some objects to the drawer 1 ..."

/* add some objects to the drawer 1              */ thisRC = SysSetObjectData(,    curObjectID ,,     "DRAWEROBJECTS=1,<WP_TOOLS>,<WP_SHRED>,<WP_DRIVES>;" )

say " Result of SysSetObjectData is " || thisRC

if thisRC <> 1 then do   say "Oops, something went wrong!" exit 255 end /* if thisRC <> 1 then */

/* */  say "Now adding one object to the drawer 2 ..."

/* add one object to the drawer 2                */ thisRC = SysSetObjectData(,    curObjectID ,,     "DRAWEROBJECTS=2,<WP_TUTOR>;" )

say " Result of SysSetObjectData is " || thisRC

if thisRC <> 1 then do   say "Oops, something went wrong!" exit 255 end /* if thisRC <> 1 then */

/* */  say "Now adding some objects to the drawer 4 ..."

/* add some objects to the drawer 4              */ thisRC = SysSetObjectData(,    curObjectID ,,     "DRAWEROBJECTS=4,<WP_DOSFS>,<WP_DOSWIN>,<WP_WINFS>,<WP_WIN2WIN>;" )

say " Result of SysSetObjectData is " || thisRC

if thisRC <> 1 then do   say "Oops, something went wrong!" exit 255 end /* if thisRC <> 1 then */

/* */  say "Now adding some further objects to the LaunchPad ..."

/* add some objects to the LaunchPad             */ thisRC = SysSetObjectData(,    curObjectID ,,     "DRAWEROBJECTS=0,<WP_GAMES>,<WP_NOWHERE>,C:\OS2;" )

say " Result of SysSetObjectData is " || thisRC

if thisRC <> 1 then do   say "Oops, something went wrong!" exit 255 end /* if thisRC <> 1 then */

/* */  say "Now adding some further objects to the drawer 4 ..."

/* add some objects to the drawer 4              */ thisRC = SysSetObjectData(,    curObjectID ,,     "DRAWEROBJECTS=4,<WP_DOS_DRV_A>,<WP_OS2WIN>,C:\OS2\FDISKPM.EXE;" )

say " Result of SysSetObjectData is " || thisRC

if thisRC <> 1 then do   say "Oops, something went wrong!" exit 255 end /* if thisRC <> 1 then */

/* */  say "Now changing the style of the LaunchPad ..."

/* change the style of the LaunchPad             */ thisRC = SysSetObjectData(,    curObjectID ,,     "LPTEXT=NO;" )

say " Result of SysSetObjectData is " || thisRC

if thisRC <> 1 then do   say "Oops, something went wrong!" exit 255 end /* if thisRC <> 1 then */

/* */  say "Now opening the LaunchPad ..."

/* open the LaunchPad                            */ thisRC = SysSetObjectData(,    curObjectID ,,     "OPEN=DEFAULT;" )

say " Result of SysSetObjectData is " || thisRC

if thisRC <> 1 then do   say "Oops, something went wrong!" exit 255 end /* if thisRC <> 1 then */

/* */

Sample program to create a WebExplorer_Url object
/* TEST202.CMD                                                       */ /* Source: Message from Dick Goran in a public CompuServe forum      */ /*        (see EMail Addresses)                                      */

/*                      added by /bs                           v2.00 */ call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs" call SysLoadFuncs /*                      added by /bs                           v2.00 */

dll_name  = "WEBEXURL" class_name = "WebExplorer_Url" location  = "<WP_DESKTOP>" title     = "C F S Nevada's^Home Page" setup     = "LOCATOR=http://www.cfsrexx.com;"

call SysRegisterObjectClass class_name, dll_name if RESULT \= 1 then                                      /* v2.00 */ do    say "Unable to register class" class_name exit end

call SysCreateObject class_name, title, location, setup, "U" if RESULT \= 1 then                                      /* v2.00 */ do    say "Unable to create object for" title exit end

Hints for some setup string keywords
This section contains some hints for various setup string keywords in OS/2 WARP. To get more information about sections referring an APAR you may download the complete APAR or from certain large OS/2 file archives such as Hobbes (see Internet - Web Pages).

Setting environment variables for OS/2 objects
Setting additional environment variables for OS/2 session via the SET varName=varValue in the settings of the object does not work under OS/2 WARP 3. Instead of adding the new variable to the local environment, the environment is replaced with the environment variables from the object settings.

This bug is fixed in the WARP 3 fixpack #11 (source: APAR PJ19921).

The keyword DOS_AUTOEXEC
You can specify parameters for the keyword DOS_AUTOEXEC. Use the normal placeholder for parameters (%1 ... %9) to retrieve these parameters in your AUTOEXEC.BAT file. Using this method you can create one AUTOEXEC.BAT file with special settings for various DOS boxes.

The keyword CLASSDEFAULTVIEW
Beginning with WARP 4 Fixpack #1 there is a new keyword to set the default view for a class of files. The syntax for this keyword is: For example, to change the default view for new .FLC files to Video Editor you may use the following code: /* sample code to change the default view for new .FLC files         */

call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs" call SysLoadFuncs

say SysSetObjectData( 'C:\OS2\APPS\KLONDIKE.FLC',,                       'CLASSDEFAULTVIEW="Video Editor"' ) To get another example for using this feature, see the file \OS2\SETDEFV.CMD.

The keyword ICONPOS
The keyword ICONPOS has no effect for LaunchPads. There's no workaround for this bug at this time (see APAR PJ17399)

The keyword ICONRESOURCE
By Christian Langanke

All comments on the keyword ICONRESOURCE apply as well to the keyword ICONNRESOURCE.

When loading icons from resource DLLs using the keyword ICONRESOURCE, you can specify the DLL in two different ways: This approach is mostly used with system resource DLLs coming with OS/2 WARP. This approach is recommended to be used where C/C++ programs or REXX scripts create WPS objects with WinCreateObject/SysCreateObject calls using icons from within application resource DLLs. For that such DLLs need not to reside in a directory being contained in the LIBPATH statement, which is convenient for DLLs only being used within one application.
 * module name only: ICONRESOURCE=60,PMWP;
 * Such a DLL must be already loaded via (BEGIN/END)LIBPATH.
 * full pathname with extension: ICONRESOURCE=123,D:\TEST\MYRES.DLL;
 * Such a DLL must be already loaded into memory under WARP 3 and must not be loaded under WARP 4 (see comments below) in order to use it with the ICONRESOURCE keyword.

See further notes on DLLS at the end of this page about loading DLLs.

Problems with using the keyword ICONRESOURCE under WARP 3

Under WARP 3 using the keyword ICONRESOURCE will only succeed when using DLLs being already loaded by the Workplace Shell (like PMWP.DLL) or another process. This applies both to DLLs being referenced with their module name only (such as PMWP) as well as to DLLs being referenced with full pathname and file extension.

To achive this, any module being specified to load an icon from must explicitely be loaded before, either by another process or a REXX script itself. Otherwise the specified icon resource will not be useable, which will result in creating objects not showing up with the desired icon. While it is easy to load a DLL from within a C/C++ program, this is rather complicated from within a REXX script.

The following methods allow to load a resource DLL from within REXX:
 * use an external REXX extension DLL. This requires an additional DLL to be shipped with the REXX script, which I would recommend to avoid, if you do not need such external DLL in the same or another REXX script of the same application for other purposes anyway.
 * load the DLL with the built-in method RxFuncAdd. This requires to have at least one REXX compliant C-function within the resource DLL, which must be registered and called by the REXX script to let the REXX runtime effectively load the resource DLL.

Search http://hobbes.nmsu.edu for the ICONRESOURCE package (iconresource*.zip) of C.Langanke@TeamOS2.de, which contains the source and the compiled version of such a DLL plus a sample REXX script showing you the handling of the resource DLL (see also ICONRESOURCE)

A REXX programmer can use the precompiled resource DLL of this package without recompiling the C source by just adding resources with the resource compiler coming with plain OS/2 WARP 3 and 4.

Problems with using the keyword ICONRESOURCE under WARP 4

In contrast to WARP 3, under WARP 4 a resource DLL being referenced by the ICONRESOURCE keyword MUST NOT be in memory, if a fully qualified path is being specified. The DLLs seems implicitely to be loaded by WARP 4 and be freed afterwards. Only a DLL specified without path and extension (such as PMWP), that has been loaded via (BEGIN/END)LIBPATH, may already be in memory to be used with the ICONRESOURCE keyword.

General notes about (resource) DLLs:


 * A DLL loaded via module name only is loaded into a public DLL namespace. The system can load only one DLL with the same name into this namespace. When loading a second DLL from within a different directory (e.g. with the "." entry in the LIBPATH or with BEGIN/ENDLIBPATH), no error is returned, but still only the first DLL is being used !


 * A DLL loaded via full pathame and extension is loaded into a namespace being private per process. The system can load different DLLs with the same name, but from different directories.


 * The filename extension for DLLs being loaded via the full pathname does not necessarily need to be .DLL, any other extension will do fine. This does not apply to DLLs being loaded via (BEGIN/END)LIBPATH, herefore the extension MUST be .DLL. Thus a DLLs extension, which does not need to be loaded via LIBPATH can always safely be changed to any extension from one to three characters.


 * Modifying the name part of a DLL is not that harmless, as under some circumstances the name of the DLL must be identical to the module name being stored in the EXE header of the DLL:


 * If a DLL is only be used to load resources or functions of a DLL are being linked to dynamically, the name of the DLL can be changed without a problem (at least according to my testings, please send mail to C.Langanke@TeamOS2.de if you found out something different). Note that the name needs to be 8.3 FAT filesystem compliant since WARP 3 !.


 * If a DLL contains functions, that other programs link statically to, the name of the DLL MAY NOT be simply renamed. You have to use appropriate tools (like DLLRNAME.EXE from IBM compilers), which path the module name to the new name for you. Such tools usually restrict you to choose an name of either the same or shorter length, so that the EXE header needs not to be completely rewritten.

The keyword ICONVIEWPOS
Under some circumstances the keyword ICONVIEWPOS is ignored when creating an object of the type WPFolder. There's no workaround for this bug at this time (see APAR PJ17393)

You can't use ICONVIEWPOS to position two folders so that there's no gap between them. There's no workaround for this bug at this time (see APAR PJ17629).

The keyword NOSETTINGS
The NOSETTINGS setup string does not prevent users from opening a workplace shell object's settings notebook with ALT+ENTER or ALT+LMB DoubleClick (source: APAR PJ18742, fixed in WARP 3 FixPack #11).

The keyword NOTVISIBLE
Under OS/2 WARP, if a folder is set to NOTVISIBLE=YES and is then set to be NOTVISIBLE=NO, the system will hang.

This is a bug in the current release of WARP. The supposed workaround: Force the invisible folder to open with OPEN=DEFAULT before changing the setup string NOTVISIBLE (see APAR PJ16250 fixed in WARP 3 FixPack #12).

The keyword OBJECTID
Always use the keyword OBJECTID as the last keyword in the WPS setup string. Otherwise it may "not stick", i.e., the value of the keyword may be lost.

Source: Gregory Czaja

The keyword PARAMETERS
Resetting the parameters field of an existing WPProgram object to a null string is only possible if the last parameter for SysCreateObject is R (i.e., replace). But this use of the function SysCreateObject deletes and recreates the existing object. This means that all references to the object are deleted but not recreated.

A workaround for this feature: Use PARAMETERS=% (or PARAMETERS=%* if the object should support drag & drop) in the setup string to change the object. This method is also necessary if you're going to change the object settings with SysSetObjectData.

The keyword PROGTYPE
Use the setup string PROGTYPE for OS/2 programs objects with care. If you use an invalid value, your program may not work as expected.

The keyword TITLE
There's a problem using carets (^) in object titles.

To avoid this problem, always use object IDs to reference objects with carets in their titles. (see APAR PJ17176).

The keywords XCELLCOUNT and YCELLCOUNT
The keywords XCELLCOUNT and YCELLCOUNT are ignored for objects of the type WPFontPalette and WPColorPalette. There's no workaround for this bug at this time (see APAR PJ17516 [WPFontPalette] and APAR PJ16848 [WPColorPalette])

Sample Code fur MENUITEMSELECTED
This section contains some sample code about how to use the object setup string MENUITEMSELECTED.

Activating Lockup now
In OS/2 WARP 4 you can use the new setup string MENUITEMSELECTED to force a lockup of the desktop: /* -- */ /* LOCKUP.CMD - force a desktop lockup now                           */ /*                                                                   */ /* (only possible in WARP 4!!!                                        */ /*                                                                    */

call rxFuncAdd 'SysSetObjectData', 'REXXUTIL', 'SysSetObjectData' call rxFuncAdd 'SysOS2Ver', 'REXXUTIL', 'SysOS2Ver'

if SysOS2Ver < 2.40 then do   say 'Sorry, this program needs WARP 4 or above!' exit 255 end /* if SysOS2Ver < 2.40 then */

call SysSetObjectData '<WP_DESKTOP>', 'MENUITEMSELECTED=705;' exit 0

Refreshing a folder view
In OS/2 WARP 4 you can use the new setup string MENUITEMSELECTED to force a refresh of a folder: /* -- */ /* REFFOLDER.CMD - force the refresh of a folder                     */ /*                                                                   */ /* (only possible in WARP 4!!!                                        */ /*                                                                    */

call rxFuncAdd 'SysSetObjectData', 'REXXUTIL', 'SysSetObjectData' call rxFuncAdd 'SysOS2Ver', 'REXXUTIL', 'SysOS2Ver'

if SysOS2Ver < 2.40 then do   say 'Sorry, this program needs WARP 4 or above!' exit 255 end /* if SysOS2Ver < 2.40 then */

folder = "C:\Desktop\Programs"

call SysSetObjectData folder, "MENUITEMSELECTED=503;"

exit 0

Release or hold a printer queue
In OS/2 WARP 4 you can use the new setup string MENUITEMSELECTED to hold or release printer queue: /* -- */ /* release or hold a printer queue                                   */ /*                                                                   */ /* (only possible in WARP 4!!!)                                       */ /*                                                                   */

call rxFuncAdd 'SysSetObjectData', 'REXXUTIL', 'SysSetObjectData' call rxFuncAdd 'SysOS2Ver', 'REXXUTIL', 'SysOS2Ver'

if SysOS2Ver < 2.40 then do   say 'Sorry, this program needs WARP 4 or above!' exit 255 end /* if SysOS2Ver < 2.40 then */

/* object ID of the printer object               */ printerID = '<WPPO_EpsonSty>'

/* -- hold a printer queue */

thisRC = SysSetObjectData( printerID, 'MENUITEMSELECTED=9004;' )

/* -- release a printer queue - */

thisRC = SysSetObjectData( printerID, 'MENUITEMSELECTED=9005;' )

exit 0

Open a folder in tree view
In OS/2 WARP 4 you can use the new setup string MENUITEMSELECTED to open a folder in tree view: /* -- */ /* REFFOLDER.CMD - open a folder in tree view                        */ /*                                                                   */ /* (only possible in WARP 4!!!                                        */ /*                                                                    */

call rxFuncAdd 'SysSetObjectData', 'REXXUTIL', 'SysSetObjectData' call rxFuncAdd 'SysOS2Ver', 'REXXUTIL', 'SysOS2Ver'

if SysOS2Ver < 2.40 then do   say 'Sorry, this program needs WARP 4 or above!' exit 255 end /* if SysOS2Ver < 2.40 then */

folder = "C:\Desktop\Programs"

call SysSetObjectData folder, "MENUITEMSELECTED=123;"

exit 0

Open objects in the foreground
Use the function SysSetObjectData twice if you want to open an object and run it in the foreground: /* ID of the object                          */ objectID = "<WP_SYSED>"

/* open the object ... */ objectOpen = SysSetObjectData( objectID, "OPEN=DEFAULT;" )

/* ... and bring it in the foreground        */ if objectOpen = 1 then objectOpen = objectOpen + , SysSetObjectData( objectID, "OPEN=DEFAULT;" )

/* now the value of the variable objectOpen is   */ /* 2 if the object is open and in the foreground, */ /* 1 if the object is open in the background and */ /* 0 if we couldn't open the object              */

Note that the value for the key CCVIEW in the settings of the object must be NO to make this work (otherwise the second call of SysSetObjectData would open a new window).

see also

Switch a REXX program in the foreground
Sometimes it is useful if a REXX program can switch itself in the foreground. To do this, you need to create an temporary WPS object for your REXX program and then use SysSetObjectData inside your REXX program.

Example: /* -- */ /* FOREGROUND.CMD - example code for a REXX program that can switch  */ /*                 itself in the foreground                          */ /*                                                                   */ /*                                                                    */

/* load REXX util                                */ call rxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLodFuncs' call SysLoadFuncs

global. = ''                   /* the fully qualified name of this program is    */ /* necessary for the SysCreateObject call below  */ parse source. . global.__thisProg

/* a special parameter is necessary to           */ /* distinguish between the first call and the    */ /* call via the WPS object                       */ special_parameter = '$$REAL_START$$'

/* get and check the parameter                   */ parse arg special_parm global.__this_objectID normal_parameter

if special_parm <> special_parameter then do                   /* this is the very first start of the program:   */ /* Here we only create a temporary WPS object for */ /* ourself and restart us using this object      */

/* get all parameter again for the               */ /* SysCreateObject call                          */ parse arg real_parameter

/* get a unique string for an object ID          */ curString = rxqueue( 'create ') call rxqueue curString, delete

global.__this_objectID = '<' || curString || '>'

/* now create the temporary object               */ call SysCreateObject "WPProgram"     ,, global.__thisProg ,, '<WP_NOWHERE>'    ,, 'CCVIEW=NO;NOAUTOCLOSE=NO;'|| 'PROGTYPE=WINDOWABLEVIO;EXENAME=*;PARAMETERS=' || '/c "' global.__thisProg special_parameter curString                       real_parameter || '";' || 'OBJECTID=' || global.__this_objectID || ';', "Update"

/* open the Object (= start this program again)  */ call SysSetObjectData global.__this_objectID, "OPEN=DEFAULT;"

/* put the telnet session into the foreground    */ call SysSetObjectData global.__this_objectID, "OPEN=DEFAULT;"

/* that's all - exit now                         */ exit 0 end /* if */

/* this is the second start via the object       */ global.__this_objectID = '<' || global.__this_objectID || '>'

say '' say 'This is ' || global.__thisProg || ' called via the temporary object '

say 'The object ID of our object is: "' || global.__this_objectID || '"' say 'The parameter for this program are : "' || normal_parameter || '"' say '' say 'Now we wait for 10 seconds and then we put ourselv into the foreground again ...' call SysSleep 10

call SysSetObjectData global.__this_objectID, 'OPEN=DEFAULT;' say 'Now we are back in the foreground'

say 'OK, that''s all for now ' 'pause'

/* delete the temporary object                   */ /* Note: You should add this code also to any    */ /*      error handler in your program! */ say 'Deleting the object "' || global.__this_objectID || '" ...' call SysDestroyObject global.__this_objectID exit 0

Closing a WPS folder
Unfortunately it is not possible to close a WPS folder using Classic REXX (in Object-Oriented REXX it is: see Close a folder).

For this purpose you need an additional tool like for example SendMsg from the ZipShell package or a DLL exporting a close function.

Start a program with specific settings
Create a temporary object to start a program (DOS, Windows, or OS/2) with specific settings. Example: /* example code to start the Program Manager as seamless windows     */ /* program in a common session                                       */

call rxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs' call SysLoadFuncs

/* ID for the temporary object               */ objectID = '<MY_TEMP_OBJECT>'

title = 'Program^Manager' class = 'WPProgram' location = '<WP_NOWHERE>' setup = 'EXENAME=F:\WINDOWS\PROGMAN.EXE;' || , 'PROGTYPE=PROG_31_ENHSEAMLESSCOMMON;' || , 'OBJECTID=' || objectID || ';'

/* create the temporary object               */ say SysCreateObject( class, title, location, setup )

/* open the temporary object                 */ say SysSetObjectData( objectID, 'OPEN=DEFAULT;' )

/* bring it into the foreground              */ say SysSetObjectData( objectID, 'OPEN=DEFAULT;' )

/* destroy the temporary object              */ say SysDestroyObject( objectID ) exit This method is possible in all OS/2 versions. Beginning with OS/2 WARP 4 you can use another method to start a DOS or Windows program with specific settings:

Just set environment variables in the format DOSSetting.{dossetting} and issue a start command. {dossetting} can be any setup string that can be used in the setup string used to create or change a WPS Object for DOS sessions.

For example, to start a DOS session with a specific AUTOEXEC.BAT file use the following code: REM *** OS/2 Batch (works also in REXX programs) REM

REM The DOS sessions should use the file C:\TEST.BAT REM as AUTOEXEC.BAT. REM The name of the environment variables seems not to be case REM sensitive. REM set DOSSetting.DOS_AUTOEXEC=C:\TEST.BAT

REM Now use the start command to start the DOS session REM start /dos

Save the Desktop
/*                                                                   */ /* Name:     SaveWPS.CMD                                              */ /*                                                                   */ /* Function:                                                          */ /*  Save the desktop (OS/2 3.0 and above)                            */ /*                                                                   */ /* Usage:                                                             */ /*  SaveWPS                                                          */ /*                                                                   */ /* Where:                                                             */ /*  -                                                                */ /*                                                                    */ /* Returns:                                                           */ /*  -                                                                */ /*                                                                    */ /* Credits:                                                           */ /*  -                                                                */ /*                                                                    */ /* History:                                                           */ /*  -                                                                */ /*                                                                    */ /* Notes:                                                             */ /*  Create a program object for the program "\OS2\PMREXX.EXE" and    */ /*  insert the name of the file with the code below as parameters. */ /*                                                                   */ /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */ /*                                                                   */

/* load the necessary function from REXXUTIL */ call rxFuncAdd 'SysSaveObject', 'REXXUTIL', 'SysSaveObject'

/* save the desktop object & check the result */ if SysSaveObject( '<WP_DESKTOP>', 0 ) = 1 then rc = rxMessageBox( 'Desktop saved.'    ,,                       'SaveWPS - Result '  ,,                       'OK'                 ,,                       'INFORMATION' ) else rc = rxMessageBox( 'Error saving the Desktop!' ,,                      'SaveWPS - Result '         ,,                       'OK'                        ,,                       'ERROR' )

/* release the function SysSaveObject        */ call rxFuncDrop 'SysSaveObject' exit 0

Icon resources in default OS/2 DLLs
Many of the default icons used by OS/2 are saved as resources in the DLLs. To use them, you must use the setup string keyword ICONRESOURCE. To get a folder of the existing icons in the OS/2 DLLs you might use the following REXX program.

This program creates a folder called OS/2 Iconresources on your desktop. In this folder you find a folder for each directory with DLLs searched. The name of each folder is the name of the directory. Inside these folders are folders for each DLL with icon resources. The names of the folders are in the format DLL: dllName. In the folders for the DLLs are abstract objects for every icon resource from the DLL. The names of the objects are in the format dllName:resourceNumber (see also Extract the icon from the EAs and Get ICONS from the OS2.INI file). /*                                                                   */ /* Name:     ShowICO.CMD                                              */ /*                                                                   */ /* Function:                                                          */ /*  sample program to create some folders with the default           */ /*  OS/2 icons which reside in various DLLs                          */ /*                                                                   */ /* Usage:                                                             */ /*   ShowICO {path1} {...} {path#}                                   */ /*                                                                   */ /* Where:                                                             */ /*  path# is the path of the DLLs to use, in this version            */ /*  path# can be                                                     */ /*                                                                   */ /*   C:\OS2\DLL                                                       */ /*  C:\TCPIP\DLL                                                     */ /*  C:\TCPIP\UMAIL                                                   */ /*                                                                   */ /* Returns:                                                           */ /*  -                                                                */ /*                                                                    */ /*                                                                    */ /* Credits:                                                           */ /*  Based on Mike Lamb's program ICONRES.CMD. ICONRES.CMD is part of */ /*  REXXUTIL.TXT. */ /*                                                                   */ /*                                                                    */ /* History:                                                           */ /*  14.01.1995 /bs                                                   */ /*    - initial release for RXT&T v2.00                              */ /*                                                                   */ /* Notes:                                                             */ /*                                                                   */ /*   Used DLLs:                                                       */ /*    OS/2 DLLs                                                      */ /*    TCP/IP DLLs                                                    */ /*                                                                   */ /*   Tested only with WARP! Use ICONRES.CMD for OS/2 versions prior  */ /*  to WARP. */ /*                                                                   */ /*   Tested with TCP/IP (CSD level XX00000) and Ultimedia Mail/2 Lite */ /*  (CSD level UN00000). This program may not work correct with     */ /*  other CSD levels! */ /*                                                                   */ /*                                                                    */ /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */ /*                                                                   */                        /* get and save the parameter                 */ parse upper arg dirsToUse

/* load REXXUTIL functions                   */ call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs" call SysLoadFuncs

/* install a CTRL-BREAK handler              */ signal on halt name UserAbort

/* init some global variables                */ BootDrive = substr( value( "RUNWORKPLACE",, "OS2ENVIRONMENT" ),1,2 ) OS2DLLPath =  BootDrive || "\OS2\DLL" TCPIPDLLPath = BootDrive || "\TCPIP\DLL" UMailDLLPath = BootDrive || "\TCPIP\UMAIL"

parse source. . thisProgram parse value SysTextScreenSize with cols rows

say "" say center( fileSpec( "N", thisProgram ), rows ) say center( "Create abstract objects for icon " ||,             "resources from various DLLs", rows )

say "" if dirsToUse = "" then do   say "  This program asumes, the OS/2 dlls are in the directory " say "   " || OS2DllPath say " and the TCP/IP dlls are in the directories " say "   " || TCPIPDLLPath say " and " say "   " || UMailDLLPath say " If this is not true, abort the program and change the path in the" say " source code." say ""

say " Caution: "

say " This program will create up to 22 folders and up to 144 objects" say " on your desktop!" end /* if dirsToUse = "" then */ else do   say "  This program creates objects for the icon resources of all " say " known DLLs in the directories:" say "" do i = 1 to words( dirsToUse ) say "   " || word( dirsToUse, i ) end /* do i = 1 to words( dirsToUse ) */ end /* else */

say "" say " Do you want to continue (Y/n)?" parse pull userInput if right( translate( strip( userInput ) ) ,1 ) = "N" then signal UserAbort

/* init the stem with the DLL names and      */ /* icon resource numbers                     */ call InitDLLStem

/* no. of icon objects created               */ IconObjectsCreated = 0

/* no. of folder objects created             */ FolderObjectsCreated = 0

/* object ID for the base result folder      */ BaseFolderObjectID = "<MY_ICONRESOURCE_FOLDER>"

/* create the base folder on the desktop     */ call SysCreateObject "WPFolder" ,, "OS/2 Iconresources" ,, "<WP_DESKTOP>" ,, "OBJECTID=" || BaseFolderObjectID || ";" ,, "U"

FolderObjectsCreated = FolderObjectsCreated + 1

/* variable with the object IDs of the       */ /* directory folders created                 */ SubFoldersCreated = ""

/* now create an object for every icon       */ /* resource in each DLL                      */ do i = 1 to DllStem.0 curDLLName = DLLStem.i.name curDLLPath = DLLStem.i.path

if dirsToUse <> "" then if wordPos( DLLStem.i.path, dirsToUse ) = 0 then iterate

curResources = DLLStem.i.resources curDLL = curDllPath || "\" || curDLLName

say "Creating icons from the DLL """ || curDLL || """ ..."

if stream( curDLL, "c", "QUERY EXISTS" ) = "" then do     say "Error: DLL """ || curDll || """ not found!" iterate end /* if stream( ... */

/* create the sub folder for this directory  */ /* if necessary                              */ curDirectoryFolderObjectID = "<Directory_" || curDllPath || ">" if pos( curDirectoryFolderObjectID, SubFoldersCreated ) = 0 then do                       /* create a folder for this DLL               */ call SysCreateObject "WPFolder" ,, "Directory: " || curDLLPath ,, BaseFolderObjectID ,, "OBJECTID=" || curDirectoryFolderObjectID || ";" ,, "U"

SubFoldersCreated = SubFoldersCreated curDirectoryFolderObjectID

FolderObjectsCreated = FolderObjectsCreated + 1

end /* if pos( ... */

/* object ID for this DLLs folder            */ curDLLFolderObjectID = "<DLL_" || curDLLName || ">"

/* create a folder for this DLL              */ call SysCreateObject "WPFolder" ,, "DLL: " || curDLL ,, curDirectoryFolderObjectID ,, "OBJECTID=" || curDLLFolderObjectID || ";" ,, "U"

FolderObjectsCreated = FolderObjectsCreated + 1

/* create the objects                        */ do j = 1 to words( curResources )

curResourceID = strip( word( curResources, j ) )

call CharOut, " " || curResourceID

if SysCreateObject( "WPAbstract" ,,                         curDLLName || ":" || curResourceID ,,                          curDLLFolderObjectID ,,                          "ICONRESOURCE=" || curResourceID || " " || curDLL || ";" ,,                          "U" ) = 0 then do       say "" say "Error creating the object: " || curDllName || ":" || curResourceID end /* if SysCreateObject( ... */     else        IconObjectsCreated = IconObjectsCreated + 1

end /* do j = 1 to words curResources */ call LineOut, ""

end /* do i = 1 to DllStem.0 */

say "" say FolderObjectsCreated || " folders created." say IconObjectsCreated || " abstract objects created."

exit

/* -- */ /* Function: Init the stem with the DLL names and icon resource      */ /*          numbers                                                  */ /*                                                                   */ InitDlLStem: /* init the stem with the DLL names and      */ /* icon resource numbers                     */ DLLStem.0 = 0 i = DLLStem.0

i = i+1 DLLStem.i.name      = "IBMS332.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "10 11 12 13 14"

i = i+1 DLLStem.i.name      = "MINXMRI.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "1"

i = i+1 DLLStem.i.name      = "PMCTLS.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "1 2 3 4 5 6 7 8 9 17 19"

i = i+1 DLLStem.i.name      = "PMMERGE.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "10"

i = i+1 DLLStem.i.name      = "PMSDMRI.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "300 301"

i = i+1 DLLStem.i.name     = "PMVIOP.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "1 2 3"

i = i+1 DLLStem.i.name     = "PMWP.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "1 2 3 4 6 8 9 10 12 13 15 16 17 18 19 20 22 23", "24 25 26 27 28 29 32 33 35 37 38 39 42 43 44",                        "46 47 48 49 52 53 56 57 58 59 60 61 62 63 64",                         "65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80",                         "2146 2147"

i = i+1 DLLStem.i.name     = "WINCFG.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "5000"

i = i+1 DLLStem.i.name     = "WPCONFIG.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17"

i = i+1 DLLStem.i.name     = "WPCONMRI.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "15"

i = i+1 DLLStem.i.name     = "WPPRTMRI.DLL" DLLStem.i.path      = OS2DllPath DLLStem.i.resources = "2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 19 20 21 22 23"

i = i+1 DLLStem.i.Name     = "ADV.DLL" DLLStem.i.path      = TCPIPDllPath DLLStem.i.resources = "619 683 1003 2002 3608 26387 26388 26388"

i = i+1 DLLStem.i.Name     = "FTPWPS.DLL" DLLStem.i.path      = TCPIPDllPath DLLStem.i.resources = "101"

i = i+1 DLLStem.i.Name     = "WEBEXURL.DLL" DLLStem.i.path      = TCPIPDllPath DLLStem.i.Resources = "101"

i = i+1 DLLStem.i.Name     = "WPTELNET.DLL" DLLStem.i.path      = TCPIPDllPath DLLStem.i.resources = "499"

i = i+1 DLLStem.i.Name     = "WPTN3270.DLL" DLLStem.i.path      = TCPIPDllPath DLLStem.i.resources = "499"

i = i+1 DLLStem.i.Name     = "UMAILWPS.DLL" DLLStem.i.path      = UMailDllPath DLLStem.i.resources = "4000 4002 4004 4006 4008"

i = i+1 DLLStem.i.Name     = "UMBASE.DLL" DLLStem.i.path      = UMailDllPath DLLStem.i.resources = "3072"

DLLStem.0 = i RETURN

/* -- */ UserAbort: say "" say "Program aborted by the user." exit 255

Get icons from the OS2.INI file
Use the following program to get the icons saved in the file OS2.INI (see also Icon resources in default OS/2 DLLs and Extract the icon from the EAs): /*                                                                   */ /* Name:     GetWICO.CMD                                              */ /*                                                                   */ /* Function:                                                          */ /*  sample program to get the icons from the OS2.INI file            */ /*                                                                   */ /* Usage:                                                             */ /*  GetWICO                                                          */ /*                                                                   */ /* Where:                                                             */ /*  -                                                                */ /*                                                                    */ /* Returns:                                                           */ /*  -                                                                */ /*                                                                    */ /* Credits:                                                           */ /*  -                                                                */ /*                                                                    */ /* History:                                                           */ /*  18.01.1996 /bs                                                   */ /*    - initial release for RXT&T v2.00                              */ /*                                                                   */ /* Notes:                                                             */ /*                                                                   */ /*   The .ICO files are created in the current directory. */ /*                                                                   */ /*   Tested only with WARP. */ /*                                                                   */ /*                                                                    */ /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */ /*                                                                   */

/* load REXXUTIL function                    */ call rxFuncAdd "SysIni", "REXXUTIL", "SysIni"

say "GetWICO - get the icons from the OS2.INI file"

/* get a list of the icons                   */ call SysIni "USER", "PM_Abstract:Icons", "ALL:", "icons."

call CharOut, "Creating " || icons.0 || " .ICO files "

do i = 1 to icons.0 curIconFile = "ICO_" || icons.i || ".ICO"

call CharOut, "." call stream curIconFile, "c", "OPEN WRITE"

call CharOut curIconFile ,, sysIni( "User", "PM_Abstract:Icons", icons.i )

call stream curIconFile, "c", "CLOSE" end /* do i = 1 to icons.0 */ call LineOut, " done."

exit 0

Extract the icon from the EAs
A lot of programs save their icon in the Extended Attribute .ICON. You may use the following code to extract the icon from the EAs of a program (see also Icon resources in default OS/2 DLLs and Get icons from the OS2.INI file): /*                                                                   */ /* Name:     GetIcon.CMD                                              */ /*                                                                   */ /* Function:                                                          */ /*  sample program to get the icons from the OS2.INI file            */ /*                                                                   */ /* Usage:                                                             */ /*  GetIcon fileName                                                 */ /*                                                                   */ /* Where:                                                             */ /*  fileName - name of the file with the .ICON EA                    */ /*                                                                   */ /* Returns:                                                           */ /*  -                                                                */ /*                                                                    */ /* Credits:                                                           */ /*  -                                                                */ /*                                                                    */ /* History:                                                           */ /*  RXT&T v2.00 /bs                                                  */ /*    - initial release                                              */ /*  RXT&T v2.10 /bs                                                  */ /*    - added some error checking code                               */ /*                                                                   */ /* Notes:                                                             */ /*                                                                   */ /*   The .ICO files are created in the current directory. */ /*                                                                   */ /*   Tested only with WARP. */ /*                                                                   */ /*                                                                    */ /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de     */ /*                                                                   */

parse arg sourceFileName sourceFileName = strip( sourceFileName )

/* load the necessary REXXUTIL function          */ call RxFuncAdd "SysGetEA", "REXXUTIL", "SysGetEA"

/* check the parameter                           */ if sourceFileName = "" then do   say "Usage: GetIcon fileName" exit 2 end /* if sourceFileName = "" then */

iconData = ""

/* use ".ICON1" to retrieve the Animation icon of */ /* folder                                        */ if SysGetEA( sourceFileName, ".ICON", "iconData" ) <> 0 | iconData = "" then do   say "Error: Either the file does not exist or the file has no .ICON EA" exit 3 end /* if SysGetEA( ... */

/* check the type and format of the EA     v2.10 */ parse var iconData EAType +2 EALength +2 IconData         /* v2.10 */ EALength = c2d( translate( "12", EALength, "21" ) )       /* v2.10 */

if EAType <> "F9FF"x |,                                  /* v2.10 */ EALength <> length( iconData ) then                    /* v2.10 */ do                                                        /* v2.10 */ say "Error: The .ICON EA is corrupted!" /* v2.10 */ exit 5                                                  /* v2.10 */ end /* if EAType <> "F9FF"x | ... */                     /* v2.10 */

/* create the name for the target file           */ i = lastPos( ".", sourceFileName ) j = lastPos( "\", sourceFileName )

if i = 0 | ( i < j ) then targetFileName = sourceFileName || ".ICO" else targetFileName = substr( sourceFileName, 1, i ) || "ICO"

if stream( targetFileName, "c", "QUERY EXISTS" ) <> "" then do   say "Error: The targetfile " || , targetFileName || , " already exist!" exit 4 end /* if stream( ... */

/* create, write and close the ICON file         */ call stream targetFileName, "c", "OPEN WRITE" call CharOut targetFileName, iconData call stream targetFileName, "c", "CLOSE"

say "Iconfile " || targetFileName || " created." exit 0

Format of the file created with 'Print settings'
In OS/2 WARP 3 and 4 you can save the settings of a DOS/WIN-OS/2 object with the PRINT button in the settings dialog. The format of the file created is as follows (Source: OS/2 Inside 9/95):

The object is represented with the following keywords and values: Each setting of the object is respresented with the following keywords and values: The keys p, t and d are unique for each keyword; the key v can be used more than one time.

The keys d and v can be a combination of numbers and text, 3 represents the default value, 0 (off) and 1 (on) represent non default values.

Example: s=DCF i=Excel - Settings

p=WIN_RUN_MODE t=5 v=320 3.1 Standard d=0 Off

p=WIN_DDE t=5 v=1 On d=1  On

p=WIN_CLIPBOARD t=5 v=1 On d=1  On

p=WIN_ATM t=0 v=0 Off d=1 On

p=COM_DIRECT_ACCESS t=0 v=0 Off d=1 On

p=COM_HOLD t=0 v=0 Off d=1 On

p=COM_RECEIVE_BUFFER_FLUSH t=2 v=NONE d=1 On

p=COM_SELECT t=2 v= ALL d=1 On

p=DOS_AUTOEXEC t=3 v=C:\AUTOEXEC.BAT d=1 On

p=DOS_BACKGROUND_EXECUTION t=0 v=1 On d=1  On

p=DOS_BREAK t=0 v=0 Off d=1 On

p=DOS_DEVICE t=4 v= d=1 On

p=DOS_FCBS t=1 v=16 d=1 On

p=DOS_FCBS_KEEP t=1 v=8 d=1 On

p=DOS_FILES t=1 v=20 d=1 On

p=DOS_HIGH t=0 v=0 Off d=1 On

p=DOS_LASTDRIVE t=3 v=Z d=1 On

p=DOS_RMSIZE t=1 v=640 d=1 On

p=DOS_SHELL t=3 v=C:\OS2\MDOS\COMMAND.COM C:\OS2\MDOS d=1 On

p=DOS_STARTUP_DRIVE t=3 v= d=1 On

p=DOS_UMB t=0 v=0 Off d=1 On

p=DOS_VERSION t=4 v=DCJSS02.EXE,3,40,255 v=DFIA0MOD.SYS,3,40,255 v=DXMA0MOD.SYS,3,40,255 v=EXCEL.EXE,10,10,4 v=IBMCACHE.COM,3,40,255 v=IBMCACHE.SYS,3,40,255 v=ISAM.EXE,3,40,255 v=ISAM2.EXE,3,40,255 v=ISQL.EXE,3,40,255 v=MSD.EXE,5,00,255 v=NET3.COM,3,40,255 v=NETX.COM,4,00,255 v=NETX.EXE,5,00,255 v=PSCPG.COM,3,40,255 v=SAF.EXE,3,40,255 v=WIN200.BIN,10,10,4 d=1 On

p=DPMI_DOS_API t=2 v=AUTO d=1 On

p=DPMI_MEMORY_LIMIT t=1 v=4 d=0 Off

p=DPMI_NETWORK_BUFF_SIZE t=1 v=8 d=1 On

p=EMS_FRAME_LOCATION t=2 v=AUTO d=1 On

p=EMS_HIGH_OS_MAP_REGION t=1 v=0 d=1 On

p=EMS_LOW_OS_MAP_REGION t=1 v=384 d=1 On

p=EMS_MEMORY_LIMIT t=1 v=0 d=0 Off

p=HW_NOSOUND t=0 v=0 Off d=1 On

p=HW_ROM_TO_RAM t=0 v=0 Off d=1 On

p=HW_TIMER t=0 v=0 Off d=1 On

p=IDLE_SECONDS t=1 v=0 d=1 On

p=IDLE_SENSITIVITY t=1 v=75 d=1 On

p=INT_DURING_IO t=0 v=0 Off d=0 Off

p=KBD_ALTHOME_BYPASS t=0 v=1 On d=0  Off

p=KBD_BUFFER_EXTEND t=0 v=1 On d=1  On

p=KBD_CTRL_BYPASS t=2 v=NONE d=1 On

p=KBD_RATE_LOCK t=0 v=0 Off d=1 On

p=MEM_EXCLUDE_REGIONS t=3 v= d=1 On

p=MEM_INCLUDE_REGIONS t=3 v= d=1 On

p=MOUSE_EXCLUSIVE_ACCESS t=0 v=0 Off d=0 Off

p=PRINT_SEPARATE_OUTPUT t=0 v=1 On d=1  On

p=PRINT_TIMEOUT t=1 v=15 d=1 On

p=SESSION_PRIORITY t=1 v=1 d=1 On

p=VIDEO_8514A_XGA_IOTRAP t=0 v=0 Off d=0 Off

p=VIDEO_FASTPASTE t=0 v=0 Off d=1 On

p=VIDEO_MODE_RESTRICTION t=2 v=NONE d=1 On

p=VIDEO_ONDEMAND_MEMORY t=0 v=1 On d=1  On

p=VIDEO_RETRACE_EMULATION t=0 v=1 On d=0  Off

p=VIDEO_ROM_EMULATION t=0 v=1 On d=1  On

p=VIDEO_SWITCH_NOTIFICATION t=0 v=1 On d=0  Off

p=VIDEO_WINDOW_REFRESH t=1 v=1 d=1 On

p=XMS_HANDLES t=1 v=32 d=1 On

p=XMS_MEMORY_LIMIT t=1 v=2048 d=1 On

p=XMS_MINIMUM_HMA t=1 v=0 d=1 On