                                    -    1 -






XSpawn
 

XSpawn version 1.0
Copyright (C) by Golan Yaniv 1994



Why do I need XSpawn ?
 

Windows ain't what it used to be... Not so long ago, when you wrote a Windows
application, you knew that people are going to run it using Microsoft Windows 3.1.
Today your application could end up running under one of the various emulation
of windows, ranging from Windows NT, through OS/2 (Win-OS/2), and soon Chicago
and maybe even Unix. And if Bill's dreams come true, you might find one day 
your application running on your washing machine...

Many times Windows applications need to spawn another program to do something.
Maybe you'll need to spawn Notepad to view some text file, or a command line
compiler to compile the code you have worked so hard to generate. And sometime,
you'll want to wait until the spawned application terminates, in order to get
back the results. You'll also want to know what was its exit code to 
determine its success or failure.

Under MS-Windows 3.1, the task was managable. You called WinExec(), installed
a notification callback using ToolHelp, and waited patiently. It wasn't fun,
but it could be done. 

However, under the various Windows emulations, this method stopped working. 
A Windows application running under Win-OS/2 or NT, can spawn not only other
Windows application, but also OS/2 applications, DOS applications and NT
applications. Each one of this runs in a seperate VDM, and usually the
Windows session will not even know that they exist. The instance handle
returned from WinExec() becomes useless.

The XSpawn package offers an alternate way to accomplish the task - to 
spawn an application, wait for it to complete, and retrieve its exit code.
The XSpawn method has been tested under all the emulations I had
access to. It does not require any callbacks.



XSpawn Overview
 

The XSpawn package provides a DLL and several support programs, which enable
Windows application written in any language that can use DLLs to spawn
(execute) other applications, wait for them to terminate and retrieve the
exit code of the spawned application.

The spawned application need not be only another Windows application - it can
be a DOS program, and when running under OS/2 (Win-OS/2) or Windows NT (WOW),



                   xspawn, Page #   1   Date 15-8-1994 Monday
                                    -    2 -





it can be a native OS/2 or Win32 application.

The XSpawn API is simple and does not require the use of callbacks.


Installing XSpawn
 

Please read the accompanying README.1ST file before proceeding.

Before you attempt to use the XSpawn package or the demo programs, you will
need to install its componenets in your system. The installation process 
is rather simple :

- Copy XEXEC.DLL to your Windows System directory (\WINDOWS\SYSTEM).
- Copy the various agents (XA*.EXE) to your Windows directory (usually \WINDOWS)

Once you did that, you can use any of the example programs to verify
that the package is working.


Using the XSpawn API
 

To spawn a program using the XSpawn API, you will need to do the following :

1. Add the appropriate header file, depending on the language you use -
 - #include "xexecd.h" for C\C++
 - USES xexecd for Borland Pascal
 - Add xexecd.bas to your project for Visual Basic

2. In C / C++ you will need to add the supplied XEXEC.LIB to your project.
This step is not required for Borland Pascal or Visual Basic.

3. Call WXSpawn to spawn the program, and check the returned
value for errors.

4. Wait until the program terminates using WXIsDone.

5. Check for errors using lpdwErrorCode.

6. If there wasn't an error, you have the program's exit code in the buffer
pointed to by lpdwExitCode.

Note:
Waiting for the program to terminate can be done in two ways :
- You may either loop until WXIsDone returns TRUE - make sure
to yield control back to Windows inside the loop to allow other applications
to execute.
- Or, you may want to install a timer, and use the WM_TIMER messages to
call WXIsDone. This has a number of advantages - It takes less CPU time, 
Windows has plenty of time to execute other applications, and it makes it
easier to display a 'Please-wait'-type dialog box. This is the method 
used in the sample programs.



                   xspawn, Page #   2   Date 15-8-1994 Monday
                                    -    3 -







How does it work?
 

XSpawn does not use any secret undocumented method that has been
magically discovered to work under all environments. Instead, for each 
supported environment, it uses a tailored solution that fits it best.



The XSpawn Agents
 

A central part of the package are the XSpawn agents (I'm rather proud of the
name). The package is distributed with several agents, each one of them
responsible for handling a certain type of application. The provided DLL
(XEXEC.DLL) and the agents cooperate to spawn the program, wait for it to 
terminate and retrieve its exit code. 

