mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-27 02:00:41 +00:00
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:
parent
cd50a51f3e
commit
6c123dd078
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
@ -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">
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user