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 --