Name:      xTask.dll
Purpose:   Monitoring termination of other tasks;
           Mapping between hTask and hInstance.
Version:   1.0
Date:      15 Nov 92
Requires:  Windows 3.1
Author:    Pieter Stam (CompuServe 100065,603),  Pontis Consulting (U.K.)
Ownership: Public.  Free usage & redistribution.
           *** USE THIS LIBRARY AT YOUR OWN RISK *** 
           Be sure to test thoroughly in your environment. 
           No warrantees extended, no support promised.
           Please report any problems back to the author.


Introduction
------------

This DLL will allow you to detect the termination of any EXE. 
You pass a window handle of the calling application along with 
the task handle of another running application, and a number of 
your own choice.  The function returns immediately.  When the 
application exits, the window specified receives a WM_KEYDOWN 
message with as argument the number of your choice plus the 
exit code of the terminated application (e.g. of a DOS 
application in a DOS box).  
One application can monitor several applications.  
One application can be monitored by several applications.

In VB, you could have started an application with 'Shell'.  
'Shell' returns an instance handle, that you can map to a task 
handle with this library.  You start monitoring by calling this 
library, passing the task handle, a Form's hWnd, and a number of 
your choice.  When the monitored application exits, the 
Form_KeyDown event happens for the form of which the hWnd was 
passed.  The argument 'KeyCode' equals your number plus exit 
code.  Your code in the Form_KeyDown subroutine of your 
application can then do its business.

NOTE:  This ONLY will work with Windows 3.1 and later.  
Various functions (i.a. NotifyRegister) of ToolHelp.DLL 
of 3.1 are used.


Interface definition
--------------------

* Visual Basic:

Declare Function SetTaskExitWatch Lib "xTask.dll" (ByVal hTaskToWatch As Integer, ByVal hWndRecipient As Integer, ByVal kCode As Integer) As Integer
Declare Function CancelTaskExitWatches Lib "xTask.dll" (ByVal hWndRecipient As Integer) As Integer
Declare Function hTaskFromhInstance Lib "xTask.dll" (ByVal hInstance As Integer) As Integer
Declare Function hInstanceFromhTask Lib "xTask.dll" (ByVal hTask As Integer) As Integer

* C:

#include <Windows.h>
BOOL      WINAPI SetTaskExitWatch( HTASK ToWatch, HWND Recipient, WPARAM kCode );
UINT      WINAPI CancelTaskExitWatches( HWND );
HTASK     WINAPI hTaskFromhInstance( HINSTANCE );
HINSTANCE WINAPI hInstanceFromhTask( HTASK );

* Semantics:

SetTaskExitWatch returns 0 on failure, e.g. when the task does not exist,
or when internal resources are exhausted (there can be 16 'TaskExitWatches',
but Windows 3.1 seems to support only 12 RegisterNotify callback settings).
Upon success it returns hex FFFF (-1, as traditional in VB for booleans).
When the monitored task exits, the recipient window receives a WM_KEYDOWN event
with LPARAM 0 and WPARAM equal to kCode + exit code of terminating app (0-255).
In VB this means a KeyDown event for the Form whose hWnd was specified;
the KeyCode argument is kCode of SetExitTaskWatch plus exit code.
It seems safest & easiest to use kCode values 256, 512, ...
Warning:
If the receiving VB application happens to display a MsgBox when a monitored
application exits, the Form_KeyDown event does not happen;
this is an officially recognized VB "feature".
(Things work fine when another form is being shown, modal or modeless.)

CancelTaskExitWatches is a cleanup routine that one 'should' use before
destroying the window, if there may still be monitored applications alive.
In VB one could call it in Form_Unload.  Failure to do so may lead to
misinterpreted messages to windows created later with a recycled handle.
The function returns the number of TaskExitWatches that have been cancelled.

hTaskFromhInstance returns the Task handle belonging to the argument Instance
handle.  (Note that VB's Shell, like Window's WinExec, returns an Instance
handle.)  If the argument is 0, it returns the Task handle of the caller.
On errors (typically: hInstance not found in system) it returns 0.

hInstanceFromhTask returns the Instance handle belonging to the argument Task
handle.  If the argument is 0, it returns the Instance handle of the caller.
On errors (typically: hTask not found in system) it returns 0.