The following agents are provided. Listed next to each agent is the kind
of application it supports. If support for a certain operating system is
not needed, the corresponding agent need not be installed.

XADOS.EXE   - MS-DOS applications.
XAWIN16.EXE - Windows (16-bit) applications, MS-DOS applications.
XAOS2.EXE   - OS/2 applications.
XANT.EXE    - Windows NT applications.


Supported Environments
 

XSpawn has been tested under the following environments :

- Microsoft Windows 3.1
- Microsoft Windows For Workgroups 3.1
- Microsoft Windows NT 3.1
- Microsoft Windows NT 3.5
- OS/2 2.1
- OS/2 2.11


Example Programs
 

The full source to 3 sample programs is distributed with XSpawn. This programs
are contained in the following ZIP files:

POWLDEMO.ZIP - Borland Pascal 7.0 OWL 1.0 sample program
COWLDEMO.ZIP - Borland C++ 4.0 OWL 2.0 sample program
VBDEMO.ZIP - Visual Basic 3.0 sample program. Note that this demo requires
VBRUN300.DLL, which is not supplied due to its size. This file is available
in most of the archives.



                   xspawn, Page #   3   Date 15-8-1994 Monday
                                    -    4 -






Each of the archives contains instructions on how to rebuild the programs, in
the file REBUILD.TXT. You can use these programs to verify that XSpawn is 
installed correctly on your computer and to identify problems.


The XSpawn API
 

To use the XSpawn package, you'll need to call the functions
that reside in XEXEC.DLL. Functions prototype are supplied for Borland Pascal,
C, C++ and Visual Basic. Following is a list of the functions and procedures
exported by XEXEC.DLL :

 WXGetError
 WXGetFileOS
 WXGetHostOS
 WXGetInstance
 WXGetVersion
 WXIsDone
 WXSetDebugMode
 WXSpawn
 WXStopTracking

See Also:

Error codes


WXSpawn
 

Borland Pascal:
function    WXSpawn(lpszFileName : pchar;
                    lpszArgs : pchar;
                    lpszDirectory : pchar;
                    nCmdShow : word;
                    wOptions : word;
                    var hExec : longint) : longint; 

C / C++ :
DWORD WINAPI    WXSpawn(LPCSTR lpszFileName,
                        LPCSTR lpszArgs,
                        LPCSTR lpszDirectory,
                        WORD   nCmdShow,
                        WORD   wOptions,
                        DWORD *hExec);


Visual Basic:
Declare Function WXSpawn Lib "XEXEC" (ByVal lpszFileName$, 
                                      ByVal lpszArgs$, 
                                      ByVal lpszDirectory$, 
                                      ByVal nCmdShow%, 



                   xspawn, Page #   4   Date 15-8-1994 Monday
                                    -    5 -





                                      ByVal wOptions%, 
                                      hExec As Long) As Long

Description
WXSpawn spawns (executes) an application.

Parameters :
lpszFileName 
 The application or batch file to run.

lpszArgs 
 The command line arguments that will be passed to the application.

lpszDirectory
The default directory

nCmdShow
 Whether the application window is to be shown when the application is opened.
This parameter can be one of the SW_XXX constants passed to ShowWindow(). Note 
that not all environments respect all values of this parameter.

wOptions
 A bit-mapped options field. See WXSpawn options for more
information.

hExec
 This is a pointer to a 4-byte (DWORD, longint) buffer that will hold the Exec Handle.
This handle will be used in subsequent calls to other XSpawn functions. If an error
has occoured, the value of this handle will be set to zero.

Returns
The function return a double word. The returned value should be tested for 
errors. See Error Handling.

Comments
WXSpawn will spawn the application specified in the lpszFile field,
passing to it on the command line the arguments pointed to by lpszArgs,
and starting it in the directory specified by lpszDirectory.

Note that lpszFileName can be the name of a PIF file. This option is supported
only under "real" MS-Windows 3.1. Also, the WXO_USESHELL
cannot be used if lpszFileName is a PIF file.

The Visual Basic declaration should appear in one line.


WXSpawn wOptions parameter
 

The following options can be specified in the wOptions paramter of WXSpawn :

WXO_AUTO
WXSpawn will attempt to detect the type of the executable passed in lpszFileName.
Note that this is not possible for batch files (*.BAT, *.CMD, *.BTM). See WXGetFileOS



                   xspawn, Page #   5   Date 15-8-1994 Monday
                                    -    6 -





