Series: OS/2 development
Author: Ilya Zakharevich see note
Homepage: ftp site
+ EDM/2 mirror

NAME

HOWTO-wps-details - how to programmatically fight with WPS


DESCRIPTION

Programmatic access to WPS is complicated due to several reasons:

However, some stuff can be done even with such low-grade stuff as plain REXX.


TOOLS

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:

WPTOOLS.DLL is also accessible from REXX. Beware: there are tools which require uncompatible 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 ancessors, icon styles (no-delete etc), methods, interface.

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

RWX
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
 http://www.os2ezine.com/v3n07/wpsetup.txt

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

WPObjData
 http://www.os2ezine.com/v3n07/hammer.htm

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

WPSTools:
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

Perl
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 absense of an interface to DII).

DragText

Are you saying I can hilite 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
  =================================================
    OBJECTID <WP_TEMPS> (from 32DCB - G:\DESKTOP\ALL\OS!2 SYSTEM\TEMPLATES)
    POINTS TO ANOTHER OBJECT 32968 - F:\DESKTOP\ALL\OS!2 System\TEMPLATES
  愔种种种种种种种种种种种种种种种种种种种种种种种种种种种种种种种种
   Assign a new OBJECTID to G:\DESKTOP\ALL\OS!2 SYSTEM\TEMPLATES?  
  帋帋帋帋帋帋帋帋帋帋帋帋帋帋帋帋稁帋帋帋帋帋帋帋帋帋帋帋帋帋帋帋庺
                 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:

  Folder : F:\DESKTOP\PRONEWS!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 favors 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: http://www.os2ss.com/information/kelder/

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
    end

PMFJI... but this is a perfect example of where my favorite 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 Monito r). 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 http://www.os2ezine.com/v3n07/wpsetup.txt, same as in Setup strings list:

    -1  UNKNOWN
     0  DEFAULT
     1  CONTENTS (icon view)
     2  SETTINGS
     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)
   etc
  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
   etc
 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, dependint 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 favorite editor.

  /* SETVIEW.CMD */
  /*   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!

  exit
  ReportRC:
  parse arg rc
  if rc
  then
     say "Success"
  else
     say "Failure"
  return

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.


.CLASSINFO, 90 sec delay, DEFAULTVIEW

After deleting the CLASSINFO EA did you reboot, or at least restart the WPS?

The WPS only looks at this EA when it ``awakens'' an object (typically, when you open the folder containing the object); thereafter, it uses its in-memory copy of this info. Restarting the WPS clears this.

OTOH, If you close the folder in question, and you don't have anything open in tree-view which includes this folder, the WPS will put the objects to sleep after about 90 seconds (i.e. it will remove them from memory). With the CLASSINFO gone and no memory of the objects' previous settings, the WPS should use the association currently in force.

If you're in a hurry <g>, use this (see Open View IDs for 4096) in Boilerspace template:

  call ReportRC(SysSetObjectData(object,"DEFAULTVIEW=4096;"))

Sample script to set .TYPE and .CLASSINFO

I want to change all files with an extension of jar files to TSZipMgr so that jar files can be opened by the OD Zip Manager. [snip] I'll come up with a REXX script that will perform at least part of the work.

Paste or drag the following into a file named jarz.cmd, then drop objects on it or use it from a command line. Your jar files should change class when you restart the WPS. It may happen sooner if the folder containing the objects is closed for about 2 minutes. YMMV.

  /*****************************************************************/
  /* JARZ.CMD                                                      */
  /* (C) Copyright R L Walsh 1999 - All Rights Reserved            */
  /*                                                               */
  /* JARZ resets .JAR .ZIP, and optionally .EXE files'             */
  /* filetype to "ZIP File" and deletes their WPS class data.      */
  /*                                                               */
  /* Each file should become an instance of whatever WPS class     */
  /* handles ZIP Files (a reboot may be needed).  It may also      */
  /* become associated with programs that handle this file type.   */
  /*                                                               */
  /*****************************************************************/
  /* DATA                                                          */
  /*****************************************************************/
  /* the list of acceptable extensions;  ext.0 sets the "last"     */
  /* item in the list (e.g. '2' excludes EXEs, '3' includes them   */
  ext.0 = 2
  ext.1 = '.jar'
  ext.2 = '.zip'
  ext.3 = '.exe'
  /* The          Curr one       8 data    EA                      */
  /* EA:    MVMT CP   item ACSI chars     value                    */
  typeval = 'DFFF 0000 0100 FDFF 0800'X || 'ZIP File'
  /*****************************************************************/
  /* CODE                                                          */
  /*****************************************************************/
  parse upper arg junk
  junk = strip(junk)
  if (junk = '' | junk = '?'  | junk = '/?' | junk = '/HELP') then
  do
      say ''
      say '    JARZ resets .JAR .ZIP, and (optionally) .EXE files' || "'"
      say '    filetype to "ZIP File" and deletes their WPS class data.'
      say ''
      say '    JARZ filespec [filespec [...]]'
      say ''
      say '         filespec = file name (wildcards OK), or'
      say '                  = directory name (no wildcards)'
      say ''
      say '    See the comments in jarz.cmd for additional info.'
      exit
  end
  call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  call SysLoadFuncs
  /* the big loop that's executed for each file spec               */
  do while junk \= ''
  /* deal with quoted names, then clean up string                  */
      if left(junk, 1) = '"' then
          parse var junk '"' filespec '" ' junk
      else
          parse var junk filespec junk
      filespec = strip(filespec)
      filespec = strip(filespec,,'"')
      if filespec = '' then
          iterate
  /* rustle up some files                                          */
  /* note:  SaySFTErr performs an exit so it never returns         */
      rc = SysFileTree(filespec,'file','FO')
      if rc \= 0 then
          call SaySFTErr
  /*  if that didn't work, see if the filespec is a directory      */
      if file.0 = 0 then
      do
          rc = SysFileTree(filespec,'file','DO')
          if rc \= 0 then
              call SaySFTErr
  /* if we didn't get exactly one dir back, make this a no-op      */
  /* else get a list of all files in this dir                      */
          if file.0 \= 1 then
              file.0 = 0
          else
          do
              filespec = file.1 || '\*.*'
              rc = SysFileTree(filespec,'file','FO')
              if rc \= 0 then
                call SaySFTErr
          end
      end
  /* for each file, see if it's extension is on the list           */
  /* if so, have DueDamage change its EAs                          */
      ctr = 0
      do i=1 to file.0
          do j=1 to ext.0
              if right(file.i,4) = ext.j then
              do
                  call DueDamage
                  ctr = ctr + 1
                  leave
              end
          end
      end
      say ctr 'files processed for <' || filespec || '>'
  end
  /* bottom of the big loop                                        */
  say 'Exiting'
  exit
  /*****************************************************************/
  DueDamage:
  /* write a null value for .CLASSINFO                             */
      rc = SysPutEA(file.i,'.CLASSINFO','')
      if rc \= 0 then
          err = 'removing .CLASSINFO'
      else
  /* write new value for .TYPE                                     */
      do
          rc = SysPutEA(file.i,'.TYPE',typeval)
          if rc \= 0 then
              err = 'resetting .TYPE'
      end
  /* display either the filename or an error message               */
      if rc = 0 then
          say Filespec('name',file.i)
      else
          say 'Error #' rc err 'for file' Filespec('name',file.i)
      return
  /*****************************************************************/
  SaySFTErr:
      say 'Error #' rc 'in SYSFILETREE for <' || filespec ||'>'
      say 'Exiting'
      exit
  /*****************************************************************/

