The &xshutdown; feature has cost me a lot of thought, because it is really not documented anywhere what happens during the normal shutdown process.

&os2; per default knows two different shutdown APIs:

Trouble is, there is no function "in between" these two. If you call DosShutdown the WPS data is not saved. And if you call WinShutdownSystem you get the regular shutdown without any further chance to interfere. So basically, I had to recode a complete new WinShutdownSystem, which will now be explained. This was quite difficult, since IBM hardly explains anything about what is really going on during WinShutdownSystem.

Note: In &xwp;, the "eXtended Shutdown" and "Restart Desktop" routines share the same code; they only differ in what happens after all windows have been closed. I will thus use the term "&xshutdown;" in the following explanations for both features, unless otherwise stated.

&xshutdown; is integrated into the WPS and relies heavily on the &xwp; class replacements. I have intentionally not put the &xshutdown; code into a separate .EXE file for two reasons: for one, &xshutdown; needs access to WPS internal data, which is only available from the SOM context; second, I want to prevent people from trying to use &xshutdown; separately, without having the &xwp; classes installed, because this could severely damage the Workplace Shell. In more detail, &xshutdown; relies on the XFldObject replacement class and the &xwp; Worker thread, which cooperatively keep track of the WPS internal data.

To understand what &xshutdown; is now doing, it is necessary to understand how the WPS handles its objects internally. Every single object which becomes relevant to the WPS at some point, be it through populating a folder or querying its settings or starting a program or whatever, is -- in WPS terminology -- "awakened" by the system, which means that it exists as a SOM object in memory.

The WPS only very rarely puts awake objects back to sleep though, which would free the associated memory and store the object's data back to disk. This has two consequences:

  1. There are always many more awakened objects on your system than you would actually think, because most of them aren't currently visible. Even after you close an open folder, the objects therein remain awake; this speeds up populating the folder when it's opened a second time. As a result however, the WPS eats up more and more of your memory with each folder you open. (If you have turned on the &xshutdown; log file, you can see how many awake objects were saved by &xshutdown;; these are usually several hundred objects, even though &xshutdown; doesn't save all awake objects, but only descendants of WPFolder and WPAbstract. On the "Internals" page in the Desktop's settings notebook you can take a look at how many objects are currently awake.)
  2. A change to the object's data sometimes has only an effect on the SOM object in memory, but is not always saved to disk or the OS2.INI / OS2SYS.INI files. This is why sometimes the WPS gets into trouble if you make comprehensive changes, such as moving a folder containing many abstract objects, and do not shutdown properly: the physical file data on disk and the WPS records differ then.
This is what &xshutdown; needs the XFldObject class for, which replaces WPObject. Every time an object is awakened, the WPS calls several methods (among them wpInitData and wpObjectReady). XFldObject overrides these and passes the object address in memory to the Worker thread, which will then properly update an &xwp;-internal list of all currently awake objects. As far as I know, there is no other way to find out which objects are currently awake; at least there is no documented API for enumerating them.

Now, when &xshutdown; is initiated and confirmed, it first starts two new threads for the following shutdown procedure, which run parallel to the regular WPS threads: the main "Shutdown thread" with the message queue for the status window, and the "Update thread", which monitors the &os2; Window List and posts messages to the main shutdown thread, if the status window needs to be updated. So closing all currently open windows is a fairly complex process of interaction between these two threads: the Shutdown thread closes a window and then goes to sleep until the Update thread has detected a change in the Window List (which means that the window has successfully been closed) and posts a message back to the Shutdown thread, which then in turn closes the next window, until all windows are closed.

When all windows are closed, the Update thread exits. Now the Shutdown thread goes through the list of currently awake objects (which was described above) and forces saving their data to the INI files or to disk by calling each object's wpSaveImmediate method. This is only done for WPAbstract and WPFolder descendants, because from my experience, all other classes save their data synchroneously. (I have tried saving all WPFileSystem descendants once, and this caused a lot of extended attributes to be created for every single file that was ever awakened by the WPS. In addition, shutdown took ages then.)

Finally, depending on what action was desired, the Shutdown thread does one of the following: