aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-05-27 08:35:59 +0100
committerRon Yorston <rmy@pobox.com>2023-05-27 08:35:59 +0100
commit603af9bb92af6bc429d880df71618e96820967c5 (patch)
tree7100a2f8d93e7d133329906c2f0658c9cf5be171
parent5adeafb91fe5d0fbfd2e4f773e64da9aa13d2f09 (diff)
downloadbusybox-w32-603af9bb92af6bc429d880df71618e96820967c5.tar.gz
busybox-w32-603af9bb92af6bc429d880df71618e96820967c5.tar.bz2
busybox-w32-603af9bb92af6bc429d880df71618e96820967c5.zip
win32: support "app exec link" reparse points
Reparse points with the tag IO_REPARSE_TAG_APPEXECLINK are present in ~/AppData/Local/Microsoft/WindowsApps in Windows 10 and 11. They are: Used by Universal Windows Platform (UWP) packages to encode information that allows the application to be launched by CreateProcess. Modify readlink(2) and lsattr(1) to treat them as symbolic links, in much the same way as was done previously for junctions. They aren't really symbolic links but they're similar. Costs 128-160 bytes. (GitHub issue #327)
-rw-r--r--e2fsprogs/e2fs_lib.c6
-rw-r--r--e2fsprogs/lsattr.c1
-rw-r--r--win32/mingw.c37
3 files changed, 43 insertions, 1 deletions
diff --git a/e2fsprogs/e2fs_lib.c b/e2fsprogs/e2fs_lib.c
index 031f5e06b..4a4db1a13 100644
--- a/e2fsprogs/e2fs_lib.c
+++ b/e2fsprogs/e2fs_lib.c
@@ -135,6 +135,9 @@ void print_e2flags_long(struct stat *sb)
135 case IO_REPARSE_TAG_MOUNT_POINT: 135 case IO_REPARSE_TAG_MOUNT_POINT:
136 ln = "Junction"; 136 ln = "Junction";
137 break; 137 break;
138 case IO_REPARSE_TAG_APPEXECLINK:
139 ln = "App_Exec_Link";
140 break;
138 } 141 }
139 } 142 }
140 fputs(ln, stdout); 143 fputs(ln, stdout);
@@ -174,6 +177,9 @@ void print_e2flags(struct stat *sb)
174 case IO_REPARSE_TAG_MOUNT_POINT: 177 case IO_REPARSE_TAG_MOUNT_POINT:
175 c = 'j'; 178 c = 'j';
176 break; 179 break;
180 case IO_REPARSE_TAG_APPEXECLINK:
181 c = 'A';
182 break;
177 } 183 }
178 } 184 }
179#endif 185#endif
diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c
index a6c4a27e9..87fdb78b3 100644
--- a/e2fsprogs/lsattr.c
+++ b/e2fsprogs/lsattr.c
@@ -47,6 +47,7 @@
47//usage: "\n\nAttributes:\n" 47//usage: "\n\nAttributes:\n"
48//usage: "\n j Junction" 48//usage: "\n j Junction"
49//usage: "\n l Symbolic link" 49//usage: "\n l Symbolic link"
50//usage: "\n A App exec link"
50//usage: "\n R Reparse point" 51//usage: "\n R Reparse point"
51//usage: "\n o Offline" 52//usage: "\n o Offline"
52//usage: "\n e Encrypted" 53//usage: "\n e Encrypted"
diff --git a/win32/mingw.c b/win32/mingw.c
index 9e1cf5eea..be4fc7aa1 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -593,6 +593,7 @@ static DWORD get_symlink_data(DWORD attr, const char *pathname,
593 switch (fbuf->dwReserved0) { 593 switch (fbuf->dwReserved0) {
594 case IO_REPARSE_TAG_SYMLINK: 594 case IO_REPARSE_TAG_SYMLINK:
595 case IO_REPARSE_TAG_MOUNT_POINT: 595 case IO_REPARSE_TAG_MOUNT_POINT:
596 case IO_REPARSE_TAG_APPEXECLINK:
596 return fbuf->dwReserved0; 597 return fbuf->dwReserved0;
597 } 598 }
598 } 599 }
@@ -1602,6 +1603,23 @@ static wchar_t *normalize_ntpath(wchar_t *wbuf)
1602 return wbuf; 1603 return wbuf;
1603} 1604}
1604 1605
1606/*
1607 * This is the stucture required for reparse points with the tag
1608 * IO_REPARSE_TAG_APPEXECLINK. The Buffer member contains four
1609 * NUL-terminated, concatentated strings:
1610 *
1611 * package id, entry point, executable path and application type.
1612 *
1613 * https://www.tiraniddo.dev/2019/09/overview-of-windows-execution-aliases.html
1614 */
1615typedef struct {
1616 DWORD ReparseTag;
1617 USHORT ReparseDataLength;
1618 USHORT Reserved;
1619 ULONG Version;
1620 WCHAR Buffer[1];
1621} APPEXECLINK_BUFFER;
1622
1605#define SRPB rptr->SymbolicLinkReparseBuffer 1623#define SRPB rptr->SymbolicLinkReparseBuffer
1606ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) 1624ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)
1607{ 1625{
@@ -1613,9 +1631,11 @@ ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)
1613 DWORD nbytes; 1631 DWORD nbytes;
1614 BYTE rbuf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; 1632 BYTE rbuf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1615 PREPARSE_DATA_BUFFER rptr = (PREPARSE_DATA_BUFFER)rbuf; 1633 PREPARSE_DATA_BUFFER rptr = (PREPARSE_DATA_BUFFER)rbuf;
1634 APPEXECLINK_BUFFER *aptr = (APPEXECLINK_BUFFER *)rptr;
1616 BOOL status; 1635 BOOL status;
1617 size_t len; 1636 size_t len;
1618 WCHAR *name = NULL; 1637 WCHAR *name = NULL, *str[4], *s;
1638 int i;
1619 1639
1620 status = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, 1640 status = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0,
1621 rptr, sizeof(rbuf), &nbytes, NULL); 1641 rptr, sizeof(rbuf), &nbytes, NULL);
@@ -1627,6 +1647,21 @@ ssize_t readlink(const char *pathname, char *buf, size_t bufsiz)
1627 } else if (status && rptr->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { 1647 } else if (status && rptr->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
1628 len = MRPB.SubstituteNameLength/sizeof(WCHAR); 1648 len = MRPB.SubstituteNameLength/sizeof(WCHAR);
1629 name = MRPB.PathBuffer + MRPB.SubstituteNameOffset/sizeof(WCHAR); 1649 name = MRPB.PathBuffer + MRPB.SubstituteNameOffset/sizeof(WCHAR);
1650 } else if (status && rptr->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) {
1651 // We only need the executable path but we determine all of
1652 // the strings as a sanity check.
1653 i = 0;
1654 s = aptr->Buffer;
1655 do {
1656 str[i] = s;
1657 while (*s++)
1658 ;
1659 } while (++i < 4);
1660
1661 if (s - aptr->Buffer < MAXIMUM_REPARSE_DATA_BUFFER_SIZE) {
1662 len = wcslen(str[2]);
1663 name = str[2];
1664 }
1630 } 1665 }
1631 1666
1632 if (name) { 1667 if (name) {