Effects of lost EA

You're right, the problem is the EAs - but why they aren't copied onto a floppy is beyond me. Bad news: you've lost 2 EAs. Good news: you can recover the one that counts and gain some functionality.

.CLASSINFO
this identifies the file as a WebEx_Url to WPS. Unlike most file-based classes, WebEx_Url doesn't reconstruct this, so when it's gone, it's gone. No big loss: you've lost the icon and special notebook.

.TYPE
this is set on the first page of a standard datafile's notebook and is what the WebEx app uses to identify Urls. Set your copied files to type 'WebExplorer_Url' and they'll become acceptable to WebEx. Open WebEx's notebook and associate it with objects of this type. They'll get WebEx's icon and open WebEx when you doubleclick on them.

The EAs for *most* files are completely superfluous. The exceptions are those files which need their EAs to be recognized as belonging to a specialized WPS class or to be given special handling by an app. This usually applies to files without a distinguishing file extension. In these cases, the WPS relies on their .TYPE or .CLASSINFO EAs.

A good example is a URL object: see URL objects. (Effectively, different programs use .TYPE or .CLASSINFO EA to distinguish the URLs objects from data files.)

FYI... The WPS uses a file's extension or filetype to assign it to a class only if it lacks a .CLASSINFO EA. Once it has acquired this (typically by opening the object's Properties notebook), the extension or type no longer matters and can be changed or deleted without affecting the file's class assignment.

For folders, the only EA that really matters is .CLASSINFO, and then, primarily for folders in your Desktop tree. Folders such as Desktop, Templates, and Nowhere only possess special properties because their CLASSINFO EA identifies them as belonging to a specialized class. Loss of their .CLASSINFO will cause serious system disruption.

Some of your Desktop folders may be generic WPFolder objects, but their .CLASSINFO contains their Object ID which the system may rely upon. Since the Object IDs are also stored in os2.ini, loss of these EAs isn't that critical. Checkini will identify the problem and fix it. For all other folders, all you'll lose is your customizations such as sort order, icon positioning, etc.

Miscellanea: If you have files or folders with longnames on a FAT drive, you'll lose the name when the .LONGNAME EA is stripped. On any file system, titles that include illegal file characters like linefeeds or backslashes will be lost. When restored, the titles will match the file or folder's real name and have exclamation points where the illegal characters were.

A very few exe's will lose their icons when their .ICON EA is removed. In most cases, the WPS can look in the file to get the icon, but in some cases this fails. Other than this, you can safely strip the EAs from your application files and never notice the difference.

In those cases where the EAs _are_ critical, use EAUTIL to strip them before backup and to restore them when you return the files and directories to use. Better yet, use backup and restore products that were designed for OS/2. If all else fails, use Info-zip, then backup the zips.

Menu items

So you're saying there's no way to do what I want to do? Those menu items have to be stored SOMEWHERE. Even if I can't use a standard API, there's got to be a way to add these menu items. Are they part of the EA's for the Desktop folder?

Yes they are. They are stored in the .CLASSINFO ea.

As I recall well, there has been a beta toolkit for Warp 3 that even included the syntax for adding menues to objects of WPFileSystem or derived classes. Unfortunattely, this vanished again in the non-beta version. It didn't work anyway....

