[comp.windows.ms] Spawning Windows Applications

roberth@microsoft.UUCP (Robert Hess) (09/20/89)

Ok, there has been enough posting back and forth about how to spawn a
Windows application, and enough mis-information being stated that I
decided I'd better 'bring out the horse' so you could get it straight
from the source.

Following this message will be the code that the Windows Development
Support Team provides its customers on how to spawn applications in
Windows. If you have an OnLine account, an archive of this information
(includeing .OBJs and the .EXE) is available under the title of
WINSPAWN.ARC in the software library.

!!DO NOT EVER USE ANY OF THE 'spawn' FUNCTIONS FROM THE C RUNTIME LIBRARY!!

They do not properly spawn Windows applications, and your applications
will eventually fail under the right conditions. Just because they
'happen' to work on your machine, doesn't mean they will always work.
Under interesting memory conditions, things can get strange.

Even using the following code, there is at least one situation that I
know of that will cause problems. That is:

  Execute your program, have it spawn Excel, then quit your program,
  then quit Excel.

There are conditions that will cause this to crash Windows. The reason
being, that Excel (and some other non-MS applications) took for granted
that they were being spawned by the MS-DOS Executive, which was
'guaranteed' to be around longer then they were, and they were making
use of the spawners stack to maintain some special data. If that stack
disappears, then problems arise.

Even though this application demonstrates it, I would not recommend
allowing users of your program to spawn *any* application. (If you are
shipping your program as a 'Stand-Alone' application, this would
invalidate your licenceing agreement with Microsoft). Only spawn your
own applications, or specific others (such as the ones that ship with
Windows).

- Robert

 __________________________________________________________________________
     #####   ####### |	  Robert B. Hess, Microsoft Corp., Redmond, WA
    ######  #######  |-----------------------------------------------------
   ####### #######   |	roberth@microsof.uu.net
  #### ##### ####    |	{decvax, uunet, uw-beaver}!microsof!roberth
 ####  ###  ####     |_____________________________________________________
   "...my opinions are strictly my own, and not those of my employer..."



[Disclaimer: The following code is provided as-is. It does not represent
any guarantee on the part of Microsoft or any other person or company to
be error-free. Microsoft takes no responsibility regarding its usage in
an application, and it is presented mearly as an example. This code may
not be re-distibuted in any manner that provides profit or
advertisement. It may not be shipped with any application, either as
source code, or executable]


//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// WinSpawn.MAK
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

WinSpawn.obj : WinSpawn.c
     cl -c -D LINT_ARGS -Gsw -Os -W2 -Zp WinSpawn.c

WinSpawn.res : WinSpawn.rc WinSpawn.h
     rc -r WinSpawn.rc

wspawn.obj   : wspawn.asm
     masm wspawn;

WinSpawn.exe : WinSpawn.obj WinSpawn.def WinSpawn.res wspawn.obj
     link4 WinSpawn wspawn, /align:16, /map, slibw, WinSpawn
    mapsym WinSpawn
    rc WinSpawn.res

WinSpawn.exe : WinSpawn.res
    rc WinSpawn.res


//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// WinSpawn.DEF
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

NAME           WINSPAWN
DESCRIPTION    'Andrew Krois June 1988'
STUB           'WINSTUB.EXE'
CODE           MOVEABLE
DATA           MOVEABLE MULTIPLE
SEGMENTS
    ASMCODE   CLASS'ASMCODE'  FIXED LOADONCALL READWRITE
HEAPSIZE       1024
STACKSIZE      4096
EXPORTS        WndProc
               SpawnDlgBoxProc      @2
               NewSpawnDlgBoxProc   @3



//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// WinSpawn.RC
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

#include <windows.h>
#include  "WinSpawn.h"


WinSpawn MENU
    BEGIN
        POPUP "&Choose Application"
            BEGIN
                MENUITEM "&MS-DOS dir | sort",              IDM_DOSDIRSORT
                MENUITEM "MS-DOS &type winspawn.c",         IDM_DOSTYPE
                MENUITEM "&Windows Clock",                  IDM_CLOCK
                MENUITEM "&Notepad winspawn.c",             IDM_NOTEPAD
                MENUITEM "&Spawn All",                      IDM_SPAWNALL
            END					            
        MENUITEM "\a&Help"                                  IDM_HELP  HELP
    END

