diff --git a/libretro-common/file/file_path.c b/libretro-common/file/file_path.c index f3e32b9bf1..a12be47ab2 100644 --- a/libretro-common/file/file_path.c +++ b/libretro-common/file/file_path.c @@ -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 diff --git a/libretro-common/include/vfs/vfs_implementation.h b/libretro-common/include/vfs/vfs_implementation.h index c7d6bb0330..b88d2f3d2b 100644 --- a/libretro-common/include/vfs/vfs_implementation.h +++ b/libretro-common/include/vfs/vfs_implementation.h @@ -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 diff --git a/libretro-common/vfs/vfs_implementation_uwp.cpp b/libretro-common/vfs/vfs_implementation_uwp.cpp index dac09ddf62..969f454fb1 100644 --- a/libretro-common/vfs/vfs_implementation_uwp.cpp +++ b/libretro-common/vfs/vfs_implementation_uwp.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -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(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(SecurityDescriptor)); + } + if (AccessControlNew) + { + LocalFree(reinterpret_cast(AccessControlNew)); + } + CloseHandle(original_file); + } +} diff --git a/pkg/msvc-uwp/RetroArch-msvc2019-UWP/RetroArch-msvc2019-UWP.vcxproj b/pkg/msvc-uwp/RetroArch-msvc2019-UWP/RetroArch-msvc2019-UWP.vcxproj index 1b50c3b889..5b2f461480 100755 --- a/pkg/msvc-uwp/RetroArch-msvc2019-UWP/RetroArch-msvc2019-UWP.vcxproj +++ b/pkg/msvc-uwp/RetroArch-msvc2019-UWP/RetroArch-msvc2019-UWP.vcxproj @@ -228,11 +228,10 @@ False False - x86|x64|arm|arm64 - 1 + x64 + 0 OnApplicationRun Always - 261A18AB51F9C1DC1956AF9084285F82A2A7FD30 SHA256 True 0 @@ -632,4 +631,4 @@ - + \ No newline at end of file diff --git a/pkg/msvc-uwp/RetroArch-msvc2019-UWP/RetroArch-msvc2019-UWP.vcxproj.filters b/pkg/msvc-uwp/RetroArch-msvc2019-UWP/RetroArch-msvc2019-UWP.vcxproj.filters index 5588895a04..48a2c09ed1 100755 --- a/pkg/msvc-uwp/RetroArch-msvc2019-UWP/RetroArch-msvc2019-UWP.vcxproj.filters +++ b/pkg/msvc-uwp/RetroArch-msvc2019-UWP/RetroArch-msvc2019-UWP.vcxproj.filters @@ -30,6 +30,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tasks/task_content.c b/tasks/task_content.c index 2c1f8c4900..9573560bff 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -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(