Tcl Source Code

Artifact [7d5a384fc6]
Login

Artifact 7d5a384fc6bc1e0766d974f37e3a209fd9e2290f:

Attachment "diff.txt" to ticket [469618ffff] added by davygrvy 2002-01-15 09:10:38.
Index: tclWin32Dll.c
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWin32Dll.c,v
retrieving revision 1.11
diff -c -r1.11 tclWin32Dll.c
*** tclWin32Dll.c	2001/11/19 17:45:12	1.11
--- tclWin32Dll.c	2002/01/15 01:45:24
***************
*** 64,70 ****
      (DWORD (WINAPI *)(CONST TCHAR *, DWORD nBufferLength, WCHAR *, 
  	    TCHAR **)) GetFullPathNameA,
      (DWORD (WINAPI *)(HMODULE, WCHAR *, int)) GetModuleFileNameA,
!     (DWORD (WINAPI *)(CONST TCHAR *, WCHAR *, DWORD)) GetShortPathNameA,
      (UINT (WINAPI *)(CONST TCHAR *, CONST TCHAR *, UINT uUnique, 
  	    WCHAR *)) GetTempFileNameA,
      (DWORD (WINAPI *)(DWORD, WCHAR *)) GetTempPathA,
--- 64,70 ----
      (DWORD (WINAPI *)(CONST TCHAR *, DWORD nBufferLength, WCHAR *, 
  	    TCHAR **)) GetFullPathNameA,
      (DWORD (WINAPI *)(HMODULE, WCHAR *, int)) GetModuleFileNameA,
!     (DWORD (WINAPI *)(CONST TCHAR *, TCHAR *, DWORD)) GetShortPathNameA,
      (UINT (WINAPI *)(CONST TCHAR *, CONST TCHAR *, UINT uUnique, 
  	    WCHAR *)) GetTempFileNameA,
      (DWORD (WINAPI *)(DWORD, WCHAR *)) GetTempPathA,
***************
*** 75,81 ****
      (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *)) MoveFileA,
      (BOOL (WINAPI *)(CONST TCHAR *)) RemoveDirectoryA,
      (DWORD (WINAPI *)(CONST TCHAR *, CONST TCHAR *, CONST TCHAR *, DWORD, 
! 	    WCHAR *, TCHAR **)) SearchPathA,
      (BOOL (WINAPI *)(CONST TCHAR *)) SetCurrentDirectoryA,
      (BOOL (WINAPI *)(CONST TCHAR *, DWORD)) SetFileAttributesA,
      NULL,
--- 75,81 ----
      (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *)) MoveFileA,
      (BOOL (WINAPI *)(CONST TCHAR *)) RemoveDirectoryA,
      (DWORD (WINAPI *)(CONST TCHAR *, CONST TCHAR *, CONST TCHAR *, DWORD, 
! 	    TCHAR *, TCHAR **)) SearchPathA,
      (BOOL (WINAPI *)(CONST TCHAR *)) SetCurrentDirectoryA,
      (BOOL (WINAPI *)(CONST TCHAR *, DWORD)) SetFileAttributesA,
      NULL,
***************
*** 102,108 ****
      (DWORD (WINAPI *)(CONST TCHAR *, DWORD nBufferLength, WCHAR *, 
  	    TCHAR **)) GetFullPathNameW,
      (DWORD (WINAPI *)(HMODULE, WCHAR *, int)) GetModuleFileNameW,
!     (DWORD (WINAPI *)(CONST TCHAR *, WCHAR *, DWORD)) GetShortPathNameW,
      (UINT (WINAPI *)(CONST TCHAR *, CONST TCHAR *, UINT uUnique, 
  	    WCHAR *)) GetTempFileNameW,
      (DWORD (WINAPI *)(DWORD, WCHAR *)) GetTempPathW,
--- 102,108 ----
      (DWORD (WINAPI *)(CONST TCHAR *, DWORD nBufferLength, WCHAR *, 
  	    TCHAR **)) GetFullPathNameW,
      (DWORD (WINAPI *)(HMODULE, WCHAR *, int)) GetModuleFileNameW,
!     (DWORD (WINAPI *)(CONST TCHAR *, TCHAR *, DWORD)) GetShortPathNameW,
      (UINT (WINAPI *)(CONST TCHAR *, CONST TCHAR *, UINT uUnique, 
  	    WCHAR *)) GetTempFileNameW,
      (DWORD (WINAPI *)(DWORD, WCHAR *)) GetTempPathW,