for more information. Also, if auto-detection is enabled, lpszFileName must be
the fully qualified name of a file.

WXO_WIN
Disables auto-detection, force XSpawn to assume that the executable type is 16-bit Windows.

WXO_DOS
Disables auto-detection, force XSpawn to assume that the executable type is MS-DOS.

WXO_OS2
Disables auto-detection, force XSpawn to assume that the executable type is OS/2.

WXO_NT
Disables auto-detection, force XSpawn to assume that the executable type is Windows NT.

WXO_USESHELL
WXSpawn will pass the application and arguments to the host shell for execution.
        
Notes
The WXO_USESHELL can be combined (ORed) with any of the other flags. Only
one of one the following flags should be used : WXO_AUTO, WX_WIN, WXO_DOS, 
WXO_OS2 and WXO_NT.


Exec Handle - hExec
 

If the call to WXSpawn function was successful, an exec handle is
returned in hExec. This 32-bit value (DWORD, longint) should be saved, since
it is required by the other XSpawn API.

A quick way to check if the call to WXSpawn was successful,
is to check the value in the returned hExec. If it is zero, an error has
occoured, and the function result should be checked to determine the exact
error.

Note that if hExec isn't zero it doesn't mean that all is well. In some cases,
it just means that the agent was executed successfully. See Error Handling
for details.


WXIsDone
 

Borland Pascal:
function WXIsDone(hExec: longint; 
                  lpdwErrorCode : PLongint;
                  lpdwExitCode : PLongint) : Bool; 

C / C++ :
BOOL  WINAPI    WXIsDone(DWORD hExec,
                         DWORD *lpdwErrorCode,
                         DWORD *lpdwExitCode);




                   xspawn, Page #   6   Date 15-8-1994 Monday
                                    -    7 -





Visual Basic:
Declare Function WXIsDone Lib "XEXEC" (ByVal hExec As Long, 
                                       lpdwErrorCode As Long, 
                                       lpdwExitCode As Long) As Integer


Description
WXIsDone checks if the application identified by hExec has terminated,
and if it has, what was its exit code. It also provides a way to check for
errors on the agent's side.

Parameters :
hExec 
The handle returned in the hExec field by the WXSpawn function
that spawned the application. 

lpdwErrorCode 
A pointer to a 4-bytes buffer (DWORD, longint) that will hold the error code
returned by the agent. Valid only when the functions returns TRUE.

lpdwExitCode
A pointer to a 4-bytes buffer (DWORD, longint) that will hold the application
exit code. Valid only when the functions returns TRUE.

Returns
The functions returns TRUE if the application has terminated, FALSE othewise.

Comments
This function should be used to determine the state the spawned application
is in. As long as WXIsDone returns FALSE, the application is assumed to be
still executing, and the lpdwErrorCode and lpdwExitCode fields do not contain
valid values.

When the functions returns TRUE, one of the following holds :

- The application has completed, lpdwErrorCode contains 0, and lpdwExitCode
contains its exit code.

- If lpdwErrorCode is not 0, there was an error. In that case, lpdwErrorCode contains
the error code - one of the WX_XXXX constants. lpdwExitCode 
might contain additional information about the error.

In any case, once the function returns TRUE, the hExec handle is not valid
anymore.

If using WXIsDone inside a tight loop, make sure you yield control back to
windows inside the loop (using PeekMessage for example), otherwise other
Windows application (including the application you spawned) will never get
a chance to run.

To prevent such problems, you may want to install a timer, and check WXIsDone
in response to the WM_TIMER messages.

In Visual Basic the declaration should appear in one line. Also, note that



                   xspawn, Page #   7   Date 15-8-1994 Monday
                                    -    8 -





the constant TRUE defined in Visual Basic differs from the one defined in
Borland Pascal and C. Therefore, in Visual Basic, test if the function 
result is not equal to zero.

See Also
WXStopTracking
Error Handling


WXStopTracking
 

Borland Pascal:
procedure WXStopTracking(hExec: longint); 

C / C++ :
VOID  WINAPI    WXStopTracking(DWORD hExec);

Visual Basic:
Declare Sub WXStopTracking Lib "XEXEC" (ByVal hExec As Long)

