Skip to content

gh-100107: Make Py launcher ignore app aliases that launch Microsoft Store #114358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 25, 2024
Original file line number Diff line number Diff line change
@@ -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
69 changes: 69 additions & 0 deletions PC/launcher2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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) &&
Expand Down