SpawnDlgBox DIALOG LOADONCALL MOVEABLE DISCARDABLE 13, 14, 104, 72
STYLE WS_DLGFRAME | WS_POPUP
BEGIN
     LTEXT "App Name      Extension", -1,     2,  4,100, 10
     EDITTEXT             IDD_DLGSPAWNAPPNAME,2, 14, 50, 12, ES_AUTOHSCROLL
     EDITTEXT             IDD_DLGEXTENSION,  55, 14, 25, 12, ES_AUTOHSCROLL 
     LTEXT "Command Line",           -1,      2, 30, 75, 10
     EDITTEXT             IDD_DLGCOMMANDLINE, 2, 42,100, 12, ES_AUTOHSCROLL
     DEFPUSHBUTTON "&OK", IDOK,              27, 56, 50, 14, WS_GROUP
END



//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// WinSpawn.H
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

#define IDM_ABOUT            45
#define IDM_CHOOSERANDOM     46
#define IDM_HELP             47
#define IDM_CHOOSE           48
#define IDM_CLOCK            49
#define IDM_DOSDIRSORT       50
#define IDM_SPAWNIT          51
#define IDM_NOTEPAD          52
#define IDM_DOSTYPE          53
#define IDM_SPAWNALL         54
#define IDD_DLGSPAWNAPPNAME  55
#define IDD_DLGCOMMANDLINE   56
#define IDD_DLGEXTENSION     57


long FAR PASCAL WndProc                (HWND, unsigned, WORD, LONG) ;
BOOL FAR PASCAL SpawnDlgBoxProc      (HWND, unsigned, WORD, LONG) ;
BOOL FAR PASCAL NewSpawnDlgBoxProc   (HWND, unsigned, WORD, LONG);
HWND            FindNextWindow         (HWND) ;
BOOL            FindPeriod             (char *);
extern int far pascal Int21Function4B  (BYTE, LPSTR, LPSTR);


//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// WSpawn.ASM
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------


include cmacros.inc

externFP   <GlobalCompact>

createSeg   ASMCODE,ASMCODE,PARA,PUBLIC,ASMCODE

;;
;;  Int21Function4B cannot be a discardable segment.  If the segment
;;  were discardable, the int21 interrupt might cause it to be discarded
;;  and then reread from disk.  This would set stackSS and stackSP to 0.
;;  Upon return from int21, SS would be set to 0 and SP would be set to
;;  0.
;;
;;  Warning:  the code is not reentrant.  Multiple sp's cannot be saved.
;;  Warning:  In applications SS == DS by default.  If the DS should move
;;  the stored SS would be invalidated.  For maximum reliability it is
;;  recommended that LockData(), UnlockData() call bracket the call to
;;  int21function4B.
;;  Warning:  Should the code segment move using the debugging KERNEL,
;;  the segment will be checksummed and the write of SS:SP into the
;;  code segment detected as a fatal error.  To avoid this extraneous
;;  ( in this one instance ) error condition,
;;  use the non-debugging kernel or place the code in a fixed segment.
;;

assumes CS,ASMCODE
assumes DS,DATA


sBegin DATA
sEnd   DATA

sBegin ASMCODE
	stackSS dw 0
	stackSP dw 0

cProc   Int21Function4B,<PUBLIC,FAR>,<ax,bx,cx,dx,si,di,es,ds>
	parmB mode
	parmD path
	parmD execblock
cBegin
      mov ax,-1
      cCall GlobalCompact,<ax,ax>
	mov cs:[stackSS],ss         ;; EXEC destroys all register. Save SS:SP.
	mov cs:[stackSP],sp
	mov al,mode
	lds dx,path
	les bx,execblock
	mov ah,4bh
	int 21h
	mov ss,cs:[stackSS]
	mov sp,cs:[stackSP]
; AX is return value
cEnd

sEnd ASMCODE
END





//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// WinSpawn.C
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

/*

Date:  June 15, 1988

Function(s) demonstrated in this program: Int21Function4B

Windows version:  2.03

Windows SDK version:  2.00

Compiler version:  C 5.10

Description:  This is a Function created using Masm, and it corresponds
   with the MS-DOS interrupt 21 function 4BH.

Additional Comments:  This function can be used to spawn windows
   applications, as well as old MS-DOS applications from within a 
   windows application.  A method of sending command line arguments
   to the spawnded windows application is also discussed.

*/

#define NOMINMAX
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "WinSpawn.h"