Description
WXStopTracking instructs XEXEC.DLL to stop tracking the application
identified by the hExec handle. Note that this will not terminate the application,
since it is not safe to do that. It will just free the resources assigned to
tracking it.

Parameters :
hExec 
The handle returned in the hExec field by the WXSpawn function
that spawned the application. 

Comments
This function can be used when the user requests to cancel the execution.
It is advised to provide the user with a way to do that, such as 'Please Wait'-type
dialog box with a 'Cancel' button.

Once WXStopTracking is called, the hExec handle becomes invalid and 
should not be used.


WXSetDebugMode
 

Borland Pascal:
procedure WXSetDebugMode(bDebugFlag : Bool); 

C / C++ :
VOID  WINAPI    WXSetDebugMode(BOOL bDebugFlag);

Visual Basic:
Declare Sub WXSetDebugMode Lib "XEXEC" (ByVal bDebugFlag As Integer)

Description



                   xspawn, Page #   8   Date 15-8-1994 Monday
                                    -    9 -





WXSetDebugMode enables / disables debug mode.

When in debug mode, the XSpawn agents display verbose informational
messages. 

Parameters :
bDebugMode
The new mode - TRUE for debug mode, FALSE for regular mode.

Comments
Note that the effect of WXSetDebugMode is global to all applications
that use the package in this session. Therefore, use this flag only in the
development phase.

After displaying the debugging messages the agents pause and wait for a key
to be pressed or for the dialog box to be closed.


WXGetVersion
 

Borland Pascal:
function  WXGetVersion : word; 

C / C++ :
WORD WINAPI    WXGetVersion;

Visual Basic:
Declare Function WXGetVersion Lib "XEXEC" () As Integer

Description
Returns the version number of the XSpawn package.

Returns
The high byte contains the major version number, and low byte contains the
minor version number.

Comments
This function can be used to force XEXEC.DLL to load.


WXGetInstance
 

Borland Pascal:
function  WXGetInstance(hExec : longint) : THandle; 

C / C++ :
HINSTANCE WINAPI WXGetInstance(DWORD hExec);

Visual Basic:
Declare Function WXGetInstance Lib "XEXEC" (ByVal hExec As Long) As Integer

Description



                   xspawn, Page #   9   Date 15-8-1994 Monday
                                    -   10 -





Retrieves the instance handle of the application associated with hExec.

Parameters :
hExec
The handle returned in hExec when the application was spawned.

Returns
The instance handle of the application identified by hExec, as reported
by WinExec(). 

Comments
The instance handle is of use only when running under "real" windows, or
when the spawned application is a Windows application. Under the various
emulated Windows sessions using it may cause a GPF.


WXGetFileOS
 


Borland Pascal:
function    WXGetFileOS(lpszFileName : pchar) : word;

C / C++ :
WORD  WINAPI    WXGetFileOS(LPCSTR lpszFileName);

Visual Basic:
Declare Function WXGetFileOS Lib "XEXEC" (ByVal lpszFileName$) As Integer

Description
Attempts to determine the operating system for which the file was written.

Parameters :
lpszFileName
The full path to the executable file.

Returns
WXGetFileOS returns 0 if it was unable to the detect the operation system
type, or one of the following values (which are the same as those specified
under WXSpawn options) :

WXO_WIN - If the file is a MS-Windows (16-bit) application 
WXO_DOS - If the file is a MS-DOS application
WXO_OS2 - If the file is a OS/2 application
WXO_NT  - If the file is a Windows NT application.

Comments
For batch files (*.BAT, *.CMD, *.BTM) WXGetFileOS always returns 0, since
its not possible to detect what operating system they were written for.

COM files are assumed to be DOS files.

Executables produced by the Borland's 16-bit DOS extender which is distributed
with Borland Pascal 7.0 are marked as OS/2 version 0.0 programs. Therefore



                   xspawn, Page #  10   Date 15-8-1994 Monday
                                    -   11 -





they cannot be correctly identified by WXGetFileOS.


WXGetError
 

Borland Pascal:
procedure   WXGetError(dwErrorCode : longint; 
                       var wError : word; 
                       var wReason : word); 

C / C++ :
VOID  WINAPI    WXGetError(DWORD dwErrorCode,
                           WORD *wError,
                           WORD *eReason);