***************
*** 113,119 ****
      (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *)) MoveFileW,
      (BOOL (WINAPI *)(CONST TCHAR *)) RemoveDirectoryW,
      (DWORD (WINAPI *)(CONST TCHAR *, CONST TCHAR *, CONST TCHAR *, DWORD, 
! 	    WCHAR *, TCHAR **)) SearchPathW,
      (BOOL (WINAPI *)(CONST TCHAR *)) SetCurrentDirectoryW,
      (BOOL (WINAPI *)(CONST TCHAR *, DWORD)) SetFileAttributesW,
      NULL,
--- 113,119 ----
      (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *)) MoveFileW,
      (BOOL (WINAPI *)(CONST TCHAR *)) RemoveDirectoryW,
      (DWORD (WINAPI *)(CONST TCHAR *, CONST TCHAR *, CONST TCHAR *, DWORD, 
! 	    TCHAR *, TCHAR **)) SearchPathW,
      (BOOL (WINAPI *)(CONST TCHAR *)) SetCurrentDirectoryW,
      (BOOL (WINAPI *)(CONST TCHAR *, DWORD)) SetFileAttributesW,
      NULL,
Index: tclWinInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWinInt.h,v
retrieving revision 1.12
diff -c -r1.12 tclWinInt.h
*** tclWinInt.h	2001/10/29 15:02:44	1.12
--- tclWinInt.h	2002/01/15 01:45:24
***************
*** 75,81 ****
      DWORD (WINAPI *getFullPathNameProc)(CONST TCHAR *, DWORD nBufferLength, 
  	    WCHAR *, TCHAR **);
      DWORD (WINAPI *getModuleFileNameProc)(HMODULE, WCHAR *, int);
!     DWORD (WINAPI *getShortPathNameProc)(CONST TCHAR *, WCHAR *, DWORD); 
      UINT (WINAPI *getTempFileNameProc)(CONST TCHAR *, CONST TCHAR *, UINT, 
  	    WCHAR *);
      DWORD (WINAPI *getTempPathProc)(DWORD, WCHAR *);
--- 75,81 ----
      DWORD (WINAPI *getFullPathNameProc)(CONST TCHAR *, DWORD nBufferLength, 
  	    WCHAR *, TCHAR **);
      DWORD (WINAPI *getModuleFileNameProc)(HMODULE, WCHAR *, int);
!     DWORD (WINAPI *getShortPathNameProc)(CONST TCHAR *, TCHAR *, DWORD); 
      UINT (WINAPI *getTempFileNameProc)(CONST TCHAR *, CONST TCHAR *, UINT, 
  	    WCHAR *);
      DWORD (WINAPI *getTempPathProc)(DWORD, WCHAR *);
