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