Mitigate need for vfs cores on ntfs drives [UWP/XBOX] (#13368)

* make check for standard io by access rather than the just assuming based on path string

* add code to auto permissions so files can be accessed by non vfs cores
(no exfat or fat32 support yet)

* remove commit from macro because apparently it causes issues

Co-authored-by: Tunip3 <tunip3@users.noreply.github.com>
This commit is contained in:
tunip3 2021-12-17 12:46:04 +00:00 committed by GitHub
parent cd50a51f3e
commit 6c123dd078
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 235 additions and 53 deletions

View File

@ -1369,13 +1369,8 @@ void fill_pathname_home_dir(char *s, size_t len)
bool is_path_accessible_using_standard_io(const char *path)
{
#ifdef __WINRT__
char relative_path_abbrev[PATH_MAX_LENGTH];
fill_pathname_abbreviate_special(relative_path_abbrev,
path, sizeof(relative_path_abbrev));
return (strlen(relative_path_abbrev) >= 2 )
&& ( relative_path_abbrev[0] == ':'
|| relative_path_abbrev[0] == '~')
&& PATH_CHAR_IS_SLASH(relative_path_abbrev[1]);
DWORD trygetattrbs = GetFileAttributesA(path);
return trygetattrbs != INVALID_FILE_ATTRIBUTES;
#else
return true;
#endif

View File

@ -71,6 +71,12 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *dirstream);
int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *dirstream);
#ifdef __WINRT__
void uwp_set_acl(const wchar_t* path, const wchar_t* AccessString);
#endif
RETRO_END_DECLS
#endif

View File

