From e0cb900abe61a630fd5b099a64b88442e851d796 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 7 Apr 2019 21:22:20 +0200 Subject: [PATCH] (UWP VFS) Cleanups --- .../vfs/vfs_implementation_uwp.cpp | 121 +++++++++--------- 1 file changed, 64 insertions(+), 57 deletions(-) diff --git a/libretro-common/vfs/vfs_implementation_uwp.cpp b/libretro-common/vfs/vfs_implementation_uwp.cpp index 9487840659..2febfba933 100644 --- a/libretro-common/vfs/vfs_implementation_uwp.cpp +++ b/libretro-common/vfs/vfs_implementation_uwp.cpp @@ -55,69 +55,63 @@ using namespace Windows::Storage::FileProperties; namespace { - /* Dear Microsoft - * I really appreciate all the effort you took to not provide any - * synchronous file APIs and block all attempts to synchronously - * wait for the results of async tasks for "smooth user experience", - * but I'm not going to run and rewrite all RetroArch cores for - * async I/O. I hope you like this hack I made instead. - */ template - T RunAsync(std::function()> func) - { - volatile bool finished = false; - volatile Platform::Exception^ exception = nullptr; - volatile T result; - func().then([&finished, &exception, &result](concurrency::task t) { - try - { - result = t.get(); - } - catch (Platform::Exception^ exception_) - { - exception = exception_; - } - finished = true; - }); - - /* Don't stall the UI thread - prevents a deadlock */ - Windows::UI::Core::CoreWindow^ corewindow = Windows::UI::Core::CoreWindow::GetForCurrentThread(); - while (!finished) - { - if (corewindow) - corewindow->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent); - } - - if (exception != nullptr) - throw exception; - return result; - } - - template - T RunAsyncAndCatchErrors(std::function()> func, T valueOnError) + static T RunAsyncAndCatchErrors(std::function()> func, T valueOnError) { try { - return RunAsync(func); + /* Dear Microsoft + * I really appreciate all the effort you took to not provide any + * synchronous file APIs and block all attempts to synchronously + * wait for the results of async tasks for "smooth user experience", + * but I'm not going to run and rewrite all RetroArch cores for + * async I/O. I hope you like this hack I made instead. + */ + volatile bool finished = false; + volatile Platform::Exception^ exception = nullptr; + volatile T result; + func().then([&finished, &exception, &result](concurrency::task t) { + try + { + result = t.get(); + } + catch (Platform::Exception^ exception_) + { + exception = exception_; + } + finished = true; + }); + + /* Don't stall the UI thread - prevents a deadlock */ + Windows::UI::Core::CoreWindow^ corewindow = Windows::UI::Core::CoreWindow::GetForCurrentThread(); + while (!finished) + { + if (corewindow) + corewindow->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent); + } + + if (exception != nullptr) + throw exception; + return result; } catch (Platform::Exception^ e) { return valueOnError; } } +} - void windowsize_path(wchar_t* path) +static void windowsize_path(wchar_t* path) +{ + /* UWP deals with paths containing / instead of \ way worse than normal Windows */ + /* and RetroArch may sometimes mix them (e.g. on archive extraction) */ + if (!path) + return; + while (*path) { - /* UWP deals with paths containing / instead of \ way worse than normal Windows */ - /* and RetroArch may sometimes mix them (e.g. on archive extraction) */ - if (!path) - return; - while (*path) - { - if (*path == '/') - *path = '\\'; - ++path; - } + if (*path == '/') + *path = '\\'; + ++path; } } @@ -166,7 +160,7 @@ namespace /* A list of all StorageFolder objects returned using from the file picker */ Platform::Collections::Vector accessible_directories; - concurrency::task TriggerPickerAddDialog() + static concurrency::task TriggerPickerAddDialog() { auto folderPicker = ref new Windows::Storage::Pickers::FolderPicker(); folderPicker->SuggestedStartLocation = Windows::Storage::Pickers::PickerLocationId::Desktop; @@ -183,7 +177,7 @@ namespace } template - concurrency::task LocateStorageItem(Platform::String^ path) + static concurrency::task LocateStorageItem(Platform::String^ path) { /* Look for a matching directory we can use */ for each (StorageFolder^ folder in accessible_directories) @@ -231,7 +225,7 @@ namespace }); } - IStorageItem^ LocateStorageFileOrFolder(Platform::String^ path) + static IStorageItem^ LocateStorageFileOrFolder(Platform::String^ path) { if (!path || path->IsEmpty()) return nullptr; @@ -273,6 +267,8 @@ struct libretro_vfs_implementation_file libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints) { + char *dirpath = NULL; + wchar_t *dirpath_wide = NULL; if (!path || !*path) return NULL; @@ -288,9 +284,14 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns return NULL; } - char* dirpath = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + dirpath = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); + + if (!dirpath) + return NULL; + fill_pathname_basedir(dirpath, path, PATH_MAX_LENGTH); - wchar_t *dirpath_wide = utf8_to_utf16_string_alloc(dirpath); + + dirpath_wide = utf8_to_utf16_string_alloc(dirpath); windowsize_path(dirpath_wide); Platform::String^ dirpath_str = ref new Platform::String(dirpath_wide); free(dirpath_wide); @@ -570,11 +571,17 @@ const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *strea int retro_vfs_stat_impl(const char *path, int32_t *size) { + wchar_t *path_wide = NULL; if (!path || !*path) return 0; - wchar_t *path_wide = utf8_to_utf16_string_alloc(path); + path_wide = utf8_to_utf16_string_alloc(path); + + if (!path_wide) + return 0; + windowsize_path(path_wide); + Platform::String^ path_str = ref new Platform::String(path_wide); free(path_wide);