Visual Basic:
Declare Sub WXGetError Lib "XEXEC" (ByVal dwErrorCode as Long,
                                    wError as Integer, 
                                    wReason as Integer)

Description
Retrieves the error and reason from the error code returned by WXSpawn
and WXIsDone.

Parameters :
dwErrorCode
The error code as returned from the above functions.

wError
A word-sized (2 bytes, integer) buffer that will recieve the low word of 
dwErrorCode.

wReason
A word-sized (2 bytes, integer) buffer that will recieve the high word of 
dwErrorCode.

Comments
WXGetError simply extracts the high and low words from the double word value
passed to it. It was designed with Visual Basic in mind, but is useful in
C and Pascal too.


WXGetHostOS
 

Borland Pascal:
function    WXGetHostOS : longint; 

C / C++ :
DWORD WINAPI    WXGetHostOS();

Visual Basic:
Declare Sub WXGetHostOS Lib "XEXEC" ()



                   xspawn, Page #  11   Date 15-8-1994 Monday
                                    -   12 -






Description
Detects the Operating System that is emulating the current Windows session.

Parameters : None.

Returns
WXGetHostOS returns one of the following values :


WX_OS_WIN3X   - Running under MS-Windows 3.X (16-bit)
WX_OS_WINNT   - Running under Windows NT
WX_OS_WINOS2  - Running under a Win-OS/2 session
WX_OS_UNKNOWN - Unknown host operating system


Error Handling
 

Since the XSpawn package is divided into two parts (DLL and Agents), the error
checking has to be performed in two different phases. Errors can be reported
either by WXSpawn or by WXIsDone.

Use the following code samples as a basis for error handling code :

Pascal Example
C Example
Visual Basic Example



Error Codes
 

Error codes are returned by two functions : WXSpawn and WXIsDone.
WXSpawn returns an error code as the function return value, and WXIsDone returns
the error code in the lpdwErrorCode parameter. Both of this double-word values 
should be interpreted as follows :

The low word of the value contains the error code. The error codes are
listed below. For some error codes, the high word contains additional
information about the cause of the error.

WX_APPEXEC
XSpawn could not execute the application specified in lpszFileName.
The high word contains either one of the WinExec errors as documented under
WinExec in the SDK, or one of the following error codes:

    WX_NOTFOUND    - Path or file not found
    WX_NOMEM       - Not enough memory
    WX_ARGLIST     - Arguments list too long
    WX_BADFORMAT   - Bad exec format
    WX_UNKNOWN     - Unknown error




                   xspawn, Page #  12   Date 15-8-1994 Monday
                                    -   13 -





WX_AGENTEXEC
XSpawn could not execute the agent needed for the file type. The high word
contains the WinExec error code.

WX_OUTOFMEM
XSpawn did not have enough memory to complete the operation.

WX_AGENTCOMM
XSpawn failed to establish communication with the agent.

WX_NOAGENT
XSpawn could not find the agent needed for the file type. See XSpawn Agents
for more information. The high word contains the expected agent type as would have
been returned by WXGetFileOS.

WX_UNKNOWNOS
XSpawn could not determine the operating system for which the executable specified
by lpszFileName was written. This can also happen if lpszFileName specifies a
batch file. See also WXGetFileOS.

WX_BADVER
The agent expected a different version of the DLL (XEXEC.DLL). The expected version
is in the high word.

WX_AGENTKILLED
The agent was killed while waiting for the spawned application to terminate.

WX_INVALIDHEXEC
The hExec Exec Handle is invalid.


Handling Errors - Pascal Example
 

var
  dwErrorCode : longint;
  hExec : longint;
  dwExitCode : longint;
  pszMsg : pchar;
  szOkMsg : array[0..255] of char;