@ -32,6 +32,7 @@
#include <functional>
#include <fileapifromapp.h>
#include <AclAPI.h>
#include <sddl.h>
#include <io.h>
#include <fcntl.h>
@ -489,10 +490,8 @@ int uwp_copy_acl(const wchar_t* source, const wchar_t* target)
LocalFree(sidOwnerDescriptor);
LocalFree(sidGroupDescriptor);
LocalFree(daclDescriptor);
CloseHandle(original_file);
return result;
}
CloseHandle(original_file);
}
else
{
@ -902,3 +901,73 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir* rdir)
free(rdir);
return 0;
}
void uwp_set_acl(const wchar_t* path, const wchar_t* AccessString)
{
PSECURITY_DESCRIPTOR SecurityDescriptor = nullptr;
EXPLICIT_ACCESSW ExplicitAccess = { 0 };
ACL* AccessControlCurrent = nullptr;
ACL* AccessControlNew = nullptr;
SECURITY_INFORMATION SecurityInfo = DACL_SECURITY_INFORMATION;
PSID SecurityIdentifier = nullptr;
HANDLE original_file = CreateFileFromAppW(path, GENERIC_READ | GENERIC_WRITE | WRITE_DAC, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (original_file != INVALID_HANDLE_VALUE) {
if (
GetSecurityInfo(
original_file,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
nullptr,
nullptr,
&AccessControlCurrent,
nullptr,
&SecurityDescriptor
) == ERROR_SUCCESS
)
{
ConvertStringSidToSidW(AccessString, &SecurityIdentifier);
if (SecurityIdentifier != nullptr)
{
ExplicitAccess.grfAccessPermissions = GENERIC_READ | GENERIC_EXECUTE | GENERIC_WRITE;
ExplicitAccess.grfAccessMode = SET_ACCESS;
ExplicitAccess.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ExplicitAccess.Trustee.ptstrName = reinterpret_cast<wchar_t*>(SecurityIdentifier);
if (
SetEntriesInAclW(
1,
&ExplicitAccess,
AccessControlCurrent,
&AccessControlNew
) == ERROR_SUCCESS
)
{
SetSecurityInfo(
original_file,
SE_FILE_OBJECT,
SecurityInfo,
nullptr,
nullptr,
AccessControlNew,
nullptr
);
}
}
}
if (SecurityDescriptor)
{
LocalFree(reinterpret_cast<HLOCAL>(SecurityDescriptor));
}
if (AccessControlNew)
{
LocalFree(reinterpret_cast<HLOCAL>(AccessControlNew));
}
CloseHandle(original_file);
}
}

View File

@ -228,11 +228,10 @@
<PropertyGroup>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<AppxBundlePlatforms>x86|x64|arm|arm64</AppxBundlePlatforms>
<AppInstallerUpdateFrequency>1</AppInstallerUpdateFrequency>
<AppxBundlePlatforms>x64</AppxBundlePlatforms>
<AppInstallerUpdateFrequency>0</AppInstallerUpdateFrequency>
<AppInstallerCheckForUpdateFrequency>OnApplicationRun</AppInstallerCheckForUpdateFrequency>
<AppxBundle>Always</AppxBundle>
<PackageCertificateThumbprint>261A18AB51F9C1DC1956AF9084285F82A2A7FD30</PackageCertificateThumbprint>
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
<GenerateTestArtifacts>True</GenerateTestArtifacts>
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
@ -632,4 +631,4 @@
<Import Project="$(VSINSTALLDIR)\Common7\IDE\Extensions\Microsoft\VsGraphics\MeshContentTask.targets" />
<Import Project="$(VSINSTALLDIR)\Common7\IDE\Extensions\Microsoft\VsGraphics\ShaderGraphContentTask.targets" />
</ImportGroup>
</Project>
</Project>

View File

@ -30,6 +30,110 @@
<None Include="ANGLE\$(Platform)\*.dll" />
<None Include="ANGLE\$(Platform)\*.dll" />
<None Include="ANGLE\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\cores\*.dll" />
<None Include="cores\$(Platform)\cores\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
<None Include="cores\$(Platform)\*.dll" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\uwp\uwp_func.h">

View File

@ -1047,54 +1047,63 @@ static bool content_file_load(
if (!system->supports_vfs &&
!is_path_accessible_using_standard_io(content_path))
{
/* Fallback to a file copy into an accessible directory */
char new_basedir[PATH_MAX_LENGTH];
char new_path[PATH_MAX_LENGTH];
new_path[0] = '\0';
new_basedir[0] = '\0';
RARCH_LOG("[Content]: Core does not support VFS"
" - copying to cache directory.\n");
if (!string_is_empty(content_ctx->directory_cache))
strlcpy(new_basedir, content_ctx->directory_cache,
sizeof(new_basedir));
if (string_is_empty(new_basedir) ||
!path_is_directory(new_basedir) ||
!is_path_accessible_using_standard_io(new_basedir))
{
RARCH_WARN("[Content]: Tried copying to cache directory, "
"but cache directory was not set or found. "
"Setting cache directory to root of writable app directory...\n");
strlcpy(new_basedir, uwp_dir_data, sizeof(new_basedir));
}
fill_pathname_join(new_path, new_basedir,
path_basename(content_path), sizeof(new_path));
/* Try copy acl to file first, if successfull this should mean that cores using standard io can still access them
* it would be better to set the acl to allow full access for all application packages however this is substantially easier than writing out new functions to do this
* Copy acl from localstate*/
// I am genuinely really proud of these work arounds
wchar_t wcontent_path[MAX_PATH];
mbstowcs(wcontent_path, content_path, MAX_PATH);
wchar_t wnew_path[MAX_PATH];
mbstowcs(wnew_path, new_path, MAX_PATH);
/* TODO: This may fail on very large files...
* but copying large files is not a good idea anyway
* (This disclaimer is out dated but I don't want to remove it)*/
if (!CopyFileFromAppW(wcontent_path,wnew_path,false))
wchar_t wuwp_dir_data[MAX_PATH];
mbstowcs(wuwp_dir_data, uwp_dir_data, MAX_PATH);
uwp_set_acl(wcontent_path, L"S-1-15-2-1");
if (!is_path_accessible_using_standard_io(content_path))
{
int err = GetLastError();
snprintf(msg, sizeof(msg), "%s \"%s\". (during copy read or write)\n",
/* Fallback to a file copy into an accessible directory */
char new_basedir[PATH_MAX_LENGTH];
char new_path[PATH_MAX_LENGTH];
new_path[0] = '\0';
new_basedir[0] = '\0';
RARCH_LOG("[Content]: Core does not support VFS"
" - copying to cache directory.\n");
if (!string_is_empty(content_ctx->directory_cache))
strlcpy(new_basedir, content_ctx->directory_cache,
sizeof(new_basedir));
if (string_is_empty(new_basedir) ||
!path_is_directory(new_basedir) ||
!is_path_accessible_using_standard_io(new_basedir))
{
RARCH_WARN("[Content]: Tried copying to cache directory, "
"but cache directory was not set or found. "
"Setting cache directory to root of writable app directory...\n");
strlcpy(new_basedir, uwp_dir_data, sizeof(new_basedir));
}
fill_pathname_join(new_path, new_basedir,
path_basename(content_path), sizeof(new_path));
wchar_t wnew_path[MAX_PATH];
mbstowcs(wnew_path, new_path, MAX_PATH);
/* TODO: This may fail on very large files...
* but copying large files is not a good idea anyway
* (This disclaimer is out dated but I don't want to remove it)*/
if (!CopyFileFromAppW(wcontent_path, wnew_path, false))
{
int err = GetLastError();
snprintf(msg, sizeof(msg), "%s \"%s\". (during copy read or write)\n",
msg_hash_to_str(MSG_COULD_NOT_READ_CONTENT_FILE),
content_path);
*error_string = strdup(msg);
return false;
}
*error_string = strdup(msg);
return false;
}
content_path = content_file_list_append_temporary(
content_path = content_file_list_append_temporary(
p_content->content_list, new_path);
used_vfs_fallback_copy = true;
used_vfs_fallback_copy = true;
}
}
#endif
RARCH_LOG("[Content]: %s\n", msg_hash_to_str(