HWND     hWndMain;
HANDLE   hInstMain;
char     szOutputBuffer1 [70];
char     szOutputBuffer2 [500];
char     szSpawnAppName  [40];
char     szCommandLine   [40];
HWND     hSpawnAppEdit, hExtensionEdit, hCommandLineEdit, hOK2;
FARPROC  lpProcSpawnDlgBox;
FARPROC  lpProcNewSpawnDlgBox;
FARPROC  lpProcOldSpawnApp;
FARPROC  lpProcOldExtension;
FARPROC  lpProcOldCommandLine;
char     szDlgSpawnAppName [40];
char     szDlgCommandLine [40];
char     szDlgExtension [4] = "EXE";

typedef struct {
         WORD   environment;
         LPSTR  commandline;
         LPSTR  FCB1;
         LPSTR  FCB2;
        } EXECBLOCK;
EXECBLOCK      exec;
WORD           wFCB1Contents[2];


/****************************************************************************/
/************************    Message Structure      *************************/
/****************************************************************************/

struct { char *szMessage; }
       Messages [] = {
"About",
"     This is a sample application to demonstrate the\n\
use  of  Interrupt 21 function 4B in spawning Windows\n\
applications, and MS-DOS applications from a Windows\n\
Windows application.  Program by Andrew Krois",

"Help Message",
"     This program demonstrates the use of the\n\
Int21Function4B function.  Use the menu to select\n\
either a MS-DOS application or a Windows application\n\
to be spawned.  The program will also send command\n\
line arguments to the spawned application.",

};	

/****************************************************************************/

void ProcessMessage (HWND, int); 

void ProcessMessage (hWnd, MessageNumber) 
     HWND     hWnd;
     int      MessageNumber;
{
     sprintf (szOutputBuffer1, "%s", Messages [MessageNumber]);
     sprintf (szOutputBuffer2, "%s", Messages [MessageNumber + 1]);
     MessageBox (hWnd, szOutputBuffer2, szOutputBuffer1, MB_OK);
}       

/****************************************************************************/

