@@ -572,6 +572,21 @@ findArgv0End(const wchar_t *buffer, int bufferLength)
572572 *** COMMAND-LINE PARSING ***
573573\******************************************************************************/
574574
575+ // Adapted from https://stackoverflow.com/a/65583702
576+ typedef struct AppExecLinkFile { // For tag IO_REPARSE_TAG_APPEXECLINK
577+ DWORD reparseTag ;
578+ WORD reparseDataLength ;
579+ WORD reserved ;
580+ ULONG version ;
581+ wchar_t stringList [MAX_PATH * 4 ]; // Multistring (Consecutive UTF-16 strings each ending with a NUL)
582+ /* There are normally 4 strings here. Ex:
583+ Package ID: L"Microsoft.DesktopAppInstaller_8wekyb3d8bbwe"
584+ Entry Point: L"Microsoft.DesktopAppInstaller_8wekyb3d8bbwe!PythonRedirector"
585+ Executable: L"C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_1.17.106910_x64__8wekyb3d8bbwe\AppInstallerPythonRedirector.exe"
586+ Applic. Type: L"0" // Integer as ASCII. "0" = Desktop bridge application; Else sandboxed UWP application
587+ */
588+ } AppExecLinkFile ;
589+
575590
576591int
577592parseCommandLine (SearchInfo * search )
@@ -763,6 +778,55 @@ _shebangStartsWith(const wchar_t *buffer, int bufferLength, const wchar_t *prefi
763778}
764779
765780
781+ int
782+ ensure_no_redirector_stub (wchar_t * filename , wchar_t * buffer )
783+ {
784+ // Make sure we didn't find a reparse point that will open the Microsoft Store
785+ // If we did, pretend there was no shebang and let normal handling take over
786+ WIN32_FIND_DATAW findData ;
787+ HANDLE hFind = FindFirstFileW (buffer , & findData );
788+ if (!hFind ) {
789+ // Let normal handling take over
790+ debug (L"# Did not find %s on PATH\n" , filename );
791+ return RC_NO_SHEBANG ;
792+ }
793+
794+ FindClose (hFind );
795+
796+ if (!(findData .dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
797+ findData .dwReserved0 & IO_REPARSE_TAG_APPEXECLINK )) {
798+ return 0 ;
799+ }
800+
801+ HANDLE hReparsePoint = CreateFileW (buffer , 0 , FILE_SHARE_READ , NULL , OPEN_EXISTING , FILE_FLAG_OPEN_REPARSE_POINT , NULL );
802+ if (!hReparsePoint ) {
803+ // Let normal handling take over
804+ debug (L"# Did not find %s on PATH\n" , filename );
805+ return RC_NO_SHEBANG ;
806+ }
807+
808+ AppExecLinkFile appExecLink ;
809+
810+ if (!DeviceIoControl (hReparsePoint , FSCTL_GET_REPARSE_POINT , NULL , 0 , & appExecLink , sizeof (appExecLink ), NULL , NULL )) {
811+ // Let normal handling take over
812+ debug (L"# Did not find %s on PATH\n" , filename );
813+ CloseHandle (hReparsePoint );
814+ return RC_NO_SHEBANG ;
815+ }
816+
817+ CloseHandle (hReparsePoint );
818+
819+ const wchar_t * redirectorPackageId = L"Microsoft.DesktopAppInstaller_8wekyb3d8bbwe" ;
820+
821+ if (0 == wcscmp (appExecLink .stringList , redirectorPackageId )) {
822+ debug (L"# ignoring redirector that would launch store\n" );
823+ return RC_NO_SHEBANG ;
824+ }
825+
826+ return 0 ;
827+ }
828+
829+
766830int
767831searchPath (SearchInfo * search , const wchar_t * shebang , int shebangLength )
768832{
@@ -826,6 +890,11 @@ searchPath(SearchInfo *search, const wchar_t *shebang, int shebangLength)
826890 return RC_BAD_VIRTUAL_PATH ;
827891 }
828892
893+ int result = ensure_no_redirector_stub (filename , buffer );
894+ if (result ) {
895+ return result ;
896+ }
897+
829898 // Check that we aren't going to call ourselves again
830899 // If we are, pretend there was no shebang and let normal handling take over
831900 if (GetModuleFileNameW (NULL , filename , MAXLEN ) &&
0 commit comments