***************
*** 86,92 ****
      BOOL (WINAPI *moveFileProc)(CONST TCHAR *, CONST TCHAR *);
      BOOL (WINAPI *removeDirectoryProc)(CONST TCHAR *);
      DWORD (WINAPI *searchPathProc)(CONST TCHAR *, CONST TCHAR *, 
! 	    CONST TCHAR *, DWORD, WCHAR *, TCHAR **);
      BOOL (WINAPI *setCurrentDirectoryProc)(CONST TCHAR *);
      BOOL (WINAPI *setFileAttributesProc)(CONST TCHAR *, DWORD);
      BOOL (WINAPI *getFileAttributesExProc)(CONST TCHAR *, 
--- 86,92 ----
      BOOL (WINAPI *moveFileProc)(CONST TCHAR *, CONST TCHAR *);
      BOOL (WINAPI *removeDirectoryProc)(CONST TCHAR *);
      DWORD (WINAPI *searchPathProc)(CONST TCHAR *, CONST TCHAR *, 
! 	    CONST TCHAR *, DWORD, TCHAR *, TCHAR **);
      BOOL (WINAPI *setCurrentDirectoryProc)(CONST TCHAR *);
      BOOL (WINAPI *setFileAttributesProc)(CONST TCHAR *, DWORD);
      BOOL (WINAPI *getFileAttributesExProc)(CONST TCHAR *, 
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	2002/01/15 01:45:30
***************
*** 18,23 ****
--- 18,32 ----
  #include <io.h>
  #include <sys/stat.h>
  
+ 
+ /*
+  *  The Platform SDK headers have this, but the stock headers don't.
+  */
+ #ifndef INVALID_SET_FILE_POINTER
+ #define INVALID_SET_FILE_POINTER ((DWORD)-1)
+ #endif
+ 
+ 
  /*
   * The following variable is used to tell whether this module has been
   * initialized.
***************
*** 39,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
--- 48,67 ----
   */
  
  #define APPL_NONE	0
! #define APPL_BATCH	1
! #define APPL_DOS16	2
! #define APPL_OS2	3
! #define APPL_OS2DRV	4
! #define APPL_WIN16	5
! #define APPL_WIN16DRV   6
! #define APPL_WIN32CUI   7
! #define APPL_WIN32GUI   8
! #define APPL_WIN32DLL   9
! #define APPL_WIN32DRV   10
! #define APPL_WIN64CUI   11
! #define APPL_WIN64GUI   12
! #define APPL_WIN64DLL   13
! #define APPL_WIN64DRV   14
  
  /*
   * The following constants and structures are used to encapsulate the state
***************
*** 177,184 ****
   * Declarations for functions used only in this file.
   */
  
! static int		ApplicationType(Tcl_Interp *interp,
! 			    const char *fileName, char *fullName);
  static void		BuildCommandLine(const char *executable, int argc, 
  			    char **argv, Tcl_DString *linePtr);
  static BOOL		HasConsole(void);
--- 197,204 ----
   * Declarations for functions used only in this file.
   */
  
! static int		ApplicationType(CONST char *originalName,
! 			    Tcl_DString *fullName);
  static void		BuildCommandLine(const char *executable, int argc, 
  			    char **argv, Tcl_DString *linePtr);
  static BOOL		HasConsole(void);
***************
*** 978,997 ****
      PROCESS_INFORMATION procInfo;
      SECURITY_ATTRIBUTES secAtts;
      HANDLE hProcess, h, inputHandle, outputHandle, errorHandle;
!     char execPath[MAX_PATH * TCL_UTF_MAX];
      WinFile *filePtr;
  
      PipeInit();
  
-     applType = ApplicationType(interp, argv[0], execPath);
-     if (applType == APPL_NONE) {
- 	return TCL_ERROR;
-     }
- 
-     result = TCL_ERROR;
-     Tcl_DStringInit(&cmdLine);
-     hProcess = GetCurrentProcess();
- 
      /*
       * STARTF_USESTDHANDLES must be used to pass handles to child process.
       * Using SetStdHandle() and/or dup2() only works when a console mode 
--- 998,1008 ----
      PROCESS_INFORMATION procInfo;
      SECURITY_ATTRIBUTES secAtts;
      HANDLE hProcess, h, inputHandle, outputHandle, errorHandle;
!     Tcl_DString exeFullPathUTF;
      WinFile *filePtr;
  
      PipeInit();
  
      /*
       * STARTF_USESTDHANDLES must be used to pass handles to child process.
       * Using SetStdHandle() and/or dup2() only works when a console mode 
***************
*** 1005,1010 ****
--- 1016,1036 ----
      startInfo.hStdOutput= INVALID_HANDLE_VALUE;
      startInfo.hStdError = INVALID_HANDLE_VALUE;
  
+     Tcl_DStringInit(&exeFullPathUTF);
+     Tcl_DStringInit(&cmdLine);
+     result = TCL_ERROR;
+ 
+     applType = ApplicationType(argv[0], &exeFullPathUTF);
+     if (applType == APPL_NONE) {
+ 	TclWinConvertError(GetLastError());
+ 	Tcl_AppendResult(interp, "couldn't execute \"",
+ 		Tcl_DStringValue(&exeFullPathUTF), "\": ",
+ 		Tcl_PosixError(interp), (char *) NULL);
+ 	goto end;
+     }
+ 
+     hProcess = GetCurrentProcess();
+ 
      secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
      secAtts.lpSecurityDescriptor = NULL;
      secAtts.bInheritHandle = TRUE;
***************
*** 1087,1093 ****
  	 */
  
  	if ((TclWinGetPlatformId() == VER_PLATFORM_WIN32_WINDOWS) 
! 		&& (applType == APPL_DOS)) {
  	    if (CreatePipe(&h, &startInfo.hStdOutput, &secAtts, 0) != FALSE) {
  		CloseHandle(h);
  	    }
--- 1113,1119 ----
  	 */
  
  	if ((TclWinGetPlatformId() == VER_PLATFORM_WIN32_WINDOWS) 
! 		&& (applType == APPL_DOS16 || applType == APPL_BATCH)) {
  	    if (CreatePipe(&h, &startInfo.hStdOutput, &secAtts, 0) != FALSE) {
  		CloseHandle(h);
  	    }
***************
*** 1141,1148 ****
  
      if (TclWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
  	if (HasConsole()) {
! 	    createFlags = 0;
! 	} else if (applType == APPL_DOS) {
  	    /*
  	     * Under NT, 16-bit DOS applications will not run unless they
  	     * can be attached to a console.  If we are running without a
--- 1167,1178 ----
  
      if (TclWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
  	if (HasConsole()) {
! 	    if (applType == APPL_DOS16) {
! 		createFlags = CREATE_SEPARATE_WOW_VDM;
! 	    } else {
! 		createFlags = 0;
! 	    }
! 	} else if (applType == APPL_DOS16 || applType == APPL_BATCH) {
  	    /*
  	     * Under NT, 16-bit DOS applications will not run unless they
  	     * can be attached to a console.  If we are running without a
***************
*** 1165,1171 ****
  	    createFlags = DETACHED_PROCESS;
  	}
  	
! 	if (applType == APPL_DOS) {
  	    /*
  	     * Under Windows 95, 16-bit DOS applications do not work well 
  	     * with pipes:
--- 1195,1201 ----
  	    createFlags = DETACHED_PROCESS;
  	}
  	
! 	if (applType == APPL_DOS16 || applType == APPL_BATCH) {
  	    /*
  	     * Under Windows 95, 16-bit DOS applications do not work well 
  	     * with pipes:
***************
*** 1223,1229 ****
       * using ab~1.def instead of "a b.default").  
       */
  
!     BuildCommandLine(execPath, argc, argv, &cmdLine);
  
      if ((*tclWinProcs->createProcessProc)(NULL, 
  	    (TCHAR *) Tcl_DStringValue(&cmdLine), NULL, NULL, TRUE, 
--- 1253,1259 ----
       * using ab~1.def instead of "a b.default").  
       */
  
!     BuildCommandLine(Tcl_DStringValue(&exeFullPathUTF), argc, argv, &cmdLine);
  
      if ((*tclWinProcs->createProcessProc)(NULL, 
  	    (TCHAR *) Tcl_DStringValue(&cmdLine), NULL, NULL, TRUE, 
***************
*** 1239,1245 ****
       * process.
       */
  
!     if (applType == APPL_DOS) {
  	WaitForSingleObject(procInfo.hProcess, 50);
      }
  
--- 1269,1275 ----
       * process.
       */
  
!     if (applType == APPL_DOS16 || applType == APPL_BATCH) {
  	WaitForSingleObject(procInfo.hProcess, 50);
      }
  
***************
*** 1261,1267 ****
      }
      result = TCL_OK;
  
!     end:
      Tcl_DStringFree(&cmdLine);
      if (startInfo.hStdInput != INVALID_HANDLE_VALUE) {
          CloseHandle(startInfo.hStdInput);
--- 1291,1298 ----
      }
      result = TCL_OK;
  
! end:
!     Tcl_DStringFree(&exeFullPathUTF);
      Tcl_DStringFree(&cmdLine);
      if (startInfo.hStdInput != INVALID_HANDLE_VALUE) {
          CloseHandle(startInfo.hStdInput);
***************
*** 1346,1368 ****
   */
  
  static int
! ApplicationType(interp, originalName, fullName)
!     Tcl_Interp *interp;		/* Interp, for error message. */
!     const char *originalName;	/* Name of the application to find. */
!     char fullName[];		/* Filled with complete path to 
! 				 * application. */
  {
!     int applType, i, nameLen, found;
      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
--- 1377,1404 ----
   */
  
  static int
! ApplicationType(originalName, fullName)
!     CONST char *originalName;	/* Name of the application to find. (in UTF-8) */
!     Tcl_DString *fullName;	/* Buffer space filled with complete path to 
! 				 * application. (in UTF-8) */
  {
!     int applType, i, nameLen, nativeNameLen;
      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, nativeNameBuff, ds;
      TCHAR *nativeName;
!     WCHAR nativeShortPath[MAX_PATH];   /* needed for unicode space */
!     static char extensions[][5] = {"", ".com", ".exe", ".bat", ".cmd"};
!     int offset64;
  
      /* 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
***************
*** 1380,1427 ****
      applType = APPL_NONE;
      Tcl_DStringInit(&nameBuf);
      Tcl_DStringAppend(&nameBuf, originalName, -1);
      nameLen = Tcl_DStringLength(&nameBuf);
  
!     for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) {
  	Tcl_DStringSetLength(&nameBuf, nameLen);
  	Tcl_DStringAppend(&nameBuf, extensions[i], -1);
          nativeName = Tcl_WinUtfToTChar(Tcl_DStringValue(&nameBuf), 
  		Tcl_DStringLength(&nameBuf), &ds);
! 	found = (*tclWinProcs->searchPathProc)(NULL, nativeName, NULL, 
! 		MAX_PATH, nativeFullPath, &rest);
! 	Tcl_DStringFree(&ds);
! 	if (found == 0) {
  	    continue;
  	}
  
  	/*
! 	 * Ignore matches on directories or data files, return if identified
! 	 * a known type.
  	 */
  
! 	attr = (*tclWinProcs->getFileAttributesProc)((TCHAR *) nativeFullPath);
! 	if ((attr == 0xffffffff) || (attr & FILE_ATTRIBUTE_DIRECTORY)) {
  	    continue;
  	}
! 	strcpy(fullName, Tcl_WinTCharToUtf((TCHAR *) nativeFullPath, -1, &ds));
! 	Tcl_DStringFree(&ds);
  
! 	ext = strrchr(fullName, '.');
! 	if ((ext != NULL) && (stricmp(ext, ".bat") == 0)) {
! 	    applType = APPL_DOS;
  	    break;
  	}
  	
! 	hFile = (*tclWinProcs->createFileProc)((TCHAR *) nativeFullPath, 
  		GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 
  		FILE_ATTRIBUTE_NORMAL, NULL);
  	if (hFile == INVALID_HANDLE_VALUE) {
! 	    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.
--- 1416,1482 ----
      applType = APPL_NONE;
      Tcl_DStringInit(&nameBuf);
      Tcl_DStringAppend(&nameBuf, originalName, -1);
+     Tcl_DStringAppend(fullName, originalName, -1);
      nameLen = Tcl_DStringLength(&nameBuf);
  
!     for (i = 0; i < (sizeof(extensions) / sizeof(extensions[0])); i++) {
  	Tcl_DStringSetLength(&nameBuf, nameLen);
  	Tcl_DStringAppend(&nameBuf, extensions[i], -1);
          nativeName = Tcl_WinUtfToTChar(Tcl_DStringValue(&nameBuf), 
  		Tcl_DStringLength(&nameBuf), &ds);
! 
! 	/* Just get the size of the buffer needed, when found. */
! 	nativeNameLen = (*tclWinProcs->searchPathProc)(NULL, nativeName,
! 		NULL, 0, NULL, &rest);
! 
! 	if (nativeNameLen == 0) {
! 	    /* not found. */
! 	    Tcl_DStringFree(&ds);
  	    continue;
  	}
  
+ 	/* Set the buffer needed. */
+ 	Tcl_DStringInit(&nativeNameBuff);
+ 	Tcl_DStringSetLength(&nativeNameBuff, 
+ 		(tclWinProcs->useWide ? nativeNameLen*2 : nativeNameLen));
+ 
+ 	(*tclWinProcs->searchPathProc)(NULL, nativeName, NULL,
+ 		Tcl_DStringLength(&nativeNameBuff),
+ 		(TCHAR *) Tcl_DStringValue(&nativeNameBuff), &rest);
+ 	Tcl_DStringFree(&ds);
+ 
  	/*
! 	 * Ignore matches on directories, keep falling through
! 	 * when identified as something else.
  	 */
  
! 	attr = (*tclWinProcs->getFileAttributesProc)(
! 		(TCHAR *) Tcl_DStringValue(&nativeNameBuff));
! 	if ((attr == -1) || (attr & FILE_ATTRIBUTE_DIRECTORY)) {
  	    continue;
  	}
! 	Tcl_WinTCharToUtf((TCHAR *) Tcl_DStringValue(&nativeNameBuff),
! 		-1, fullName);
  
! 	ext = strrchr(Tcl_DStringValue(fullName), '.');
! 	if ((ext != NULL) && (stricmp(ext, ".bat") == 0 ||
! 		stricmp(ext, ".cmd") == 0)) {
! 	    applType = APPL_BATCH;
  	    break;
  	}
  	
! 	hFile = (*tclWinProcs->createFileProc)(
! 		(TCHAR *) Tcl_DStringValue(&nativeNameBuff),
  		GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 
  		FILE_ATTRIBUTE_NORMAL, NULL);
  	if (hFile == INVALID_HANDLE_VALUE) {
! 	    applType = APPL_NONE;
! 	    break;
  	}
  
! 	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,1506 ****
  	     * magic numbers and everything.  
  	     */
  
  	    CloseHandle(hFile);
  	    if ((ext != NULL) && (strcmp(ext, ".com") == 0)) {
! 		applType = APPL_DOS;
  		break;
  	    }
! 	    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);
! 	    applType = APPL_DOS;
  	    break;
  	}
  
  	/* 
! 	 * 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;
  	}
  	break;
      }
-     Tcl_DStringFree(&nameBuf);
  
!     if (applType == APPL_NONE) {
! 	TclWinConvertError(GetLastError());
! 	Tcl_AppendResult(interp, "couldn't execute \"", originalName,
! 		"\": ", Tcl_PosixError(interp), (char *) NULL);
! 	return APPL_NONE;
!     }
! 
!     if ((applType == APPL_DOS) || (applType == APPL_WIN3X)) {
  	/* 
! 	 * Replace long path name of executable with short path name for 
  	 * 16-bit applications.  Otherwise the application may not be able
! 	 * to correctly parse its own command line to separate off the 
  	 * application name from the arguments.
  	 */
  
! 	(*tclWinProcs->getShortPathNameProc)((TCHAR *) nativeFullPath, 
! 		nativeFullPath, MAX_PATH);
! 	strcpy(fullName, Tcl_WinTCharToUtf((TCHAR *) nativeFullPath, -1, &ds));
! 	Tcl_DStringFree(&ds);
      }
      return applType;
  }
  
! /*    
   *----------------------------------------------------------------------
   *
   * BuildCommandLine --
--- 1485,1685 ----
  	     * 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_DOS16;
  		break;
  	    }
! 	    SetLastError(ERROR_INVALID_EXE_SIGNATURE);
! 	    applType = APPL_NONE;
! 	    break;
  	}
! 	if (p236.e_lfarlc < 0x40 || p236.e_lfanew == 0 /* reserved */) {
  	    /* 
! 	     * Old-style header only.  Can't be more than a DOS16 executable.
  	     */
  
  	    CloseHandle(hFile);
! 	    applType = APPL_DOS16;
  	    break;
  	}
  
  	/* 
! 	 * The LONG at p236.e_lfanew points to the real exe header only
! 	 * when p236.e_lfarlc is set to 40h (or greater).
  	 */
! 	
! 	if (SetFilePointer(hFile, p236.e_lfanew, NULL, FILE_BEGIN)
! 		== INVALID_SET_FILE_POINTER) {
! 	    /* Bogus PE header pointer. */
! 	    CloseHandle(hFile);
! 	    SetLastError(ERROR_BAD_EXE_FORMAT);
! 	    applType = APPL_NONE;
! 	    break;
! 	}
! 	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).
! 	 *  'W4'  Variant of above.
! 	 */
! 
! 	if (header.pe.Signature == IMAGE_NT_SIGNATURE) {
! 	    if (!(header.pe.FileHeader.Characteristics &
! 		    IMAGE_FILE_EXECUTABLE_IMAGE)) {
! 		/* Not an executable. */
! 		SetLastError(ERROR_BAD_EXE_FORMAT);
! 		applType = APPL_NONE;
! 		break;
! 	    }
! 
! 	    if (header.pe.OptionalHeader.Magic ==
! 		    IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
! 		/* Win32 executable */
! 		offset64 = 0;
! 	    } else if (header.pe.OptionalHeader.Magic ==
! 		    IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
! 		/* Win64 executable */
! 		offset64 = 4;
! 	    } else {
! 		/* Unknown magic number */
! 		SetLastError(ERROR_INVALID_MODULETYPE);
! 		applType = APPL_NONE;
! 		break;
! 	    }
! 
! 	    if (header.pe.FileHeader.Characteristics & IMAGE_FILE_DLL) {
! 		/*
! 		 * DLLs are executable, but indirectly.  We shouldn't return
! 		 * APPL_NONE or the subsystem that its said to run under
! 		 * as it's not the complete truth, so return a new type and
! 		 * let the user decide what to do.
! 		 */
! 
! 		applType = APPL_WIN32DLL + offset64;
! 		break;
! 	    }
! 
! 	    switch (header.pe.OptionalHeader.Subsystem) {
! 		case IMAGE_SUBSYSTEM_WINDOWS_CUI:
! 		case IMAGE_SUBSYSTEM_OS2_CUI:
! 		case IMAGE_SUBSYSTEM_POSIX_CUI:
! 		    /* Runs in the CUI subsystem */
! 		    applType = APPL_WIN32CUI + offset64;
! 		    break;
! 
! 		case IMAGE_SUBSYSTEM_WINDOWS_GUI:
! 		case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
! 		    /* Runs in the GUI subsystem */
! 		    applType = APPL_WIN32GUI + offset64;
! 		    break;
! 
! 		case IMAGE_SUBSYSTEM_UNKNOWN:
! 		case IMAGE_SUBSYSTEM_NATIVE:
! 		case IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
! 		    /* Special Driver */
! 		    applType = APPL_WIN32DRV + offset64;
! 		    break;
! 	    }
! 
! #define IMAGE_NE_FLAG_DRIVER	0x8000
! #define IMAGE_NE_EXETYP_OS2	0x1
! #define IMAGE_NE_EXETYP_WIN	0x2
! #define IMAGE_NE_EXETYP_DOS4X	0x3
! #define IMAGE_NE_EXETYP_WIN386	0x4
! 
! 	} else if (header.ne.ne_magic == IMAGE_OS2_SIGNATURE) {
! 	    switch (header.ne.ne_exetyp) {
! 		case IMAGE_NE_EXETYP_OS2:    /* Microsoft/IBM OS/2 1.x */
! 		    if (header.ne.ne_flags & IMAGE_NE_FLAG_DRIVER) {
! 			applType = APPL_OS2DRV;
! 		    } else {
! 			applType = APPL_OS2;
! 		    }
! 		    break;
! 
! 		case IMAGE_NE_EXETYP_WIN:    /* Microsoft Windows */
! 		case IMAGE_NE_EXETYP_WIN386: /* Same, but Protected mode */
! 		    if (header.ne.ne_flags & IMAGE_NE_FLAG_DRIVER) {
! 			applType = APPL_WIN16DRV;
! 		    } else {
! 			applType = APPL_WIN16;
! 		    }
! 		    break;
  
! 		case IMAGE_NE_EXETYP_DOS4X:  /* Microsoft MS-DOS 4.x */
! 		    applType = APPL_DOS16;
! 		    break;
! 
! 		default:
! 		    /* Unidentified */
! 		    SetLastError(ERROR_INVALID_MODULETYPE);
! 		    applType = APPL_NONE;
! 	    }
! 	} else if (
! 		header.le.e32_magic == IMAGE_OS2_SIGNATURE_LE /* 'LE' */ ||
! 		header.le.e32_magic == 0x584C /* 'LX' */ ||
! 		header.le.e32_magic == 0x3357 /* 'W3' */ ||
! 		header.le.e32_magic == 0x3457 /* 'W4' */
! 	){
! 	    /* Virtual device drivers are not executables, per se. */
! 	    applType = APPL_WIN16DRV;
! 	} else {
! 	    /* The loader will barf anyway, so barf now. */
! 	    SetLastError(ERROR_INVALID_EXE_SIGNATURE);
! 	    applType = APPL_NONE;
  	}
  	break;
      }
  
!     if (applType == APPL_DOS16 || applType == APPL_WIN16 ||
! 	    applType == APPL_WIN16DRV || applType == APPL_OS2 ||
! 	    applType == APPL_OS2DRV) {
  	/* 
! 	 * Replace long path name of executable with short path name for
  	 * 16-bit applications.  Otherwise the application may not be able
! 	 * to correctly parse its own command line to separate off the
  	 * application name from the arguments.
  	 */
  
! 	(*tclWinProcs->getShortPathNameProc)(
! 		(TCHAR *) Tcl_DStringValue(&nativeNameBuff),
! 		(TCHAR *) nativeShortPath, MAX_PATH);
! 	Tcl_WinTCharToUtf((TCHAR *) nativeShortPath, -1, fullName);
      }
+     Tcl_DStringFree(&nativeNameBuff);
+     Tcl_DStringFree(&nameBuf);
      return applType;
  }
  
! /*
   *----------------------------------------------------------------------
   *
   * BuildCommandLine --