int PASCAL WinMain (hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
     HANDLE      hInstance, hPrevInstance ;
     LPSTR       lpszCmdLine ;
     int         nCmdShow ;
     {
     static char szAppName [] = "WinSpawn" ;
     static char szChildClass [] = "WinSpawnChild" ;
     HWND        hWnd ;
     WNDCLASS    wndclass ;
     MSG msg;

     if (!hPrevInstance) 
          {
          wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
          wndclass.lpfnWndProc   = WndProc ;
          wndclass.cbClsExtra    = 0 ;
          wndclass.cbWndExtra    = 0 ;
          wndclass.hInstance     = hInstance ;
          wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
          wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
          wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
          wndclass.lpszMenuName  = szAppName ;
          wndclass.lpszClassName = szAppName ;

          if (!RegisterClass (&wndclass))
               return FALSE ;

          }

     hWnd = CreateWindow (szAppName,            /* window class name       */
                    "Windows Spawn",            /* window caption          */
                    WS_OVERLAPPEDWINDOW,        /* window style            */
                    CW_USEDEFAULT,              /* initial x position      */
                    0,                          /* initial y position      */
                    CW_USEDEFAULT,              /* initial x size          */
                    0,                          /* initial y size          */
                    NULL,                       /* parent window handle    */
                    NULL,                       /* window menu handle      */
                    hInstance,                  /* program instance handle */
                    NULL) ;                     /* create parameters       */

     ShowWindow (hWnd, nCmdShow) ;
     UpdateWindow (hWnd) ;

     hWndMain  = hWnd;
     hInstMain = hInstance;

     lpProcSpawnDlgBox    = MakeProcInstance (SpawnDlgBoxProc, hInstance);
     lpProcNewSpawnDlgBox = MakeProcInstance (NewSpawnDlgBoxProc,hInstance);

     while (GetMessage(&msg, NULL, 0, 0))
     {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
     } 
     return (msg.wParam) ;     
     }

/****************************************************************************/

long FAR PASCAL WndProc (hWnd, iMessage, wParam, lParam)
HWND     hWnd ;
unsigned iMessage ;
WORD     wParam ;
LONG     lParam ;
{
 HMENU       hMenu;
 PAINTSTRUCT ps;

 switch(iMessage)
 {
  case WM_CREATE:
       hMenu = GetSystemMenu (hWnd, FALSE);

       ChangeMenu (hMenu, NULL, "&About", IDM_ABOUT, 
                   MF_APPEND | MF_STRING);
       break;

  case WM_SYSCOMMAND:
       switch (wParam) {
          case IDM_ABOUT:
               ProcessMessage (hWnd, 0);
               break;
          default:
               return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
       }
       break;

  case WM_COMMAND:
       switch (wParam) {

          case IDM_SPAWNIT:
               hMenu = GetSystemMenu (hWnd, NULL);
               ChangeMenu (hMenu, SC_CLOSE, "&Close", SC_CLOSE, 
                           MF_CHANGE | MF_DISABLED | MF_GRAYED);

               GlobalCompact(-1L);
               LockData(0);

               exec.environment = 0;
               exec.commandline = szCommandLine;

               wFCB1Contents[0] = 2;
               wFCB1Contents[1] = SW_SHOWNORMAL;
               exec.FCB1 = (LPSTR)wFCB1Contents;
               exec.FCB2 = (LPSTR)NULL;

               Int21Function4B(0, (LPSTR)szSpawnAppName,
                               (LPSTR)&exec);

               UnlockData(0);
               break;

          case IDM_CLOCK:
               sprintf (szSpawnAppName,"CLOCK.EXE");
               sprintf (szCommandLine, "");
               SendMessage (hWnd, WM_COMMAND, IDM_SPAWNIT, 0L);
               break;

          case IDM_DOSDIRSORT:			
               sprintf (szSpawnAppName,"COMMAND.COM");
               sprintf (szCommandLine, "%c /c dir | sort", 14);
               SendMessage (hWnd, WM_COMMAND, IDM_SPAWNIT, 0L);
               break;

          case IDM_DOSTYPE:			
               sprintf (szSpawnAppName,"COMMAND.COM");
               sprintf (szCommandLine, "%c /c type winspawn.c", 0x13);
               SendMessage (hWnd, WM_COMMAND, IDM_SPAWNIT, 0L);
               break;

          case IDM_NOTEPAD:
               sprintf (szSpawnAppName,"NOTEPAD.EXE");
               sprintf (szCommandLine, " WINSPAWN.C");
               SendMessage (hWnd, WM_COMMAND, IDM_SPAWNIT, 0L);
               break;

          case IDM_SPAWNALL:
               DialogBox (hInstMain, (LPSTR)"SpawnDlgBox", hWnd, 
                        lpProcSpawnDlgBox);
               sprintf (szSpawnAppName, "%s.%s", szDlgSpawnAppName,
                        szDlgExtension);
               sprintf (szCommandLine, "%c %s", strlen (szDlgCommandLine) + 1,
                        szDlgCommandLine);
               SendMessage (hWnd, WM_COMMAND, IDM_SPAWNIT, 0L);
               break;

          case IDM_HELP:
               ProcessMessage (hWnd, 2);
               break;
       }
       break;

  case WM_PAINT:
       BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
       EndPaint(hWnd, (LPPAINTSTRUCT)&ps);
       break;

  case WM_DESTROY:
       PostQuitMessage(0);
       break;

  default:
  {
   return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
  }
 }
 return (0L); 
}

/****************************************************************************/

BOOL FAR PASCAL SpawnDlgBoxProc (hDlg, iMessage, wParam, lParam)
HWND hDlg;
unsigned iMessage;
WORD wParam;
LONG lParam;
{
     int Index;
     char szChange [10];
     long lReturn;

     switch (iMessage) {
     case WM_INITDIALOG:
       SendDlgItemMessage (hDlg, IDD_DLGSPAWNAPPNAME, EM_LIMITTEXT,
                           (WORD)40, 0L);
       SendDlgItemMessage (hDlg, IDD_DLGCOMMANDLINE, EM_LIMITTEXT,
                           (WORD)40, 0L);
       SendDlgItemMessage (hDlg, IDD_DLGEXTENSION, EM_LIMITTEXT,
                           (WORD)10, 0L);
         SetDlgItemText (hDlg, IDD_DLGEXTENSION, szDlgExtension);

       hSpawnAppEdit = GetDlgItem (hDlg, IDD_DLGSPAWNAPPNAME);
         lpProcOldSpawnApp = 
                  (FARPROC) GetWindowLong (hSpawnAppEdit, GWL_WNDPROC);
         SetWindowLong (hSpawnAppEdit, GWL_WNDPROC, 
                        (LONG)lpProcNewSpawnDlgBox);
         SendMessage (hSpawnAppEdit, EM_SETSEL, 0, MAKELONG (0,32767));

       hExtensionEdit = GetDlgItem (hDlg, IDD_DLGEXTENSION);
         lpProcOldExtension =
                  (FARPROC)GetWindowLong (hExtensionEdit, GWL_WNDPROC);
         SetWindowLong (hExtensionEdit, GWL_WNDPROC, 
                        (LONG)lpProcNewSpawnDlgBox);
         SendMessage (hExtensionEdit, EM_SETSEL, 0, MAKELONG (0,32767));

       hCommandLineEdit = GetDlgItem (hDlg, IDD_DLGCOMMANDLINE);
         lpProcOldCommandLine = 
                  (FARPROC) GetWindowLong (hCommandLineEdit, GWL_WNDPROC);
         SetWindowLong (hCommandLineEdit, GWL_WNDPROC, 
                        (LONG)lpProcNewSpawnDlgBox);
         SendMessage (hCommandLineEdit, EM_SETSEL, 0, MAKELONG (0,32767));

       hOK2 = GetDlgItem (hDlg, IDOK);
     
       return TRUE;
       break;

     case WM_COMMAND:
       switch (wParam) {
         case IDOK:            
              GetDlgItemText (hDlg, IDD_DLGSPAWNAPPNAME,szDlgSpawnAppName,40);
              GetDlgItemText (hDlg, IDD_DLGCOMMANDLINE, szDlgCommandLine,40);
              GetDlgItemText (hDlg, IDD_DLGEXTENSION, szDlgExtension, 4) ;
              EndDialog (hDlg, TRUE);
              break;

         default:
              return FALSE;
      }
    default:
      return FALSE;
  }
  return TRUE;
}

/****************************************************************************/

BOOL FAR PASCAL NewSpawnDlgBoxProc  (hWnd, iMessage, wParam, lParam) 
     HWND     hWnd;
     unsigned iMessage; 
     WORD     wParam;
     LONG     lParam;
{
     switch (iMessage) {
       case WM_GETDLGCODE:
            return (DLGC_WANTALLKEYS);

       case WM_CHAR:
            if ((wParam == VK_TAB) || (wParam == VK_RETURN)) {
                SendMessage (hWndMain, WM_USER, 0, 0L);
                SetFocus (FindNextWindow (hWnd));
                return TRUE;
            }
            else {
              if (hWnd == hSpawnAppEdit) 
                return ((BOOL)CallWindowProc (lpProcOldSpawnApp, hWnd, 
                        iMessage, wParam, lParam));

              if (hWnd == hExtensionEdit) 
                return ((BOOL)CallWindowProc (lpProcOldExtension, hWnd, 
                        iMessage, wParam, lParam));

              if (hWnd == hCommandLineEdit) 
                return ((BOOL)CallWindowProc (lpProcOldCommandLine, hWnd, 
                        iMessage, wParam, lParam));
            }
            break;

       default:
         if (hWnd == hSpawnAppEdit)
            return ((BOOL)CallWindowProc (lpProcOldSpawnApp, hWnd,
                    iMessage, wParam, lParam));

         if (hWnd == hExtensionEdit)
            return ((BOOL)CallWindowProc (lpProcOldExtension, hWnd,
                    iMessage, wParam, lParam));

         if (hWnd == hCommandLineEdit)
            return ((BOOL)CallWindowProc (lpProcOldCommandLine, hWnd, 
                    iMessage, wParam, lParam));
     }
}

/****************************************************************************/

HWND FindNextWindow (hWnd)
     HWND   hWnd;
{
     if (hWnd == hSpawnAppEdit)         return hExtensionEdit;
     if (hWnd == hExtensionEdit)        return hCommandLineEdit;
     if (hWnd == hCommandLineEdit)      return hOK2;
     return NULL;
}

//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//                              ...end...
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

mms00786@uxa.cso.uiuc.edu (09/23/89)

That was very much appreciated, but it brought up another question.

Can I use code like winspawn, or perhaps taken from copyrighted sources like
Petzold's book, and include them as part of a program I might sell? Obviously,
I will have to change them a little for my needs, but beyond that, the meat of
the code is essentially the same. As an example, can I use the FileDlg code in
Petzold's book in my programs?

Sorry if this is the wrong news group.

Thanks
.
Milan
mms00786@uxa.cso.uiuc.edu
.

mcdonald@uxe.cso.uiuc.edu (09/23/89)

>/* ---------- "Spawning Windows Applications (The" ---------- */

>Ok, there has been enough posting back and forth about how to spawn a
>Windows application, and enough mis-information being stated that I
>decided I'd better 'bring out the horse' so you could get it straight
>from the source.

>Following this message will be the code that the Windows Development
>Support Team provides its customers on how to spawn applications in
>Windows. If you have an OnLine account, an archive of this information
>(includeing .OBJs and the .EXE) is available under the title of
>WINSPAWN.ARC in the software library.

>!!DO NOT EVER USE ANY OF THE 'spawn' FUNCTIONS FROM THE C RUNTIME LIBRARY!!

  >Execute your program, have it spawn Excel, then quit your program,
  >then quit Excel.

>There are conditions that will cause this to crash Windows. The reason
>being, that Excel (and some other non-MS applications) took for granted
>that they were being spawned by the MS-DOS Executive, which was
>'guaranteed' to be around longer then they were, and they were making
>use of the spawners stack to maintain some special data. If that stack
>disappears, then problems arise.

> __________________________________________________________________________
>     #####   ####### |	  Robert B. Hess, Microsoft Corp., Redmond, WA
>    ######  #######  |-----------------------------------------------------
>   ####### #######   |	roberth@microsof.uu.net
>  #### ##### ####    |	{decvax, uunet, uw-beaver}!microsof!roberth
> ####  ###  ####     |_____________________________________________________
>   "...my opinions are strictly my own, and not those of my employer..."


Very odd. Very odd indeed!!!!!!

An admission from an employee of Microsoft Corporation that their
products - Microsoft C, Microsoft Windows, and Microsoft Excel -
are DEFECTIVE.


FLAME ON!!!

really now! Look at the Ansi standard for C. The spawn and exec
functions are in the standard. They are REQUIRED either to work
or to do nothing at all. When tried under Windows they most certainly
do something. If I write a program under Windows, which most
certainly claims to be multitasking (at least Windows 386),
I would spawn new programs using "spawn". I tried it - and 
it most certainly worked in every case I tried. If it breaks

**** IT IS NOT MY FAULT ****.

Microsoft should fix their bugs!!!!!!

Is there an OFFICIAL admission that Windows is brain-dead?

Does this same sick admission apply to OS/2? Is it brain-dead also?

Doug McDonald 

bright@Data-IO.COM (Walter Bright) (09/26/89)

In article <245400027@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:
<<!!DO NOT EVER USE ANY OF THE 'spawn' FUNCTIONS FROM THE C RUNTIME LIBRARY!!
<<There are conditions that will cause this to crash Windows.
<Very odd. Very odd indeed!!!!!!
<An admission from an employee of Microsoft Corporation that their
<products - Microsoft C, Microsoft Windows, and Microsoft Excel -
<are DEFECTIVE.
<FLAME ON!!!
<really now! Look at the Ansi standard for C. The spawn and exec
<functions are in the standard. They are REQUIRED either to work
<or to do nothing at all. When tried under Windows they most certainly
<do something. If I write a program under Windows, which most
<certainly claims to be multitasking (at least Windows 386),
<I would spawn new programs using "spawn". I tried it - and 
<it most certainly worked in every case I tried. If it breaks
<**** IT IS NOT MY FAULT ****.
<Microsoft should fix their bugs!!!!!!
<Is there an OFFICIAL admission that Windows is brain-dead?
<Does this same sick admission apply to OS/2? Is it brain-dead also?

Ease up. All programs have bugs in them. The guy from Microsoft was
trying to be helpful by admitting a problem and suggesting a work-
around. Attacks like yours are what cause companies to normally clam
up and refuse to admit any problems, thus *causing* problems for
developers. It's to all our advantage to encourage vendors to disclose
bug lists and suggested workarounds.

By suggesting that anything posted by an MS employee is an OFFICIAL
pronouncement, you do a disservice to both the employee and the company.
You encourage companies to not allow their employees to post anything.
Is your mail message an official statement by your company? Or is it
personal opinion?

Windows predates ANSI C (which isn't even official yet) by YEARS. Thus,
non-conformance is not a bug.

When you write a non-trivial program with no bugs in it, be sure and
let us know.

meyer@s.cs.uiuc.edu (09/27/89)

No, Windows is not "brain-dead", that's the 80286 that is "brain-dead".

Windows, in its current incarnation, is just clumsy -- prone to falling over
and killing itself.

Don
	meyer@s.cs.uiuc.edu