How to programmatically fight with WPS:Tools

From EDM2
Jump to: navigation, search
<< DESCRIPTION -- Index -- .CLASSINFO, 90 sec delay, DEFAULTVIEW >>

Object REXX

injects a class into WPS, so provides a direct access to WPS objects (with limitations w.r.t. marshalling etc).

REXX without extensions

provides access (via and Sys*Object* API) to the Win*Object* (C) subset of API.

icon.exe (GUI for WPTOOLS.DLL) (by Kelder)

among others shows many things:

  • 1/2-decyphered contents of .CLASSINFO
  • Init strings for objects;
  • Contents of NOWHERE
  • Get/Set Object ID, location

WPTOOLS.DLL is also accessible from REXX. Beware: there are tools which require incompatible versions of this DLL... WPTOOLS.DLL uses undocumented hacks to get the object data for EA and .INI files.

ObjectSpy Class

class-DLL, ID, location, class ancestors, icon styles (no-delete etc), methods, interface.

WP Class list Application

Class Tree => create an object of the given class, (un)replace a class.


Class Tree => metaclass/parent, DLL, Cause?, instance/class methods/datasize.

Object Utility/2

D&D => Class, DLL, object-id, location, get/set style flags (no-delete etc).

Setup strings list

a complete listing of setup strings for common object classes, along with a list of the values used with.


tame WPObjData _and_ to put it to work doing something useful.


mo create/modify-by-string-id objects
eo modify by handle
fo create shadows in TARGET by the *-pattern in ./
qo report the handle by the string-id
wplist list classes/dll
wpkill delete class
wpmake add class


has access to Win*Object* API (C) (via OS2::WinObject module). The module SOM gives access to all the SOM objects and the object repository, but (currently) only a limited access to DSOM objects (due to the absence of an interface to DLL).


Are you saying I can highlight something that shows up in the VIO window that CHECKINI runs in, and DragText will locate it elsewhere on the "real" desktop?

Yes - if the object actually exists. I just ran checkini looking for an example and found two. The first is sort of involved, the second is pretty straightforward.

Example 1:

 PM_Abstract:Objects & PM_Abstract:FldrContents
|               YES              |              NO                |

Honestly, I wasn't quite sure what this was telling me at first (I was up way too late last night). I have an FP7 system on "F:" and an FP14 system on "G:". I was running checkini against F:, so why was it identifying a problem on G:?

Then I remembered: I had (foolishly) opened G:'s Templates Folder while running F: and had seen the system populate it with shadows of F:'s templates. This produced a record in F:'s os2.ini describing the contents of G:'s templates folder (in particular, those shadows).

Trying to make sense of it, I highlighted <WP_TEMPS> in the VIO window where checkini's output appears. Clicking Ctrl+Shift MB2 caused DragText to pop up its WPS menu. DT adds the object's name to the menu and puts its full path on a submenu (selecting either will open whichever folder contains the object). Checking the path on the submenu confirmed that F:'s <WP_TEMPS> did point to the folder on F:. I then did the same with the two object handles (32DCB & 32968), just to be sure.

Finally, it dawned on me: when an object is assigned an ID, the info is stored in PM_Workplace:Location *and* in the object's data (in this case, in the folder's .CLASSINFO EA). Apparently, whenever checkini encounters an object whose data contains an Object ID, it cross-references this with the entry in PM_Workplace:Location.

G:\...\TEMPLATES's EA showed its ID to be <WP_TEMPS>, but PM...:Location said this was assigned to F:\...\TEMPLATES, so checkini wanted to be "helpful" and change G:'s ID. Since this ID was perfectly valid when booting G:, and since my setup on G: would be screwed up if I removed it, I answered "No".

Now, without some of this prior knowledge, DT alone wouldn't have enabled me to figure this out completely. However, being able to confirm that when booted to F:, <WP_TEMPS> pointed at the right folder on F:, and knowing that there is another setup on G: _should_ be enough info to cause any *cautious* user to answer "No" as well.

Example 2:

   Object 2E027 , Class WPProgram : Purchase ProNews/2
   Exename: E:\PN15B4\PURCHASE.EXE<-UNABLE TO ACCESS! Curdir: E:\PN15B4
 | Remove this object which contains errors? |
 |         YES         |         NO          |

