diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 9d2184d6a..1d6bcbe48 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2459,6 +2459,22 @@ symlink_info::check_sysfile (HANDLE h) return res; } +typedef struct _REPARSE_APPEXECLINK_BUFFER +{ + DWORD ReparseTag; + WORD ReparseDataLength; + WORD Reserved; + struct { + DWORD Version; /* Take member name with a grain of salt. */ + WCHAR Strings[1]; /* Four serialized, NUL-terminated WCHAR strings: + - Package ID + - Entry Point + - Executable Path + - Application Type + We're only interested in the Executable Path */ + } AppExecLinkReparseBuffer; +} REPARSE_APPEXECLINK_BUFFER,*PREPARSE_APPEXECLINK_BUFFER; + static bool check_reparse_point_string (PUNICODE_STRING subst) { @@ -2558,6 +2574,30 @@ check_reparse_point_target (HANDLE h, bool remote, PREPARSE_DATA_BUFFER rp, if (check_reparse_point_string (psymbuf)) return PATH_SYMLINK | PATH_REP; } + else if (!remote && rp->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) + { + /* App execution aliases are commonly used by Windows Store apps. */ + PREPARSE_APPEXECLINK_BUFFER rpl = (PREPARSE_APPEXECLINK_BUFFER) rp; + WCHAR *buf = rpl->AppExecLinkReparseBuffer.Strings; + DWORD size = rp->ReparseDataLength / sizeof (WCHAR), n; + + /* It seems that app execution aliases have a payload of four + NUL-separated wide string: package id, entry point, executable + and application type. We're interested in the executable. */ + for (int i = 0; i < 3 && size > 0; i++) + { + n = wcsnlen (buf, size - 1); + if (i == 2 && n > 0 && n < size) + { + RtlInitCountedUnicodeString (psymbuf, buf, n * sizeof (WCHAR)); + return PATH_SYMLINK | PATH_REP; + } + if (i == 2) + break; + buf += n + 1; + size -= n + 1; + } + } else if (rp->ReparseTag == IO_REPARSE_TAG_LX_SYMLINK) { /* WSL symlink. Problem: We have to convert the path to UTF-16 for