begin
  { Spawn notepad, ask it to edit c:\autoexec.bat : }
  dwErrorCode := WXSpawn('NOTEPAD.EXE',
                         'C:\AUTOEXEC.BAT',
                         NIL,
                         SW_SHOWNORMAL,
                         WXO_WIN,
                         hExec);
 
  { Wait for notepad to terminate. It is very important to yield }
  { control back to Windows inside the loop! }
  if (dwErrorCode = 0) then
  begin
    while (not WXIsDone(hExec, @dwErrorCode, @dwExitCode)) do



                   xspawn, Page #  13   Date 15-8-1994 Monday
                                    -   14 -





    begin
      { yield here to windows!!! }
    end;
  end;
 
  if (dwErrorCode = 0) then
  begin
    { Success! Display exit code : }
    wvsprintf(szOkMsg, 'Notepad exit code : %ld', dwExitCode);
    MessageBox(0, szOkMsg, 'Success', MB_OK or MB_ICONINFORMATION);
  end else
  begin
    { dwErrorCode <> 0 indicates error : }
    case LOWORD(dwErrorCode) of
      WX_APPEXEC      : pszMsg := 'Failed to execute application';
      WX_AGENTEXEC    : pszMsg := 'Failed to execute agent';
      WX_OUTOFMEM     : pszMsg := 'Not enough memory to complete operation';
      WX_AGENTCOMM    : pszMsg := 'Unable to establish communication with agent';
      WX_NOAGENT      : pszMsg := 'Agent not installed';
      WX_UNKNOWNOS    : pszMsg := 'Unable to determine executable OS';
      WX_BADVER       : pszMsg := 'Agent version mismatch';
      WX_AGENTKILLED  : pszMsg := 'Agent was killed while waiting';
      WX_INVALIDHEXEC : pszMsg := 'Invalid exec handle';
    end; { case }
    MessageBox(0, pszMsg, 'Error', MB_OK or MB_ICONSTOP);
  end; { if }
end.


Handling Errors - C Example
 

  DWORD dwErrorCode;
  DWORD hExec;
  DWORD dwExitCode;
  LPSTR pszMsg;
  char  szOkMsg[255];
 
  // Spawn notepad, ask it to edit c:\autoexec.bat : 
  dwErrorCode = WXSpawn("NOTEPAD.EXE",
                        "C:\\AUTOEXEC.BAT",
                        NULL,
                        SW_SHOWNORMAL,
                        WXO_WIN,
                        &hExec);
 
  // Wait for notepad to terminate. It is very important to yield 
  // control back to Windows inside the loop! 
  if (dwErrorCode == 0) then
  {
    while (!WXIsDone(hExec, &dwErrorCode, &dwExitCode))
    {
      // yield here to windows!!! 
    }



                   xspawn, Page #  14   Date 15-8-1994 Monday
                                    -   15 -





  }
 
  if (dwErrorCode == 0)
  {
    // Success! Display exit code : 
    wvsprintf(szOkMsg, "Notepad exit code : %ld", dwExitCode);
    MessageBox(0, szOkMsg, "Success", MB_OK || MB_ICONINFORMATION);
  } else
  {
    // dwErrorCode != 0 indicates error : 
    switch LOWORD(dwErrorCode)
      case WX_APPEXEC      : pszMsg = "Failed to execute application";
                             break;
      case WX_AGENTEXEC    : pszMsg = "Failed to execute agent";
                             break;
      case WX_OUTOFMEM     : pszMsg = "Not enough memory to complete operation";
                             break;
      case WX_AGENTCOMM    : pszMsg = "Unable to establish communication with agent";
                             break;
      case WX_NOAGENT      : pszMsg = "Agent not installed";
                             break;
      case WX_UNKNOWNOS    : pszMsg = "Unable to determine executable OS";
                             break;
      case WX_BADVER       : pszMsg = "Agent version mismatch";
                             break;
      case WX_AGENTKILLED  : pszMsg = "Agent was killed while waiting";
                             break;
      case WX_INVALIDHEXEC : pszMsg = "Invalid exec handle";
                             break;
    } // switch 
    MessageBox(0, pszMsg, "Error", MB_OK or MB_ICONSTOP);
  } // if 