I didn't doubt that checkini was correct, but I still wanted to see for myself. I selected the object handle (2E027), clicked Ctrl+Shift MB2 to display this program object's menu, then selected 'Properties'. As reported, it pointed at PURCHASE.EXE. Since this file had been included in previous distributions of ProNews/2, I decided to check the directory. Again, I used DT to pop up the menu for E:\PN15B4 and selected 'Open'. Scanning the directory, I found a PURCHASE.APP but no PURCHASE.EXE. Satisfied that the object was unusable, I told checkini to delete it. (BTW... this is the only bug I've found in PN v1.51b4 so far.)

FWIW... Example 1, along with my description in the original article of how I "lost" G:'s Desktop, suggests that it's a *bad* idea to look at one installation's standard system folders from another setup on the same machine. Example 1 also suggests that you're not doing yourself any favour by having it automatically answer "Yes" to every question. User intervention *is* required for optimal results!

There is no official way to query the OBJECTID of a given object. However, my WPTOOLS.DLL does have some functions to do it. WPTOOLS.DLL is part of the WPTOOLxx.ZIP archive. Please look at:

Hmmm. You're right, I misread that, I guess :-( How ' bout this rexx instead:

 /* OBJECTID.CMD - Display object ids known to Workplace Shell */
 call rxfuncadd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs'
 call sysloadfuncs
 call SysIni 'USER', 'PM_Workplace:Location', 'All:', 'ids.'
   do i=1 to ids.0
     Say ids.i

PMFJI... but this is a perfect example of where my favourite DragText feature (WPS links) would be uncommonly helpful.

Once you have a listing of object IDs, you can use DragText to manipulate them as though you had a folder full of shadows rather than words in a window. You can select an ID, then drag the object it refers to, or you can pop up its WPS menu. DT adds the object's name to the top of the menu and gives it a submenu that shows the full path. This makes it easy to identify what <PDP_SMARTPFA> refers to (F:\Desktop\OS!2 System\Problem!!Determination Tools\Hard File Monitor). Selecting this menu item will take you directly to the named object. Of course, you can use most of the other menu entries too (Open as, Copy, etc).

You can skip the script if you have an ini editor that uses a listbox to display its info (most do, regedit2 doesn't). Point it at PM_Workplace:Location in os2.ini, then select an object ID from the list. And, if you want skip the script but still have a listing, you can use DT to drag the entire contents of the listbox to somewhere more convenient - your editor, a file, etc.

Open View IDs

From, same as in Setup strings list:

   -1  UNKNOWN
    0  DEFAULT
    1  CONTENTS (icon view)
    3  HELP
    4  RUNNING (run pgm; for data files, run associated pgm)
  101  TREE (tree view)
  102  DETAILS (details view)
  120  AUTO (WPDisk objects only)
  121  PALETTE (color and font palettes, plus the LaunchPad)
 4096  the 1st pgm associated with a data file (usually 1st on its Open menu)
 4097  the 2nd pgm associated with a data file (usually 2nd on its Open menu)
 5000  the 1st pgm added to a data file's Open menu using the Menu page
 5001  the 2nd pgm added via the Menu page
25856  USER (proprietary view IDs start here;  USER+1 is most common)
42818  TextView (OD v1.0)
46914  TextView (OD v1.5)

Boilerspace Template

Change SETVIEW.CMD to the name of your script.

Keep in mind that /* should start the script, dependent on how you copy this script, you may need to unindent the first line. In view.exe, use Control-Insert to Copy the contents of this window to a clipboard, then Paste into your favourite editor.

 /*   drop a file on this script's icon, or */
 /*   invoke it from the command line passing the filename as an argument */

 call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
 call SysLoadFuncs

 arg object
 arg = strip(object,,'"')              /* Spaces in argument => quoted arg */

... Put the code at this place! 


strip() in REXX for spaces in filenames

FYI #1... because of limitations in REXX, you can only set the attributes for abstract objects like program objects or shadows if you have the object's Object ID (e.g. <WP_OS2WIN> for your OS/2 Window program object). For files and folders, you can supply the fully qualified name instead.

FYI #2... the "strip" command in my REXX Boilerspace template lets you drop files whose names contain spaces onto your cmd icon. Without it, these names will be passed to REXX with surrounding quotes that will cause functions to fail.

<< DESCRIPTION -- Index -- .CLASSINFO, 90 sec delay, DEFAULTVIEW >>