Attachment "noGUIexec.txt" to
ticket [469618ffff]
added by
davygrvy
2001-10-10 10:52:31.
Index: tclWinPipe.c
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWinPipe.c,v
retrieving revision 1.20
diff -c -r1.20 tclWinPipe.c
*** tclWinPipe.c 2001/09/06 01:38:02 1.20
--- tclWinPipe.c 2001/10/10 03:48:37
***************
*** 41,47 ****
#define APPL_NONE 0
#define APPL_DOS 1
#define APPL_WIN3X 2
! #define APPL_WIN32 3
/*
* The following constants and structures are used to encapsulate the state
--- 41,48 ----
#define APPL_NONE 0
#define APPL_DOS 1
#define APPL_WIN3X 2
! #define APPL_WIN32CUI 3
! #define APPL_WIN32GUI 4
/*
* The following constants and structures are used to encapsulate the state
***************
*** 927,934 ****
*
* The complete Windows search path is searched to find the specified
* executable. If an executable by the given name is not found,
! * automatically tries appending ".com", ".exe", and ".bat" to the
! * executable name.
*
* Results:
* The return value is TCL_ERROR and an error message is left in
--- 928,935 ----
*
* The complete Windows search path is searched to find the specified
* executable. If an executable by the given name is not found,
! * automatically tries appending ".com", ".exe", ".bat", and ".cmd"
! * to the executable name.
*
* Results:
* The return value is TCL_ERROR and an error message is left in
***************
*** 986,991 ****
--- 987,998 ----
applType = ApplicationType(interp, argv[0], execPath);
if (applType == APPL_NONE) {
return TCL_ERROR;
+ } else if (applType == APPL_WIN32GUI) {
+ TclWinConvertError(ERROR_BAD_PIPE);
+ Tcl_AppendResult(interp, execPath,
+ " is a GUI application that doesn't support pipes: ",
+ Tcl_PosixError(interp), (char *) NULL);
+ return TCL_ERROR;
}
result = TCL_ERROR;
***************
*** 1356,1368 ****
HANDLE hFile;
TCHAR *rest;
char *ext;
- char buf[2];
DWORD attr, read;
! IMAGE_DOS_HEADER header;
Tcl_DString nameBuf, ds;
TCHAR *nativeName;
WCHAR nativeFullPath[MAX_PATH];
! static char extensions[][5] = {"", ".com", ".exe", ".bat"};
/* Look for the program as an external program. First try the name
* as it is, then try adding .com, .exe, and .bat, in that order, to
--- 1363,1380 ----
HANDLE hFile;
TCHAR *rest;
char *ext;
DWORD attr, read;
! IMAGE_DOS_HEADER p236; /* p236, DOS (old-style) executable-file header */
! union {
! BYTE buf[200];
! IMAGE_NT_HEADERS pe;
! IMAGE_OS2_HEADER ne;
! IMAGE_VXD_HEADER le;
! } header;
Tcl_DString nameBuf, ds;
TCHAR *nativeName;
WCHAR nativeFullPath[MAX_PATH];
! static char extensions[][5] = {"", ".com", ".exe", ".bat", ".cmd"};
/* Look for the program as an external program. First try the name
* as it is, then try adding .com, .exe, and .bat, in that order, to
***************
*** 1407,1413 ****
Tcl_DStringFree(&ds);
ext = strrchr(fullName, '.');
! if ((ext != NULL) && (stricmp(ext, ".bat") == 0)) {
applType = APPL_DOS;
break;
}
--- 1419,1426 ----
Tcl_DStringFree(&ds);
ext = strrchr(fullName, '.');
! if ((ext != NULL) && (stricmp(ext, ".bat") == 0 ||
! stricmp(ext, ".cmd") == 0)) {
applType = APPL_DOS;
break;
}
***************
*** 1419,1427 ****
continue;
}
! header.e_magic = 0;
! ReadFile(hFile, (void *) &header, sizeof(header), &read, NULL);
! if (header.e_magic != IMAGE_DOS_SIGNATURE) {
/*
* Doesn't have the magic number for relocatable executables. If
* filename ends with .com, assume it's a DOS application anyhow.
--- 1432,1440 ----
continue;
}
! p236.e_magic = 0;
! ReadFile(hFile, &p236, sizeof(IMAGE_DOS_HEADER), &read, NULL);
! if (p236.e_magic != IMAGE_DOS_SIGNATURE) {
/*
* Doesn't have the magic number for relocatable executables. If
* filename ends with .com, assume it's a DOS application anyhow.
***************
*** 1430,1435 ****
--- 1443,1467 ----
* magic numbers and everything.
*/
+ /*
+ * Additional notes from Ralf Brown's interupt list:
+ *
+ * The COM files are raw binary executables and are a leftover
+ * from the old CP/M machines with 64K RAM. A COM program can
+ * only have a size of less than one segment (64K), including code
+ * and static data since no fixups for segment relocation or
+ * anything else is included. One method to check for a COM file
+ * is to check if the first byte in the file could be a valid jump
+ * or call opcode, but this is a very weak test since a COM file
+ * is not required to start with a jump or a call. In principle,
+ * a COM file is just loaded at offset 100h in the segment and
+ * then executed.
+ *
+ * OFFSET Count TYPE Description
+ * 0000h 1 byte ID=0E9h
+ * ID=0EBh
+ */
+
CloseHandle(hFile);
if ((ext != NULL) && (strcmp(ext, ".com") == 0)) {
applType = APPL_DOS;
***************
*** 1437,1447 ****
}
continue;
}
! if (header.e_lfarlc != sizeof(header)) {
/*
! * All Windows 3.X and Win32 and some DOS programs have this value
! * set here. If it doesn't, assume that since it already had the
! * other magic number it was a DOS application.
*/
CloseHandle(hFile);
--- 1469,1477 ----
}
continue;
}
! if (p236.e_lfarlc < 0x40 || p236.e_lfanew == 0 /* reserved */) {
/*
! * Old-style header only. Can't be more than a DOS executable.
*/
CloseHandle(hFile);
***************
*** 1450,1474 ****
}
/*
! * The DWORD at header.e_lfanew points to yet another magic number.
*/
!
! buf[0] = '\0';
! SetFilePointer(hFile, header.e_lfanew, NULL, FILE_BEGIN);
! ReadFile(hFile, (void *) buf, 2, &read, NULL);
CloseHandle(hFile);
! if ((buf[0] == 'N') && (buf[1] == 'E')) {
! applType = APPL_WIN3X;
! } else if ((buf[0] == 'P') && (buf[1] == 'E')) {
! applType = APPL_WIN32;
} else {
/*
! * Strictly speaking, there should be a test that there
! * is an 'L' and 'E' at buf[0..1], to identify the type as
! * DOS, but of course we ran into a DOS executable that
! * _doesn't_ have the magic number -- specifically, one
! * compiled using the Lahey Fortran90 compiler.
*/
applType = APPL_DOS;
--- 1480,1565 ----
}
/*
! * The LONG at p236.e_lfanew points to the real exe header only
! * when p236.e_lfarlc is set to 40h (or greater).
*/
!
! SetFilePointer(hFile, p236.e_lfanew, NULL, FILE_BEGIN);
! ReadFile(hFile, header.buf, 200, &read, NULL);
CloseHandle(hFile);
+
+ /*
+ * Check the sigs against the following list:
+ * 'PE\0\0' Win32 (Windows NT and Win32s) portable executable based
+ * on Unix COFF.
+ * 'NE' Windows or OS/2 1.x segmented ("new") executable.
+ * 'LE' Windows virtual device driver (VxD) linear executable.
+ * 'LX' variant of LE used in OS/2 2.x
+ * 'W3' Windows WIN386.EXE file; a collection of LE files
+ * (protected mode windows).
+ * 'MZ' old-style p236 DOS executable.
+ */
+
+ if (header.pe.Signature == IMAGE_NT_SIGNATURE) {
+ /*
+ * Win32, "PE\0\0" which is short for "Portable Executable".
+ */
+
+ if (header.pe.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC
+ || !(header.pe.FileHeader.Characteristics &
+ IMAGE_FILE_EXECUTABLE_IMAGE)) {
+ /*
+ * Not an executable. Might be a dll or a COMDAT library.
+ */
+
+ applType = APPL_NONE;
+ break;
+ }
+
+ switch (header.pe.OptionalHeader.Subsystem) {
+ case IMAGE_SUBSYSTEM_WINDOWS_CUI:
+ case IMAGE_SUBSYSTEM_OS2_CUI:
+ case IMAGE_SUBSYSTEM_POSIX_CUI:
+ /*
+ * image runs in the Windows, OS/2, or Posix character
+ * subsystem.
+ */
+
+ applType = APPL_WIN32CUI;
+ break;
+
+ default:
+ /*
+ * Non-CUI applications are run detached. Return a flag
+ * that will indicate this error.
+ */
+
+ applType = APPL_WIN32GUI;
+ }
+ } else if (header.ne.ne_magic == IMAGE_OS2_SIGNATURE) {
+ switch (header.ne.ne_exetyp) {
+ case 0x1: /* Microsoft/IBM OS/2 (default) */
+ case 0x3: /* Microsoft MS-DOS 4.x */
+ /* Only these might be character-mode. */
+ applType = APPL_DOS;
+ break;
+
+ default:
+ applType = APPL_NONE;
+ }
+
+ } else if (header.le.e32_magic == IMAGE_OS2_SIGNATURE_LE ||
+ header.le.e32_magic == 'LX' ||
+ header.le.e32_magic == 'W3') {
+ /*
+ * Virtual device drivers are not executables, per se.
+ */
! applType = APPL_NONE;
} else {
/*
! * NOTE: The Lahey Fortran90 compiler might make executables
! * that have a bogus signature and end-up here.
*/
applType = APPL_DOS;