diff --git a/winsup/cygwin/fhandler/termios.cc b/winsup/cygwin/fhandler/termios.cc index a3cecdb6fc..01d00daed5 100644 --- a/winsup/cygwin/fhandler/termios.cc +++ b/winsup/cygwin/fhandler/termios.cc @@ -702,24 +702,43 @@ fhandler_termios::fstat (struct stat *buf) } static bool -is_console_app (const WCHAR *filename) +is_console_app (path_conv &pc) { + tmp_pathbuf tp; + WCHAR *native_path = tp.w_get (); + pc.get_wide_win32_path (native_path); + + wchar_t *e = wcsrchr (native_path, L'.'); + if (e && (wcscasecmp (e, L".bat") == 0 || wcscasecmp (e, L".cmd") == 0)) + return true; + + if (pc.is_app_execution_alias ()) + { + UNICODE_STRING upath; + RtlInitUnicodeString (&upath, native_path); + path_conv target (&upath, PC_SYM_FOLLOW); + target.get_wide_win32_path (native_path); + } + HANDLE h; - h = CreateFileW (filename, GENERIC_READ, FILE_SHARE_READ, + h = CreateFileW (native_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (h == INVALID_HANDLE_VALUE) + return true; char buf[1024]; DWORD n; - ReadFile (h, buf, sizeof (buf), &n, 0); + BOOL res = ReadFile (h, buf, sizeof (buf), &n, 0); CloseHandle (h); + if (!res) + return true; /* The offset of Subsystem is the same for both IMAGE_NT_HEADERS32 and IMAGE_NT_HEADERS64, so only IMAGE_NT_HEADERS32 is used here. */ IMAGE_NT_HEADERS32 *p = (IMAGE_NT_HEADERS32 *) memmem (buf, n, "PE\0\0", 4); if (p && (char *) &p->OptionalHeader.DllCharacteristics <= buf + n) return p->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI; - wchar_t *e = wcsrchr (filename, L'.'); - if (e && (wcscasecmp (e, L".bat") == 0 || wcscasecmp (e, L".cmd") == 0)) - return true; - return false; + /* Return true for unknown to avoid standard handles from being unset. + Setting-up standard handles for GUI apps is pointless, but not unsafe. */ + return true; } int @@ -755,7 +774,7 @@ fhandler_termios::ioctl (unsigned int cmd, void *varg) void fhandler_termios::spawn_worker::setup (bool iscygwin, HANDLE h_stdin, - const WCHAR *runpath, bool nopcon, + path_conv &pc, bool nopcon, bool reset_sendsig, const WCHAR *envblock) { @@ -794,7 +813,7 @@ fhandler_termios::spawn_worker::setup (bool iscygwin, HANDLE h_stdin, ptys->setup_locale (); } } - if (!iscygwin && ptys_primary && is_console_app (runpath)) + if (!iscygwin && ptys_primary && is_console_app (pc)) { if (h_stdin == ptys_primary->get_handle_nat ()) stdin_is_ptys = true; diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h index 5e8f3d30f3..9fa73899c5 100644 --- a/winsup/cygwin/local_includes/fhandler.h +++ b/winsup/cygwin/local_includes/fhandler.h @@ -2035,7 +2035,7 @@ class fhandler_termios: public fhandler_base spawn_worker () : ptys_need_cleanup (false), cons_need_cleanup (false), stdin_is_ptys (false), ptys_ttyp (NULL) {} - void setup (bool iscygwin, HANDLE h_stdin, const WCHAR *runpath, + void setup (bool iscygwin, HANDLE h_stdin, path_conv &pc, bool nopcon, bool reset_sendsig, const WCHAR *envblock); bool need_cleanup () { return ptys_need_cleanup || cons_need_cleanup; } void cleanup (); diff --git a/winsup/cygwin/local_includes/path.h b/winsup/cygwin/local_includes/path.h index a9ce2c7e4b..ad142ddd3a 100644 --- a/winsup/cygwin/local_includes/path.h +++ b/winsup/cygwin/local_includes/path.h @@ -79,6 +79,7 @@ enum path_types PATH_SOCKET = _BIT ( 5), /* AF_UNIX socket file */ PATH_RESOLVE_PROCFD = _BIT ( 6), /* fd symlink via /proc */ PATH_REP_NOAPI = _BIT ( 7), /* rep. point unknown to WinAPI */ + PATH_APPEXECLINK = _BIT ( 8), /* rep. point app execution alias */ PATH_DONT_USE = _BIT (31) /* conversion to signed happens. */ }; @@ -214,6 +215,10 @@ class path_conv { return (path_flags & (PATH_REP | PATH_REP_NOAPI)) == PATH_REP; } + int is_app_execution_alias () const + { + return path_flags & PATH_APPEXECLINK; + } int isfifo () const {return dev.is_device (FH_FIFO);} int iscygdrive () const {return dev.is_device (FH_CYGDRIVE);} diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 8aff97acbe..405d4ba29f 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2661,7 +2661,7 @@ check_reparse_point_target (HANDLE h, bool remote, PREPARSE_DATA_BUFFER rp, if (i == 2 && n > 0 && n < size) { RtlInitCountedUnicodeString (psymbuf, buf, n * sizeof (WCHAR)); - return PATH_SYMLINK | PATH_REP; + return PATH_SYMLINK | PATH_REP | PATH_APPEXECLINK; } if (i == 2) break; diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 71add8755c..7d993d0810 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -579,7 +579,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, bool no_pcon = mode != _P_OVERLAY && mode != _P_WAIT; term_spawn_worker.setup (iscygwin (), handle (fileno_stdin, false), - runpath, no_pcon, reset_sendsig, envblock); + real_path, no_pcon, reset_sendsig, envblock); /* Set up needed handles for stdio */ si.dwFlags = STARTF_USESTDHANDLES;