Hi Takashi, that commit message sounds very good to me, thank you for that!
And I think you're right about app execution aliases only allowing `.exe`. At least in practice that'll be the case. Thank you, Johannes -------- Original Message -------- From: Takashi Yano <[email protected]> Sent: December 19, 2025 2:45:12 AM GMT+01:00 To: [email protected] Subject: Re: [PATCH v4 5/5] Cygwin: termios: Handle app execution alias in is_console_app() On Thu, 18 Dec 2025 09:22:52 +0100 (CET) Johannes Schindelin wrote: > Hi Takashi, > > On Thu, 18 Dec 2025, Takashi Yano wrote: > > > After the commit f74dc93c6359, WSL cannot start by distribution name > > such as debian.exe, which has '.exe' extention but actually is an app > > execution alias. This is because the commit f74dc93c6359 disabled to > > follow windows reparse point by adding PC_SYM_NOFOLLOW_REP flag in > > spawn.cc, that path is used for sapwning a process. As a result, the > > path, that is_console_app () received, had been the reparse point of > > app execution alias, then it returned false for the the path due to > > open-failure because CreateFileW() cannot open an app execution alias, > > while it can open normal reparse point. If is_console_app() returns > > false, standard handles for console app (such as WSL) would not be > > setup. This causes that the console input cannot be transfered to the > > non-cygwin app. > > Just a suggestion: Start by describing the bug instead of leading with the > commit that caused the bug. Something along the lines "Microsoft Store > apps are run via 'app execution aliases', i.e. special reparse points. > Cygwin usually treats those like symbolic links. However, unlike proper > symbolic links, app execution aliases are not resolved when trying to read > the file contents via `CreateFile()`/`ReadFile()` [...]". Thanks for the advice. How about: Microsoft Store apps are run via app execution aliases, i.e. special reparse points. Currently, spawn.cc does not resolve a reparse point when retrieving the path of app after the commit f74dc93c6359, that disabled to follow windows reparse point by adding PC_SYM_NOFOLLOW_REP flag. However, unlike proper reparse point, app execution aliases are not resolved when trying to open the file via CreateFile(). As a result, if the path, that is_console_app() received, is the reparse point for an app execution alias, the func retuned false due to open-failure because CreateFile() cannot open an app execution alias, while it can open normal reparse point. If is_console_app() returns false, standard handles for console app (such as WSL) would not be setup. This causes that the console input cannot be transfered to the non-cygwin app. This patch fixes the issue by locally converting the path once again using option PC_SYM_FOLLOW (without PC_SYM_NOFOLLOW_REP), which is used inside is_console_app() to resolve the reparse point, if the path is an app execution alias. > > This patch fixes the issue by locally converting the path, which is > > a path to the app execution alias, once again using PC_SYM_FOLLOW > > (without PC_SYM_NOFOLLOW_REP) option path_conv for using inside of > > is_console_app() to resolve the reparse point here, if the path is > > an app execution alias. > > > > Fixes: f74dc93c6359 ("fix native symlink spawn passing wrong arg0") > > Reviewed-by: Johannes Schindelin <[email protected]> > > Signed-off-by: Takashi Yano <[email protected]> > > --- > > winsup/cygwin/fhandler/termios.cc | 23 ++++++++++++++++++----- > > winsup/cygwin/local_includes/fhandler.h | 2 +- > > winsup/cygwin/spawn.cc | 2 +- > > 3 files changed, 20 insertions(+), 7 deletions(-) > > > > diff --git a/winsup/cygwin/fhandler/termios.cc > > b/winsup/cygwin/fhandler/termios.cc > > index f99ae6c80..694a5c20f 100644 > > --- a/winsup/cygwin/fhandler/termios.cc > > +++ b/winsup/cygwin/fhandler/termios.cc > > @@ -702,13 +702,26 @@ fhandler_termios::fstat (struct stat *buf) > > } > > > > static bool > > -is_console_app (const WCHAR *filename) > > +is_console_app (path_conv &pc) > > { > > - wchar_t *e = wcsrchr (filename, L'.'); > > + 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); > > + } > > + > > It might make sense to move this `is_app_execution_alias()` block before > looking at the file extension, not that it will matter a lot in pratices > because as far as I understand, app execution aliases are only ever > created for `.exe` files, with the same base name as the target (or at > least with the same file extension). Both is OK, I think. AFAIK, app execution alias never has extension: ".bat" or ".cmd" so, the both 'if' blocks are exclusive. So, only the question is: which is more natural for readers.
