gh-100107: Make py.exe launcher ignore app aliases that launch Microsoft Store (GH-114358)

This commit is contained in:
Vincent Cunningham 2024-01-24 16:23:28 -08:00 committed by GitHub
parent 6888cccac0
commit d5c21c12c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 70 additions and 0 deletions

View File

@ -0,0 +1 @@
The ``py.exe`` launcher will no longer attempt to run the Microsoft Store redirector when launching a script containing a ``/usr/bin/env`` shebang

View File

@ -572,6 +572,21 @@ findArgv0End(const wchar_t *buffer, int bufferLength)
*** COMMAND-LINE PARSING ***
\******************************************************************************/
// Adapted from https://stackoverflow.com/a/65583702
typedef struct AppExecLinkFile { // For tag IO_REPARSE_TAG_APPEXECLINK
DWORD reparseTag;
WORD reparseDataLength;
WORD reserved;
ULONG version;
wchar_t stringList[MAX_PATH * 4]; // Multistring (Consecutive UTF-16 strings each ending with a NUL)
/* There are normally 4 strings here. Ex:
Package ID: L"Microsoft.DesktopAppInstaller_8wekyb3d8bbwe"
Entry Point: L"Microsoft.DesktopAppInstaller_8wekyb3d8bbwe!PythonRedirector"
Executable: L"C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_1.17.106910_x64__8wekyb3d8bbwe\AppInstallerPythonRedirector.exe"
Applic. Type: L"0" // Integer as ASCII. "0" = Desktop bridge application; Else sandboxed UWP application
*/
} AppExecLinkFile;
int
parseCommandLine(SearchInfo *search)
@ -763,6 +778,55 @@ _shebangStartsWith(const wchar_t *buffer, int bufferLength, const wchar_t *prefi
}
int
ensure_no_redirector_stub(wchar_t* filename, wchar_t* buffer)
{
// Make sure we didn't find a reparse point that will open the Microsoft Store
// If we did, pretend there was no shebang and let normal handling take over
WIN32_FIND_DATAW findData;
HANDLE hFind = FindFirstFileW(buffer, &findData);
if (!hFind) {
// Let normal handling take over
debug(L"# Did not find %s on PATH\n", filename);
return RC_NO_SHEBANG;
}
FindClose(hFind);
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
findData.dwReserved0 & IO_REPARSE_TAG_APPEXECLINK)) {
return 0;
}
HANDLE hReparsePoint = CreateFileW(buffer, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (!hReparsePoint) {
// Let normal handling take over
debug(L"# Did not find %s on PATH\n", filename);
return RC_NO_SHEBANG;
}
AppExecLinkFile appExecLink;
if (!DeviceIoControl(hReparsePoint, FSCTL_GET_REPARSE_POINT, NULL, 0, &appExecLink, sizeof(appExecLink), NULL, NULL)) {
// Let normal handling take over
debug(L"# Did not find %s on PATH\n", filename);
CloseHandle(hReparsePoint);
return RC_NO_SHEBANG;
}
CloseHandle(hReparsePoint);
const wchar_t* redirectorPackageId = L"Microsoft.DesktopAppInstaller_8wekyb3d8bbwe";
if (0 == wcscmp(appExecLink.stringList, redirectorPackageId)) {
debug(L"# ignoring redirector that would launch store\n");
return RC_NO_SHEBANG;
}
return 0;
}
int
searchPath(SearchInfo *search, const wchar_t *shebang, int shebangLength)
{
@ -826,6 +890,11 @@ searchPath(SearchInfo *search, const wchar_t *shebang, int shebangLength)
return RC_BAD_VIRTUAL_PATH;
}
int result = ensure_no_redirector_stub(filename, buffer);
if (result) {
return result;
}
// Check that we aren't going to call ourselves again
// If we are, pretend there was no shebang and let normal handling take over
if (GetModuleFileNameW(NULL, filename, MAXLEN) &&