Handling Errors - Visual Basic Example
 

    Dim dwErrorCode As Long
    Dim wError As Integer
    Dim wReason As Integer
    Dim hExec As Long
    Dim dwExitCode As Long
    Dim strMsg As String
    Dim strOkMsg As String

    ' Spawn notepad, ask it to edit c:\autoexec.bat :
    dwErrorCode = WXSpawn("NOTEPAD.EXE", "C:\AUTOEXEC.BAT", 0, SW_SHOWNORMAL, WXO_WIN, hExec)

    ' Wait for notepad to terminate. It is very important to yield
    ' control back to Windows inside the loop!
    If (dwErrorCode = 0) Then
        While (WXIsDone(hExec, dwErrorCode, dwExitCode) = 0)
            ' yield here to windows!!!
        Wend



                   xspawn, Page #  15   Date 15-8-1994 Monday
                                    -   16 -





    End If

    If (dwErrorCode = 0) Then
        ' Success! Display exit code :
        strOkMsg = "Notepad exit code : " & dwExitCode
        MsgBox strOkMsg
    Else
        ' dwErrorCode <> 0 indicates error :
        WXGetError (dwErrorCode, wError, wReason)
        Select Case wError
            Case WX_APPEXEC
                strMsg = "Failed to execute application"
            Case WX_AGENTEXEC
                strMsg = "Failed to execute agent"
            Case WX_OUTOFMEM
                strMsg = "Not enough memory to complete operation"
            Case WX_AGENTCOMM
                strMsg = "Unable to establish communication with agent"
            Case WX_NOAGENT
                strMsg = "Agent not installed"
            Case WX_UNKNOWNOS
                strMsg = "Unable to determine executable OS"
            Case WX_BADVER
                strMsg = "Agent version mismatch"
            Case WX_AGENTKILLE
                strMsg = "Agent was killed while waiting"
            Case WX_INVALIDHEX
                strMsg = "Invalid exec handle"
        End Select
        MsgBox strMsg
    End If


Registration
 

The XSpawn package is not free. It is distributed as shareware. The shareware
version is not crippled in any way. The only difference between the shareware
and the registered version is that in the registered version the agents
do not display anything on the screen, not even a copyright message.

XSpawn can be evaluated for a trial period of 30 days. After that period,
if you wish to continue using XSpawn, you must register it, otherwise, you
must discontinue to use XSpawn.

To register XSpawn, print out the Registration Form supplied with XSpawn
in the file REGISTER.FRM, fill it out, and 
send it along with the full registration fee to the following address :

Golan Yaniv
Hageula 4
Hod Hasharon 45272
ISRAEL




                   xspawn, Page #  16   Date 15-8-1994 Monday
                                    -   17 -





I will send you the latest copy of the registered version of XSpawn.
For an additional fee you will also recieve the full sources to the
package. A registered user is entitled to product support via the Internet
(ie. E-mail). Registered users may distribute the Distributable
parts of the XSpawn package with their applications.

You are encouraged to pass along the UNREGISTERED shareware version of XSpawn,
as long as the archive full contents are preserved.

XSpawn may not be :

1. Modified
2. Distributed in a modified form
3. Distributed in a registered state
4. Distributed in connection with any other software, without written permission
from the author.

The standard disclaimer follows :

THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD  
TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  
OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL  
THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR  
CONSEQUENTIAL DAMAGES OR ANY DAMAGES  
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR  
PROFITS, WHETHER IN AN ACTION OF CONTRACT,  
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT  
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE  
OF THIS SOFTWARE.

If you do not agree with above terms and conditions you do not have permission
to use XSpawn, you must stop using it and remove it from your computer. 

Suggestions, comments and bug reports can be forwarded to the above address,
or send E-mail to :

s2942275@techst02.technion.ac.il


Redistributables
 

If you have purchased the registered version of XSpawn,
you can distribute the following files along with applications that use XSpawn :

- XEXEC.DLL
- XAWIN16.EXE
- XADOS.EXE
- XANT.EXE
- XAOS2.EXE

No other file from the registered version may be distributed.





                   xspawn, Page #  17   Date 15-8-1994 Monday
                                    -   18 -





Credits and Trademarks
 

Lucien Cinc has provided me with suggestions, solutions and code samples.
He also helped with testing. His WinOne product (A Windows command line shell) 
has been a valuable tool in the debugging phase.

UnixCorn, by Randall Spangler, has also been very usefull during development.

This documentation was created using Ron Loewy's Help Development Kit (HLPDK)
version 11.0.

Davidov Eran has read the documentation and provided me with many corrections
and suggestions.

The following compilers were used to create the package:

- Borland Pascal 7.0
- Borland C++ 4.0
- Borland C++ for OS/2 1.0
- Microsoft Visual C++ 32-bit 1.1

Borland Pascal, Borland C++ are trademarks of Borland International.

Windows, Windows NT, MS-DOS, Chicago are trademarks of Microsoft Corp.

OS/2, Win-OS/2 are trademarks of IBM.






























                   xspawn, Page #  18   Date 15-8-1994 Monday
