public inbox for cygwin-cvs@sourceware.org help / color / mirror / Atom feed
From: Corinna Vinschen <corinna@sourceware.org> To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: Treat Windows Store's "app execution aliases" as symbolic links Date: Tue, 23 Mar 2021 15:58:51 +0000 (GMT) [thread overview] Message-ID: <20210323155851.E6912385BF9E@sourceware.org> (raw) https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=0631c6644e6398c051dcda1a53c0fc0e40c814a3 commit 0631c6644e6398c051dcda1a53c0fc0e40c814a3 Author: Johannes Schindelin <johannes.schindelin@gmx.de> Date: Mon Mar 22 16:51:41 2021 +0100 Cygwin: Treat Windows Store's "app execution aliases" as symbolic links When the Windows Store version of Python is installed, so-called "app execution aliases" are put into the `PATH`. These are reparse points under the hood, with an undocumented format. We do know a bit about this format, though, as per the excellent analysis: https://www.tiraniddo.dev/2019/09/overview-of-windows-execution-aliases.html The first 4 bytes is the reparse tag, in this case it's 0x8000001B which is documented in the Windows SDK as IO_REPARSE_TAG_APPEXECLINK. Unfortunately there doesn't seem to be a corresponding structure, but with a bit of reverse engineering we can work out the format is as follows: Version: <4 byte integer> Package ID: <NUL Terminated Unicode String> Entry Point: <NUL Terminated Unicode String> Executable: <NUL Terminated Unicode String> Application Type: <NUL Terminated Unicode String> Let's treat them as symbolic links. For example, in this developer's setup, this will result in the following nice output: $ cd $LOCALAPPDATA/Microsoft/WindowsApps/ $ ls -l python3.exe lrwxrwxrwx 1 me 4096 105 Aug 23 2020 python3.exe -> '/c/Program Files/WindowsApps/PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0/python.exe' Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Diff: --- winsup/cygwin/path.cc | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) 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
reply other threads:[~2021-03-23 15:58 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210323155851.E6912385BF9E@sourceware.org \ --to=corinna@sourceware.org \ --cc=cygwin-cvs@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).