Theoretically, you could alter the .CLASSINFO EA, but I am not sure you will be able to keep the changes since the WPS tends to overwrite this EA on shutdown.

I can tell you where exactly it is stored. Should you want this, please first download my 'icontool' from my homepage since this will help you is understanding what I mean.

Still I wouldn't advise you to do this...

Henk Kelder


PMWP entries in POPUPLOG.OS2

I've been looking at this for quite a while, and have come up with a possible explanation and a cure that's worse than the disease. AFAIK, the WPS uses ``deferred parameter checking'' - IOW, it doesn't check parameters for validity, it just uses them. If they cause a trap, the WPS's exception handler cleans up, usually by aborting the current operation. As such, PMWP isn't the ``cause'' of the problem, just the unsuspecting victim of bad data. Overall, the system is working as designed.

SHELLEXCEPTIONHANDLER

If you're really hell-bent on eliminating this, you can try adding this line to config.sys:

  SET SHELLEXCEPTIONHANDLER=OFF

This turns off the WPS's exception handler, guaranteeing any errors will cause a crash. It's normally used by developers of WPS classes to keep the WPS from covering up bugs in their code. (That's why I've pursued this problem so vigorously: with the exception handler off, I couldn't keep the WPS up long enough to begin my debugging.)


Lost/broken desktop or broken Templates or Startup

Where to begin... How about a warning? The best way to ``lose'' your Desktop (without suffering any real damage) is to access one installation's Desktop from another setup on the same machine. E.g. I installed FP14 on my alternate setup, then later started looking at its Desktop from my FP7 setup. When I rebooted to the FP14 system, all I got was a command window on an empty Desktop.

First step: edit config.sys and add this line, then reboot.

    SET DESKTOP=C:\DESKTOP

(see Order of DESKTOP and <WP_DESKTOP>). If everything comes back as it should be, run the following code

  call ReportRC(SysSetObjectData("C:\DESKTOP","OBJECTID=<WP_DESKTOP>"))

(put this in Boilerspace template); then ``rem-out'' the line in config.sys until the next time it's needed. You need to run the REXX script or else many installers will be unable to create Desktop objects; you'll want to disable the config.sys entry so you'll know when a problem has occurred. These two steps will solve most lost Desktop problems.

After rebooting, if your Desktop returns and all of the folders and files are present but all of the program objects, shadows, and miscellanea are missing, then os2sys.ini is probably corrupted. If you have pgm objects or shadows that point at files on other disks, see if they're still good in order to guage the extent of the damage. Also, pop up the Desktop menu and select 'System Setup'. Does the folder open?

At this point, you have several options (see also Script to recreate all or some lost objects). The best would be to restore a *recent* archive of your Desktop from the Alt-F1 boot screen. If you were able to open System Setup from the Desktop menu, you may instead want to restore recent backups of os2.ini & os2sys.ini, such as those made by checkini. You can either reboot to a command line and copy them over, or you can edit config.sys and (temporarily) change SET SYSTEM_INI= and SET USER_INI= to point to them, then reboot. If you choose the latter option, you can copy & rename the files and reedit config.sys after you're satisfied with the results.

Lacking recent backups, you still have some options. First run checkini in diagnostic mode (i.e. *without* the ``/C'' option). If you weren't able to open System Setup from the Desktop menu, see if it offers to assign the object ID <WP_CONFIG> to the System Setup folder (and makes similar offers for other standard folders as well). This will determine whether you'll be forced to run MAKEINI. Also, see if it finds valid objects assigned to ``missing'' folders. If so, you should be able to recover them when you run it again in ``fixit'' mode.

If opening System Setup wasn't a problem, or if checkini offered to fix it, you can rerun checkini with ``/C'' to recover as much as possible. Avoid letting it delete anything and skip the final filehandles check altogether. After a reboot, see how things look. You may have to drag a lot of recovered objects back to their proper folders, and some things may still be screwed up. By not deleting anything on the first run, you may have invalid program objects but at least you'll know what you used to have and what needs fixing. When things are back to normal, then run checkini again and let it do all the cleanup still required.

My repeated mention of opening System Setup from the Desktop menu is simply a quick way to see if the standard folders have the object IDs they need for a properly functioning system. If they don't, then you probably have other problems as well that need fixing. For this you'll want to run a *non-destructive* MAKEINI with this command line (after making a backup):

    MAKEINI OS2.INI INI.RC

Before doing so, you may want to customize INI.RC and eliminate or comment-out things you don't want (e.g. all those tired URL objects, or, at the end of the file, the 3 lines that will reset your display to VGA).

When you reboot, the WPS will create a new Desktop with all new folders and objects, and will rename your current (defective) one as Previous Desktop. After another reboot (just in case), run checkini and see what it can recover (in this case, let it remove any duplicate object IDs it finds from the previous Desktop's objects). Chances are that you'll have to drag a lot of things from the old desktop to the new.

When this long ordeal is finally over, you can delete the previous or temporary Desktop folder(s). Because they have the NODELETE style, you'll have to get rid of this before 'Delete' appears on their menus. One way is to plug this into the Boilerspace template):

  rc = SysSetObjectData( "C:\PREVIOUS DESKTOP","NODELETE=NO")

Except for a few details here and there, AFAIK, that about covers it. Did I answer your question, Barbara?

BTW... since I haven't plugged DragText yet, I should mention that it can be a handy adjunct when dealing with these problems, e.g., validating required object IDs (as found in INI.RC), accessing & examining objects as checkini finds them (via the numeric object handles it displays for each), etc. See DragText.

Order of DESKTOP and <WP_DESKTOP>

If D:\DESKTOP does exist and your config.sys says SET DESKTOP=D:\DESKTOP, the WPS will attempt to use it. If that directory doesn't exist, of course you're going to have problems.

If this line is not in config.sys, the WPS will try to locate the Desktop using os2.ini info. If that info is missing, you'll have your current problem. Use the following REXX script to restore the info to os2.ini. Just be sure that it points to your current, *valid* Desktop path (and don't forget to delete the ``set desktop='' line in config.sys).

Details on lost desktops

[More on Lost/broken desktop or broken Templates or Startup.]

This problem comes in two flavors: ``plain vanilla'' and ``rocky road''.

First, restore the backup ini files (even though they didn't work last time). In config.sys, add ``SET DESKTOP=E:\DESKTOP'', then reboot. This will point PM at your original Desktop directory. If all your program objects, shadows, and other non-filesystem objects reappear, you had the ``plain vanilla'' problem. All you need to do now is run the REXX script below.

OTOH, if only files and folders reappear and/or you get unexpected objects in unexpected places, you've got ``rocky road''. In this case, consider yourself lucky if you can recover any of your old setup. If you don't already have it, get wptool19.zip so you can run checkini.exe. The first time you run it, you may want to omit the ``/C'' command line parameter so that it only reports errors and doesn't try to fix them.

The first time you have it try to fix things, your primary goal is to have it recover objects that it says are located in non-existent directories. Say 'no' to most offers to fix other problems. After a reboot, your Desktop will be filled with folders full of found objects. Retrieve and fix your own objects but skip system-supplied ones. Things will be so messed up that you'd do well to run a nondestructive MAKEINI to recreate your System Setup, Startup, etc. folders and the objects therein (see Startup folder and ObjectID, Hanging template folder, Restoring System Setup or Templates, ini.rc and SysCreateObject, Script to recreate all or some lost objects). After that's done (and you've rebooted yet again), run checkini again to clean up the mess that remains.

FYI... the ``plain vanilla'' problem is common and easy to fix: the Desktop folder's Object ID (i.e. <WP_DESKTOP>) has disappeared, so the WPS can't find it. The REXX line in Lost/broken desktop or broken Templates or Startup restores it. The ``rocky road'' problem is semi-catastrophic: the file handles table in os2sys.ini got lost/corrupted and the system assigned all new handles to the files and folders on your E: drive. The WPS uses these handles to associate abstract (i.e. non- filesystem) objects with particular folders. Now that the folders' handles have changed, your abstract objects are no longer associated with any folder, so they're in limbo. Checkini will fix this by associating these objects with new folders it creates.

Startup folder and ObjectID

To actually do anything, your Startup folder must be of class WPStartup and have the object ID ``<WP_START>''.

For future reference... Chances are that this Startup folder had lost either its ObjectID (``<WP_START>'') or its .CLASSINFO extended attribute. ObjectID is easy to fix: use SysSetObjectData in a REXX script to restore it. Losing the EA that tells the WPS that this is a Startup folder renders it useless, so you have to create a new Startup folder. If you search \os2\ini.rc, you'll find any entry for this folder that contains all the parameters you'll need to recreate it using SysCreateObject. Note that the parms are *not* listed in the order that SysCreateObject requires, so you'll have to do some transposition. See ini.rc and SysCreateObject, Script to recreate all or some lost objects.

Hanging template folder

More than likely, there's some invalid object in there which is causing the hang - perhaps a template for some object class you've deregistered. Here's a list of steps you can take to fix things, starting with the most benign:

A final note: if you've installed Feature Installer, you probably have a template labelled Data File:1 that shows a hammer and screwdriver. Then see Data File:1 and NODELETE.

You can put this to good use if you want to delete undeletable templates. Open this file in a text editor (you can Shift-drag its icon to your editor's icon, then Shift-drop it). Add this single line (without quotes), then save the file:

  "NODELETE=NO"

Whenever you need to delete an undeleteable template, just drop it on this template. The dropped object will now have a Delete entry on its popup menu and can be deleted in any of the usual ways.

can't choose properties of Desktop

  When I press RMB on the desktop I can't choose properties. Does anyone
  know the reason? I used to be able to choose it. I have installed FP1
  and FP3 on my Warp 4.

When you say you ``can't choose properties'', do you mean:

 - that entry is missing from the menu?
 - the entry is present but disabled (grayed-out)?
 - you can select Properties but nothing happens?

I'm sorry... The properties entry is missing from the menu.

OK... Have you recently installed any WPS ``enhancements'', or more likely, any WPS security add-ons that are designed to keep users from changing things? If not, try the following REXX script. Either drop your Desktop folder icon on it, or run it from the command line supplying the path of your Desktop folder as an argument (i.e. settings c:\desktop ).

Put this in Boilerspace template:

  call ReportRC(SysSetObjectData(object,"NOSETTINGS=NO"))

Restoring System Setup or Templates

The desktop pop-up menu which displays the System Setup line to show the particular folder is still there, but doesn't bring up the folder. System setup itself is in the OS/2 system folder and is still there.

Can anyone tell me how to ``re-activate'' the System Setup line in the pop up menu?

I hope I'm not too late and you haven't done a reinstall... Try this (Put this in Boilerspace template):

  call ReportRC(SysSetObjectData("F:\Desktop\OS!2 System\System Setup","OBJECTID=<WP_CONFIG>"))

Similarly for templates:

  call ReportRC(SysSetObjectData("F:\Desktop\OS!2 System\Templates","OBJECTID=<WP_TEMPS>"))

ini.rc and SysCreateObject

Whenever you damge or destroy a system-supplied object, go to \os2\ini.rc, find the entry for the object, then reformat the parameters for use with the REXX SysCreateObject command. In this case, the line from ini.rc is:

  "PM_InstallObject" "Drives;WPDrives;<WP_CONNECTIONSFOLDER>;RELOCATE"
  "ALWAYSSORT=YES;NODELETE=YES;DEFAULTVIEW=ICON;OBJECTID=<WP_DRIVES>"

Below is a REXX script that uses these parms. Note that neither ``PM_InstallObject'' nor ``RELOCATE'' are applicable in a REXX script. OTOH, the ``REPLACE'' parameter included below is REXX-specific; it is documented in your online REXX ref. (N.B. this is for Warp v4; for v3, change <WP_CONNECTIONSFOLDER> to <WP_OS2SYS>)

Put this in Boilerspace template, SysCreateObject() call should be all on the same line:

  /* REXX script to recreate the Drives folder*/
  call ReportRC(SysCreateObject("WPDrives", "Drives", "<WP_CONNECTIONSFOLDER>",
    "ALWAYSSORT=YES;NODELETE=YES;DEFAULTVIEW=ICON;OBJECTID=<WP_DRIVES>",
    "REPLACE"))

Script to recreate all or some lost objects

  /* ReCreate.CMD - restore lost desktop objects              */
  /* by Greg Czaja - July 29, 1992                            */
  /*               - April 9, 1993  ver.2                     */
  /*                 handle 2.1-style INI.RC                  */
  /* the July 1992 REXXUTIL version is required for 2.0 GA    */
  /* (look for REXX20 in Lib 17 in OS2SUPPORT)                */
  /* no additional requirements for GA+SP or 2.1              */
  Call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  Call SysLoadFuncs;
  SysBootDrive=Filespec('Drive',Value('SYSTEM_INI',,'OS2ENVIRONMENT'));
  file_name=SysBootDrive||'\OS2\INI.RC';
  Say "The program will list all single standard objects from your desktop"
  Say "Reply Y(es) if you want recreate the listed object - E(nd) to end the program"
  Say "N(o) is the default if you press ENTER:"
  Do While Lines(file_name) > 0;
  line=Linein(file_name);
  If line='' Then Iterate;        /* skip blanks   */
  Parse Var line '"PM_InstallObject"' line;
  If line='' Then Iterate;        /* skip others   */
  Parse Var line '"'head'" 'line; /* get header    */
  Parse Var line '"'setup'"' .;   /* get setup string */
  Parse Var head title';'object';'location';' . ;
  Say title "- Yes/No/End ?";
  Pull reply ;
  If Left(reply,1) ='E' Then Leave;
  If Left(reply,1) <> 'Y' Then Iterate;
  If SysCreateObject(object,title,location,setup,'Update') = 0
     Then Say 'Error creating:' title;
     Else Say title 'created !';
  End;
  rc=Stream(file_name,'C','Close');
  Return 0        /* enjoy your desktop! */
  /*
  Did you delete your Command Prompts ? Shredded your Shredder ?
  This program restores the standard WPS desktop objects on 2.x.
  It will preserve any current settings/objects you may have created and this
  is its advantage over the Alt-F1 or MAKEINI method.
  You will need the latest REXX fixes (REXX20 available in library 17) to make
  it run correctly on 2.0 GA system, no fixes required on GA+SP or 2.1.
  */


URL objects

``Go to URL'' action

Can anybody explain me how to permanently set the ``Go to URL'' action on the ``open'' menu of the URL object?

You can't under Warp v3.0. The WebEx class explicitly resets the default view each time a WebEx object is ``awakened'' (made visible when the folder it's in is opened). I know this for a fact because the code outputs this debugging message:

    **WebExplorer:wpObjectReady(): wpSetDefaultView succeeded

Your only option under v3.0 is to use an EA editor to delete the .CLASSINFO extended attribute. Then the file will no longer be a WebExplorer_Url object and can be associated with WebEx (or rather, WebEx can be associated with files of type WebExplorer_Url). The file can still be dropped on WebEx to load the Url - WebEx looks at the type, not the object class, to determine whether you're dropping a Url or a file. (Confused? See URL objects.)

Under Warp v4.0 (Merlin), you won't have this problem because the new wpUrl class doesn't mess with your choice of default open actions. However, AFAIK, you will have to manually change each old WebEx object to open the browser you choose.

URL attribute: a guess

I think that this has to do with how the URL attribute is stored. Rather and an EA, I think that it is an ini file thing <sigh>. I found that object desktop's package system will work to transport URLs, or you can use a REXX program to rewrite 'em as webx URLs.

[Does URL objects refute this?]

URL objects

The WPS uses its .TYPE EA of ``UniformResourceLocator'' to assign it to the WPUrl class while NS/2 uses the EA to identify its special function. Without this EA, URL objects will revert to plain-text files when copied back into your system. You will have to reassign them a type to restore their functionality.

Some file objects belong to a particular class solely because their CLASSINFO EA says so. Warp 3's WebExplorer_Url class is an example. Even though these files have a .TYPE EA of ``WebExplorer_Url'' for NS/2's benefit, this class wasn't written to associate the type with the class. These files had to be explicitly created as ``objects'' (which always results in a .CLASSINFO EA) in order to belong to the WebExplorer_Url class. Stripped of their .CLASSINFO EAs, WebExUrls will also revert to plain-text files and you won't be able to restore them.

There's a frequent fundamental misunderstanding of what WebEx Url objects really are. They are nothing but files whose .TYPE EA is ``WebExplorer_Url ''. While WebEx and other apps may use PM's WPS interface calls to create them, WebEx itself is wholely ignorant of their object wrapper when it comes time to read them. As long as the app that originates a drag action identifies the file being dragged as a WebExplorer_Url, WebEx will be happy to accept and read it. The WPS need not even be loaded.

In Merlin, these files have become ``WPUrl'' objects and may or may not have the WebExplorer_Url .TYPE EA. However, the WPS still identifies them as such during a drag to keep WebEx happy. (Unlike the WebExUrl class, Merlin's WPUrl class is automatically associated with any file having this .TYPE EA.)

Here's an experiment or two to demonstrate the above: - use EPM (or any editor that doesn't add a Ctrl-Z to the end of a file) to create a file with a valid URL. After saving it, open the file's settings notebook, delete any Current Types, and add WebExplorer_Url from the list of Available Types. Now drag and drop the file on WebEx. The URL will be loaded, even though it isn't a ``WebExplorer_Url'' object. - start Merlin, then look at the file's Object Class in a Details view of its folder. You'll see that it's WPUrl. Open its properties notebook: it should be that of a Url object. If it isn't, you'll have to use the ``Become'' tab to make it one; after a restart, it will belong to the WPUrl class.

BTW... *no* WPS objects are ``EAs hanging off the directory''. If an object is filesystem-based, it has its own .CLASSINFO EA that is used by the WPS. If the object is abstract (like a Program reference object), the classinfo is stored in OS2.INI.


WPObjData and ``Hammer and ...'' icons

Just curious. Back when I applied FP1 to Warp 4, my e.exe lost its pretty icon due to the ea glitch. I got the icon back from one of my previous files & everything was fine. Now we have FP3. Things have seemed to be golden since the service. Now I notice many of my *.txt files that would normally be associated with e.exe (and still open with it) have a new icon consisting of a rather drab looking screw-driver and hammer. Is my system secretly trying to make me feel more like a man or is this something to worry about? TIA.

These files have been sucked up by the WPObjData class which is an adjunct to the Feature Installer (WPInstall). Apparently, the people who are writing these WPS classes don't know how the WPS works. The files WPObjData creates are supposed to be of type ``Plain Text''. However, the way they wrote it, *any* Plain Text file becomes an instance of WPObjData if it isn't already classified as a WPDataFile. Your best bet is to deregister WPObjData using this REXX script, then restart the WPS.

Put this in Boilerspace template:

  call ReportRC(SysDeregisterObjectClass("WPObjData"))

Finally fixed!

You'll be pleased to know that IBM *has* finally addressed the problem: the version of WPObjData that comes with WSeB no longer exhibits this obnoxious behavior. Let's see... I first posted the script Tim cites on Sept 20, 1997 and the fixed version of objdata.dll is dated April 5, 1999. So, it only took 19+ months to correct - pretty good for ``them'' <g>.

FYI... You may want to read my article in os2ezine, _Using That Hammer and Screwdriver_ (http://www.os2ezine.com/v3n07/hammer.htm), for a way to both tame WPObjData and to put it to work doing something useful.

WPInstall not registered

My guess is that the WPInstall class isn't registered. You should be able to restore it by installing the latest Feature Installer, or by using the following script (I assume you have an INSTALL.DLL in C:\OS2\DLL). Put this in Boilerspace template:

  /* REXX script to reregister the WPInstall class*/
  rc = SysDeregisterObjectClass("WPInstall")
  call ReportRC(SysRegisterObjectClass("WPInstall","C:\OS2\DLL\INSTALL.DLL"))

Data File:1 and NODELETE

gobbled up a template and then everything froze. CAD brought me back and the template had been deleted and the entry had been removed from the ini (not by me).

This needn't be so difficult. You either have, or can have, an object that will make other objects deleteable. If you're running Warp 3 or 4.0 and have installed Feature Installer, you probably have a template labeled ``Data File:1'' whose icon shows a hammer & screwdriver. If running MCP or eCS, you have the required dll but the WPS class it contains (WPObjData) is not yet registered. Once this is set up, you'll be able to drop most any object on your ObjData icon to restore the Delete option to its menu. And, your system will not freeze up (well, it certainly shouldn't...).

If you don't have the ``hammer & screwdriver'' template, register the class using the script below. Doing so will create a new template. While you could create a normal object from the template, you'll probably have little other use for it, so edit the template itself. Drag the template to your editor's icon, press Shift to make it droppable, then drop. The object is actually an empty datafile to which you will add this one line:

    NODELETE=NO

Save the file, then try out its template object. Drop something that's undeleteable on it, then pop up the dropped object's menu. There should now be a usable ``Delete'' entry on it. I've found that some classes will restore their NODELETE flag if you manipulate them or drag them to the shredder, so delete the object ASAP after using your ObjData icon.

FYI... you could use a REXX script to do this for files and directories, but REXX can't operate on abstract objects like Program Objects unless they have an object ID. A WPObjData object will work with any type of object (if a file has its ``read-only'' or ``system'' attributes set, you may have to turn these off first).

Put this in Boilerspace template:

  /* OBJDATA.DLL _should_ be in your os2\dll directory and           */
  /* accessible via your LIBPATH statement.  If it isn't,            */
  /* it may be in your FISETUP directory;  in this case you          */
  /* must supply the dll's full path & filename, e.g.                */
  /* SysRegisterObjectClass('WPObjData','E:\FI\FISETUP\objdata.dll') */
  /* Be sure to use a file dated June 7, 1999 or later - earlier     */
  /* versions had a major bug and were a real PITA                   */
  call ReportRC(SysRegisterObjectClass('WPObjData','OBJDATA'))


WPVault, x:/NOWHERE, NOTVISIBLE, SHOWALLINTREEVIEW

Don't worry, you couldn't dereg/delete this class if you wanted to. Normally, WPVault is only assigned to the Nowhere folder; it is intended to make it hard for you to mess this folder or its contents. The WPS sets the physical directory's attributes to system and hidden, and the WPS object's attributes to NoMove NoDelete NoPrint NoDrag NotVisible NoRename.

You can also try aplying the following setting against x:\NOWHERE:

 NOTVISIBLE=NO;SHOWALLINTREEVIEW=YES

(see the recipe in can't choose properties of Desktop). Suddenly all objects in Nowhere appear in the treeview and can be seen...

That's an interesting way around the visibility problem. However, I think there's actually more there than meets the eye.

Under Warp 3, at least, <WP_NOWHERE> contained a lot of transient objects of classes WPFilter, WPFinder, WPFolderCV, etc. On my Warp 4 system, I know these objects exist but I can't locate them. Since each of these classes has a style of ``Private'' (which means ``hidden''), I'd assume they're still in Nowhere but totally inaccessible using conventional means.

In addition, some of the conventional objects in Nowhere have an object style of ``NotVisible''. Most notable is <WP_VIEWINF> which is the default viewer for *.INF files. Most of the objects that are visible on my system (other than the COM and LPT objects) appear to have been put there either by WarpCenter or Object Desktop.

x:/NOWHERE and NOTVISIBLE

Nowhere contains objects ``they'' don't want you to mess with, e.g. the program object for view.exe that's associated with *.INF. It also contains WarpCenter & LaunchPad shadows, some Netscape helper apps, plus objects for your COM, LPT, and remote printer ports. It may also contain junk - some people may still have remnants left by the NSv4.61 beta.

In Warp v4 (at least), you can't open Nowhere, display its menu, or show its properties notebook. However, you *can* see its contents by running the script below, then opening your boot drive in tree view and pressing the ``plus'' button next to Nowhere's icon. (Note: I've played with my system so much that YMMV greatly as to what you can see. For example, mine always shows some objects; running the script below simply increases the number visible.)

If you have more than one Nowhere directory, you should be able to identify the one in use by the presence of the port objects (assuming you can see them at all). Another way is to use the folder's Object ID (<WP_NOWHERE>) rather than its path the first time you run the script. Whichever folder is expandable is the one in use.

Put this in Boilerspace template:

  /* this makes visible two objects that are normally hidden */
  rc = SysSetObjectData( "<WP_VIEWINF>","NOTVISIBLE=NO")
  rc = SysSetObjectData( "<WP_RJAPPLETPROGREF>","NOTVISIBLE=NO")
  /* substitute <WP_NOWHERE> for the path on the first run to
     help identify which of several Nowhere folders the WPS is
     actually using */
  call ReportRC(SysSetObjectData( "C:\NOWHERE","SHOWALLINTREEVIEW=YES"))

SHOWALLINTREEVIEW

SHOWALLINTREEVIEW=YES ? What does this do, and where is this statement placed ? If this does what I think it does, I'll be wondering why the hell IBM didn't make this default.

This causes folders to display all their contents in Tree view, rather than just subfolders. You can apply this attribute to any folder using this REXX script. Supply the name of a directory when you run it (e.g. SHOWALL C:\DESKTOP), or simply drop a folder on its icon.

Put this in Boilerspace template:

  call ReportRC(SysSetObjectData(object,"SHOWALLINTREEVIEW=YES"))

SHOWALLINTREEVIEW and old (Warp 3) folders

The ability to show a folder's entire contents was added in Warp v4, but nothing was added to the folder notebook to turn this on. Instead, you have to use REXX; the script in SHOWALLINTREEVIEW will do the trick.

NODELETE and Templates

  | >I have several objects that were created by Devcon. They are extremely
  | >annoying and I would like to be rid of them. Simple deletion doesn't work,
 so
  | Go to the 'general' page of the settings notebook.  Uncheck the
  | template checkbox, close the notebook and delete 'em.

That's not enough for the Warp Toolkit objects: they are created with the object NODELETE attribute, which you can't get at from the WPS (unless you use an object inspection utility).

You *can* zap them with REXX, though:

  call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SYSLOADFUNCS'
  call SysLoadFuncs
  call SysSetObjectData 'C:\Desktop\OS!2 System\Templates\Carpp', 'NODELETE=NO;'

Remove the Template attribute as above, then you can delete them.

Ok, that partially worked...it makes the objects ``deletable'', but they come back after I delete them (i.e. Run script, Delete object, Close folder, Open folder, IT'S BAAAACK). Any other ideas? Mayhaps a recommendation as to an ``object inspection utility''? Preferrably one that will let me kill the objects?

Every time you open the Templates folder, it populates itself with a template for every class that supports ``Create Another''. If the template for a class is missing, it asks the class to create another. The only way to permanently get rid of them is to deregister the class. If that's what you want to do, add this line to the script above:

    Call SysDeregisterObjectClass "[name of class]"

Run the script, delete the object, close the folder, restart the WPS. The template, the class, and any supporting os2.ini entries will be gone for good.


.HLP not shown in view.exe

IZ: applicable only to Warp 4 (view.exe would not open hlp, use viewhelp.exe).

OTOH, if you can't dblclick on a HLP to open it in the right app, it's because HLP files don't have any pre-assigned association. During installation, OS/2 creates a hidden program object in your Nowhere folder (also hidden) and associates it with *.INF. To access this object's notebook so you can add *.HLP to its associations, run this REXX script (Put this in Boilerspace template):

  call ReportRC(SysSetObjectData("<WP_VIEWINF>","OPEN=SETTINGS"))

[Probably you need to make Nowhere visible first, see x:/NOWHERE and NOTVISIBLE.]


Drag & Drop of .dev and printers

If you drag and drop a printer file it will assume you want to install it. I don't know the answer to your question though, but am also curios to know. I would just drop to the command line & copy it from there.

When I responded to Timur's original posting, I suggested he go to the ``Become'' page of the file's notebook and change its class to WPDataFile. Contrary to my normal practice, I didn't fully test the results and was later reminded why I (almost) always test before posting: when I went to drag my test file the next day, it wouldn't budge. Even though the object's class had changed, its ``style'' settings hadn't. The following REXX script fixes that. Just replace ``C:\junk\test.drv'' with the name of your problem file, then run it.

Put this in Boilerspace template, see Open View IDs for DEFAULTVIEW=4:

  call ReportRC(SysSetObjectData("C:\junk\test.drv", "NoMove=NO;NoLink=NO;NoCopy=NO;NoDrag=NO;DEFAULTVIEW=4;"))

BTW... do *not* move a real printer-driver file if you've installed one of the printers it supports.


Start a VIO window with a changed font size

Here's a REXX script that does what's needed (on my system, at least). YMMV because of timing issues (i.e. it's possible that the font could get reset before the window uses this setting).

Notice that I've included two different ways to invoke scache: by running it directly and by opening a program object that runs it. I feel more comfortable with the latter, but it requires that the pgm object have an Object ID (in this case ``<SCACHE>''). I added mine after the fact using a feature of DTProgram.

  /* SCACHE.CMD - saves old font size, sets a new size, */
  /* invokes smartcache, then restores old size         */
  /* note:  if the font is "14x8", y=14 & x=8           */
  call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  call SysLoadFuncs
  x = 8
  y = 8
  sav = SysIni('USER','Shield','~Font Size...')
  new = d2c(x) || d2c(y)
  rc = SysIni('USER','Shield','~Font Size...', new)
  /* OPEN PROGRAM OBJECT */
  rc = SysOpenObject('<SCACHE>','4','TRUE')
  /* RUN DIRECTLY */
  /* 'CD F:\JAVA11\SCACHE'
  'START F:\JAVA11\BIN\JAVA.EXE -ms1m scache' */
  rc = SysIni('USER','Shield','~Font Size...', sav)


Desktop background

Is there a way to find where the desktop's background is stored and change it? I've heard it's possible with the WinSetObjectData() function but I don't know how to do this?

Yes, you do use WinSetObjectData(). You can find the relevant setup string in the WPS Programming Reference. e.g.

  WinSetObjectData(WinQueryObject("<WP_DESKTOP>"),
    "BACKGROUND=c:\somewhere\something.bmp,T,1,I;");


Properties of the root directory

The easiest way to clear up problems in a root directory is to erase ``WP ROOT. SF''. You'll have to turn off the hidden and system attributes and you may have to Alt-F1/boot to a command line to actually delete it (I don't recall). After doing so, you'll have to open this drive's notebook and reset whatever properties you normally change (e.g. sort order, includes, etc). Doing so will recreate this file.

FYI... Root directories have no EAs, so ``WP ROOT.SF'' provides an alternate means of storing WPS info. The file itself contains the root's .CLASSINFO. Any other EAs that would be attached to a directory (e.g. .ICONPOS) are attached to this file instead.


PM_Workplace:Location

See DragText.


PM_Workplace:Templates

See Hanging template folder.


AUTHOR

Compilation, editing, and tools info by Ilya Zakharevich. The rest obtained from Google using the search string

  classinfo extended attributes

and from Google groups with

  classinfo extended attributes group:*.os2.*
  classinfo wps group:*.os2.*
  sysloadfuncs group:*.os2.* author:walsh
  classinfo group:*.os2.* author:walsh

Most prolific info-producer is Rich Walsh (with a giant margin).

   http://www.usacomputers.net/personal/rlwalsh/

Particular chunks are not attributed to their authors, please look on Google again.