This commit is contained in:
twinaphex 2020-06-25 14:01:19 +02:00
parent aa48eeb98e
commit e727e85b1d
4 changed files with 216 additions and 157 deletions

View File

@ -87,7 +87,7 @@ dylib_t dylib_load(const char *path)
fill_pathname_abbreviate_special(relative_path_abbrev, path, PATH_MAX_LENGTH * sizeof(char)); fill_pathname_abbreviate_special(relative_path_abbrev, path, PATH_MAX_LENGTH * sizeof(char));
char *relative_path = relative_path_abbrev; char *relative_path = relative_path_abbrev;
if (relative_path[0] != ':' || !path_char_is_slash(relative_path[1])) if (relative_path[0] != ':' || !PATH_CHAR_IS_SLASH(relative_path[1]))
{ {
/* Path to dylib_load is not inside app install directory. /* Path to dylib_load is not inside app install directory.
* Loading will probably fail. */ * Loading will probably fail. */

View File

@ -571,7 +571,7 @@ void path_parent_dir(char *path)
len = strlen(path); len = strlen(path);
if (len && path_char_is_slash(path[len - 1])) if (len && PATH_CHAR_IS_SLASH(path[len - 1]))
{ {
bool path_was_absolute = path_is_absolute(path); bool path_was_absolute = path_is_absolute(path);
@ -1004,7 +1004,7 @@ void fill_pathname_expand_special(char *out_path,
out_path += src_size; out_path += src_size;
size -= src_size; size -= src_size;
if (!path_char_is_slash(out_path[-1])) if (!PATH_CHAR_IS_SLASH(out_path[-1]))
{ {
src_size = strlcpy(out_path, PATH_DEFAULT_SLASH(), size); src_size = strlcpy(out_path, PATH_DEFAULT_SLASH(), size);
retro_assert(src_size < size); retro_assert(src_size < size);
@ -1035,7 +1035,7 @@ void fill_pathname_expand_special(char *out_path,
out_path += src_size; out_path += src_size;
size -= src_size; size -= src_size;
if (!path_char_is_slash(out_path[-1])) if (!PATH_CHAR_IS_SLASH(out_path[-1]))
{ {
src_size = strlcpy(out_path, PATH_DEFAULT_SLASH(), size); src_size = strlcpy(out_path, PATH_DEFAULT_SLASH(), size);
retro_assert(src_size < size); retro_assert(src_size < size);
@ -1098,7 +1098,7 @@ void fill_pathname_abbreviate_special(char *out_path,
size -= src_size; size -= src_size;
in_path += strlen(candidates[i]); in_path += strlen(candidates[i]);
if (!path_char_is_slash(*in_path)) if (!PATH_CHAR_IS_SLASH(*in_path))
{ {
retro_assert(strlcpy(out_path, retro_assert(strlcpy(out_path,
PATH_DEFAULT_SLASH(), size) < size); PATH_DEFAULT_SLASH(), size) < size);
@ -1286,7 +1286,9 @@ bool is_path_accessible_using_standard_io(const char *path)
char *relative_path_abbrev = (char*)malloc(path_sizeof); char *relative_path_abbrev = (char*)malloc(path_sizeof);
fill_pathname_abbreviate_special(relative_path_abbrev, path, path_sizeof); fill_pathname_abbreviate_special(relative_path_abbrev, path, path_sizeof);
result = strlen(relative_path_abbrev) >= 2 && (relative_path_abbrev[0] == ':' || relative_path_abbrev[0] == '~') && path_char_is_slash(relative_path_abbrev[1]); result = (strlen(relative_path_abbrev) >= 2 )
&& (relative_path_abbrev[0] == ':' || relative_path_abbrev[0] == '~')
&& PATH_CHAR_IS_SLASH(relative_path_abbrev[1]);
free(relative_path_abbrev); free(relative_path_abbrev);
#endif #endif

View File

@ -460,9 +460,9 @@ void path_basedir_wrapper(char *path);
* Returns: true (1) if character is a slash, otherwise false (0). * Returns: true (1) if character is a slash, otherwise false (0).
*/ */
#ifdef _WIN32 #ifdef _WIN32
#define path_char_is_slash(c) (((c) == '/') || ((c) == '\\')) #define PATH_CHAR_IS_SLASH(c) (((c) == '/') || ((c) == '\\'))
#else #else
#define path_char_is_slash(c) ((c) == '/') #define PATH_CHAR_IS_SLASH(c) ((c) == '/')
#endif #endif
/** /**

View File

@ -59,10 +59,13 @@ namespace
{ {
void windowsize_path(wchar_t* path) void windowsize_path(wchar_t* path)
{ {
/* UWP deals with paths containing / instead of \ way worse than normal Windows */ /* UWP deals with paths containing / instead of
/* and RetroArch may sometimes mix them (e.g. on archive extraction) */ * \ way worse than normal Windows */
/* and RetroArch may sometimes mix them
* (e.g. on archive extraction) */
if (!path) if (!path)
return; return;
while (*path) while (*path)
{ {
if (*path == '/') if (*path == '/')
@ -139,15 +142,21 @@ namespace
/* Look for a matching directory we can use */ /* Look for a matching directory we can use */
for each (StorageFolder^ folder in accessible_directories) for each (StorageFolder^ folder in accessible_directories)
{ {
std::wstring file_path;
std::wstring folder_path = folder->Path->Data(); std::wstring folder_path = folder->Path->Data();
size_t folder_path_size = folder_path.size();
/* Could be C:\ or C:\Users\somebody - remove the trailing slash to unify them */ /* Could be C:\ or C:\Users\somebody - remove the trailing slash to unify them */
if (folder_path[folder_path.size() - 1] == '\\') if (folder_path[folder_path_size - 1] == '\\')
folder_path.erase(folder_path.size() - 1); folder_path.erase(folder_path_size - 1);
std::wstring file_path = path->Data();
file_path = path->Data();
if (file_path.find(folder_path) == 0) if (file_path.find(folder_path) == 0)
{ {
/* Found a match */ /* Found a match */
file_path = file_path.length() > folder_path.length() ? file_path.substr(folder_path.length() + 1) : L""; file_path = file_path.length() > folder_path.length()
? file_path.substr(folder_path.length() + 1)
: L"";
return concurrency::create_task(GetItemInFolderFromPathAsync<T>(folder, ref new Platform::String(file_path.data()))); return concurrency::create_task(GetItemInFolderFromPathAsync<T>(folder, ref new Platform::String(file_path.data())));
} }
} }
@ -226,7 +235,8 @@ public:
{ {
} }
HRESULT __stdcall RuntimeClassInitialize(byte *buffer, uint32_t capacity, uint32_t length) HRESULT __stdcall RuntimeClassInitialize(
byte *buffer, uint32_t capacity, uint32_t length)
{ {
m_buffer = buffer; m_buffer = buffer;
m_capacity = capacity; m_capacity = capacity;
@ -292,33 +302,38 @@ struct libretro_vfs_implementation_file
size_t buffer_fill; size_t buffer_fill;
}; };
libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints) libretro_vfs_implementation_file *retro_vfs_file_open_impl(
const char *path, unsigned mode, unsigned hints)
{ {
char *dirpath, *filename;
wchar_t *dirpath_wide;
wchar_t *filename_wide;
Platform::String^ filename_str;
Platform::String^ dirpath_str;
if (!path || !*path) if (!path || !*path)
return NULL; return NULL;
/* Something tried to access files from current directory.
* This is not allowed on UWP. */
if (!path_is_absolute(path)) if (!path_is_absolute(path))
{
/* Something tried to access files from current directory. This is not allowed on UWP. */
return NULL; return NULL;
}
/* Trying to open a directory as file?! */ /* Trying to open a directory as file?! */
if (path_char_is_slash(path[strlen(path) - 1])) if (PATH_CHAR_IS_SLASH(path[strlen(path) - 1]))
return NULL; return NULL;
char* dirpath = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); dirpath = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
fill_pathname_basedir(dirpath, path, PATH_MAX_LENGTH); 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); windowsize_path(dirpath_wide);
Platform::String^ dirpath_str = ref new Platform::String(dirpath_wide); dirpath_str = ref new Platform::String(dirpath_wide);
free(dirpath_wide); free(dirpath_wide);
free(dirpath); free(dirpath);
char* filename = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); filename = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
fill_pathname_base(filename, path, PATH_MAX_LENGTH); fill_pathname_base(filename, path, PATH_MAX_LENGTH);
wchar_t *filename_wide = utf8_to_utf16_string_alloc(filename); filename_wide = utf8_to_utf16_string_alloc(filename);
Platform::String^ filename_str = ref new Platform::String(filename_wide); filename_str = ref new Platform::String(filename_wide);
free(filename_wide); free(filename_wide);
free(filename); free(filename);
@ -332,7 +347,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns
return dir->CreateFileAsync(filename_str, (mode & RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING) != 0 ? return dir->CreateFileAsync(filename_str, (mode & RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING) != 0 ?
CreationCollisionOption::OpenIfExists : CreationCollisionOption::ReplaceExisting); CreationCollisionOption::OpenIfExists : CreationCollisionOption::ReplaceExisting);
}).then([&](StorageFile^ file) { }).then([&](StorageFile^ file) {
FileAccessMode accessMode = mode == RETRO_VFS_FILE_ACCESS_READ ? FileAccessMode accessMode = (mode == RETRO_VFS_FILE_ACCESS_READ) ?
FileAccessMode::Read : FileAccessMode::ReadWrite; FileAccessMode::Read : FileAccessMode::ReadWrite;
return file->OpenAsync(accessMode); return file->OpenAsync(accessMode);
}).then([&](IRandomAccessStream^ fpstream) { }).then([&](IRandomAccessStream^ fpstream) {
@ -343,7 +358,8 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns
stream->orig_path = strdup(path); stream->orig_path = strdup(path);
stream->fp = fpstream; stream->fp = fpstream;
stream->fp->Seek(0); stream->fp->Seek(0);
// Preallocate a small buffer for manually buffered IO, makes short read faster /* Preallocate a small buffer for manually buffered I/O,
* makes short read faster */
int buf_size = 8 * 1024; int buf_size = 8 * 1024;
stream->buffer = (char*)malloc(buf_size); stream->buffer = (char*)malloc(buf_size);
stream->bufferp = CreateNativeBuffer(stream->buffer, buf_size, 0); stream->bufferp = CreateNativeBuffer(stream->buffer, buf_size, 0);
@ -395,7 +411,9 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream)
return stream->fp->Position - stream->buffer_left; return stream->fp->Position - stream->buffer_left;
} }
int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64_t offset, int seek_position) int64_t retro_vfs_file_seek_impl(
libretro_vfs_implementation_file *stream,
int64_t offset, int seek_position)
{ {
if (!stream || !stream->fp) if (!stream || !stream->fp)
return -1; return -1;
@ -421,23 +439,30 @@ int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64
return 0; return 0;
} }
int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void *s, uint64_t len) int64_t retro_vfs_file_read_impl(
libretro_vfs_implementation_file *stream, void *s, uint64_t len)
{ {
int64_t ret;
int64_t bytes_read = 0;
IBuffer^ buffer;
if (!stream || !stream->fp || !s) if (!stream || !stream->fp || !s)
return -1; return -1;
int64_t bytes_read = 0; if (len <= stream->buffer_size)
{
if (len <= stream->buffer_size) { /* Small read, use manually buffered I/O */
// Small read, use manually buffered IO if (stream->buffer_left < len)
if (stream->buffer_left < len) { {
// Exhaust the buffer /* Exhaust the buffer */
memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], stream->buffer_left); memcpy(s,
&stream->buffer[stream->buffer_fill - stream->buffer_left],
stream->buffer_left);
len -= stream->buffer_left; len -= stream->buffer_left;
bytes_read += stream->buffer_left; bytes_read += stream->buffer_left;
stream->buffer_left = 0; stream->buffer_left = 0;
// Fill buffer /* Fill buffer */
stream->buffer_left = RunAsyncAndCatchErrors<int64_t>([&]() { stream->buffer_left = RunAsyncAndCatchErrors<int64_t>([&]() {
return concurrency::create_task(stream->fp->ReadAsync(stream->bufferp, stream->bufferp->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) { return concurrency::create_task(stream->fp->ReadAsync(stream->bufferp, stream->bufferp->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) {
retro_assert(stream->bufferp == buf); retro_assert(stream->bufferp == buf);
@ -446,15 +471,18 @@ int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void
}, -1); }, -1);
stream->buffer_fill = stream->buffer_left; stream->buffer_fill = stream->buffer_left;
if (stream->buffer_left == -1) { if (stream->buffer_left == -1)
{
stream->buffer_left = 0; stream->buffer_left = 0;
stream->buffer_fill = 0; stream->buffer_fill = 0;
return -1; return -1;
} }
if (stream->buffer_left < len) { if (stream->buffer_left < len)
// EOF {
memcpy(&((char*)s)[bytes_read], stream->buffer, stream->buffer_left); /* EOF */
memcpy(&((char*)s)[bytes_read],
stream->buffer, stream->buffer_left);
bytes_read += stream->buffer_left; bytes_read += stream->buffer_left;
stream->buffer_left = 0; stream->buffer_left = 0;
return bytes_read; return bytes_read;
@ -466,40 +494,43 @@ int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void
return bytes_read; return bytes_read;
} }
// Internal buffer already contains requested amount /* Internal buffer already contains requested amount */
memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], len); memcpy(s,
&stream->buffer[stream->buffer_fill - stream->buffer_left],
len);
stream->buffer_left -= len; stream->buffer_left -= len;
return len; return len;
} }
// Big read exceeding buffer size, exhaust small buffer and read rest in one go /* Big read exceeding buffer size,
* exhaust small buffer and read rest in one go */
memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], stream->buffer_left); memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], stream->buffer_left);
len -= stream->buffer_left; len -= stream->buffer_left;
bytes_read += stream->buffer_left; bytes_read += stream->buffer_left;
stream->buffer_left = 0; stream->buffer_left = 0;
IBuffer^ buffer = CreateNativeBuffer(&((char*)s)[bytes_read], len, 0); buffer = CreateNativeBuffer(&((char*)s)[bytes_read], len, 0);
ret = RunAsyncAndCatchErrors<int64_t>([&]() {
int64_t ret = RunAsyncAndCatchErrors<int64_t>([&]() {
return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity - bytes_read, InputStreamOptions::None)).then([&](IBuffer^ buf) { return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity - bytes_read, InputStreamOptions::None)).then([&](IBuffer^ buf) {
retro_assert(buf == buffer); retro_assert(buf == buffer);
return (int64_t)buffer->Length; return (int64_t)buffer->Length;
}); });
}, -1); }, -1);
if (ret == -1) { if (ret == -1)
return -1; return -1;
}
return bytes_read + ret; return bytes_read + ret;
} }
int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file *stream, const void *s, uint64_t len) int64_t retro_vfs_file_write_impl(
libretro_vfs_implementation_file *stream, const void *s, uint64_t len)
{ {
IBuffer^ buffer;
if (!stream || !stream->fp || !s) if (!stream || !stream->fp || !s)
return -1; return -1;
// const_cast to remove const modifier is undefined behaviour, but the buffer is only read, should be safe /* const_cast to remove const modifier is undefined behaviour, but the buffer is only read, should be safe */
IBuffer^ buffer = CreateNativeBuffer(const_cast<void*>(s), len, len); buffer = CreateNativeBuffer(const_cast<void*>(s), len, len);
return RunAsyncAndCatchErrors<int64_t>([&]() { return RunAsyncAndCatchErrors<int64_t>([&]() {
return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) { return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) {
return (int64_t)written; return (int64_t)written;
@ -523,12 +554,15 @@ int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream)
int retro_vfs_file_remove_impl(const char *path) int retro_vfs_file_remove_impl(const char *path)
{ {
wchar_t *path_wide;
Platform::String^ path_str;
if (!path || !*path) if (!path || !*path)
return -1; return -1;
wchar_t *path_wide = utf8_to_utf16_string_alloc(path); path_wide = utf8_to_utf16_string_alloc(path);
windowsize_path(path_wide); windowsize_path(path_wide);
Platform::String^ path_str = ref new Platform::String(path_wide); path_str = ref new Platform::String(path_wide);
free(path_wide); free(path_wide);
return RunAsyncAndCatchErrors<int>([&]() { return RunAsyncAndCatchErrors<int>([&]() {
@ -543,25 +577,33 @@ int retro_vfs_file_remove_impl(const char *path)
/* TODO: this may not work if trying to move a directory */ /* TODO: this may not work if trying to move a directory */
int retro_vfs_file_rename_impl(const char *old_path, const char *new_path) int retro_vfs_file_rename_impl(const char *old_path, const char *new_path)
{ {
char *new_file_name;
char *new_dir_path;
wchar_t *new_file_name_wide;
wchar_t *old_path_wide, *new_dir_path_wide;
Platform::String^ old_path_str;
Platform::String^ new_dir_path_str;
Platform::String^ new_file_name_str;
if (!old_path || !*old_path || !new_path || !*new_path) if (!old_path || !*old_path || !new_path || !*new_path)
return -1; return -1;
wchar_t* old_path_wide = utf8_to_utf16_string_alloc(old_path); old_path_wide = utf8_to_utf16_string_alloc(old_path);
Platform::String^ old_path_str = ref new Platform::String(old_path_wide); old_path_str = ref new Platform::String(old_path_wide);
free(old_path_wide); free(old_path_wide);
char* new_dir_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); new_dir_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
fill_pathname_basedir(new_dir_path, new_path, PATH_MAX_LENGTH); fill_pathname_basedir(new_dir_path, new_path, PATH_MAX_LENGTH);
wchar_t *new_dir_path_wide = utf8_to_utf16_string_alloc(new_dir_path); new_dir_path_wide = utf8_to_utf16_string_alloc(new_dir_path);
windowsize_path(new_dir_path_wide); windowsize_path(new_dir_path_wide);
Platform::String^ new_dir_path_str = ref new Platform::String(new_dir_path_wide); new_dir_path_str = ref new Platform::String(new_dir_path_wide);
free(new_dir_path_wide); free(new_dir_path_wide);
free(new_dir_path); free(new_dir_path);
char* new_file_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); new_file_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
fill_pathname_base(new_file_name, new_path, PATH_MAX_LENGTH); fill_pathname_base(new_file_name, new_path, PATH_MAX_LENGTH);
wchar_t *new_file_name_wide = utf8_to_utf16_string_alloc(new_file_name); new_file_name_wide = utf8_to_utf16_string_alloc(new_file_name);
Platform::String^ new_file_name_str = ref new Platform::String(new_file_name_wide); new_file_name_str = ref new Platform::String(new_file_name_wide);
free(new_file_name_wide); free(new_file_name_wide);
free(new_file_name); free(new_file_name);
@ -595,15 +637,19 @@ const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *strea
int retro_vfs_stat_impl(const char *path, int32_t *size) int retro_vfs_stat_impl(const char *path, int32_t *size)
{ {
wchar_t *path_wide;
Platform::String^ path_str;
IStorageItem^ item;
if (!path || !*path) if (!path || !*path)
return 0; return 0;
wchar_t *path_wide = utf8_to_utf16_string_alloc(path); path_wide = utf8_to_utf16_string_alloc(path);
windowsize_path(path_wide); windowsize_path(path_wide);
Platform::String^ path_str = ref new Platform::String(path_wide); path_str = ref new Platform::String(path_wide);
free(path_wide); free(path_wide);
IStorageItem^ item = LocateStorageFileOrFolder(path_str); item = LocateStorageFileOrFolder(path_str);
if (!item) if (!item)
return 0; return 0;
@ -618,36 +664,44 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
int retro_vfs_mkdir_impl(const char *dir) int retro_vfs_mkdir_impl(const char *dir)
{ {
Platform::String^ parent_path_str;
Platform::String^ dir_name_str;
wchar_t *dir_name_wide, *parent_path_wide;
char *dir_local, *tmp, *dir_name, *parent_path;
if (!dir || !*dir) if (!dir || !*dir)
return -1; return -1;
char* dir_local = strdup(dir); /* If the path ends with a slash, we have to remove
/* If the path ends with a slash, we have to remove it for basename to work */ * it for basename to work */
char* tmp = dir_local + strlen(dir_local) - 1; dir_local = strdup(dir);
if (path_char_is_slash(*tmp)) tmp = dir_local + strlen(dir_local) - 1;
if (PATH_CHAR_IS_SLASH(*tmp))
*tmp = 0; *tmp = 0;
char* dir_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); dir_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
fill_pathname_base(dir_name, dir_local, PATH_MAX_LENGTH); fill_pathname_base(dir_name, dir_local, PATH_MAX_LENGTH);
wchar_t *dir_name_wide = utf8_to_utf16_string_alloc(dir_name); dir_name_wide = utf8_to_utf16_string_alloc(dir_name);
Platform::String^ dir_name_str = ref new Platform::String(dir_name_wide); dir_name_str = ref new Platform::String(dir_name_wide);
free(dir_name_wide); free(dir_name_wide);
free(dir_name); free(dir_name);
char* parent_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); parent_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
fill_pathname_parent_dir(parent_path, dir_local, PATH_MAX_LENGTH); fill_pathname_parent_dir(parent_path, dir_local, PATH_MAX_LENGTH);
wchar_t *parent_path_wide = utf8_to_utf16_string_alloc(parent_path); parent_path_wide = utf8_to_utf16_string_alloc(parent_path);
windowsize_path(parent_path_wide); windowsize_path(parent_path_wide);
Platform::String^ parent_path_str = ref new Platform::String(parent_path_wide); parent_path_str = ref new Platform::String(parent_path_wide);
free(parent_path_wide); free(parent_path_wide);
free(parent_path); free(parent_path);
retro_assert(!dir_name_str->IsEmpty() && !parent_path_str->IsEmpty()); retro_assert(!dir_name_str->IsEmpty()
&& !parent_path_str->IsEmpty());
free(dir_local); free(dir_local);
return RunAsyncAndCatchErrors<int>([&]() { return RunAsyncAndCatchErrors<int>([&]() {
return concurrency::create_task(LocateStorageItem<StorageFolder>(parent_path_str)).then([&](StorageFolder^ parent) { return concurrency::create_task(LocateStorageItem<StorageFolder>(
parent_path_str)).then([&](StorageFolder^ parent) {
return parent->CreateFolderAsync(dir_name_str); return parent->CreateFolderAsync(dir_name_str);
}).then([&](concurrency::task<StorageFolder^> new_dir) { }).then([&](concurrency::task<StorageFolder^> new_dir) {
try try
@ -678,6 +732,8 @@ struct libretro_vfs_implementation_dir
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool include_hidden) libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool include_hidden)
{ {
wchar_t *name_wide;
Platform::String^ name_str;
libretro_vfs_implementation_dir *rdir; libretro_vfs_implementation_dir *rdir;
if (!name || !*name) if (!name || !*name)
@ -687,9 +743,9 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i
if (!rdir) if (!rdir)
return NULL; return NULL;
wchar_t *name_wide = utf8_to_utf16_string_alloc(name); name_wide = utf8_to_utf16_string_alloc(name);
windowsize_path(name_wide); windowsize_path(name_wide);
Platform::String^ name_str = ref new Platform::String(name_wide); name_str = ref new Platform::String(name_wide);
free(name_wide); free(name_wide);
rdir->directory = RunAsyncAndCatchErrors<IVectorView<IStorageItem^>^>([&]() { rdir->directory = RunAsyncAndCatchErrors<IVectorView<IStorageItem^>^>([&]() {
@ -712,17 +768,16 @@ bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *rdir)
rdir->entry = rdir->directory->First(); rdir->entry = rdir->directory->First();
return rdir->entry->HasCurrent; return rdir->entry->HasCurrent;
} }
else
{
return rdir->entry->MoveNext(); return rdir->entry->MoveNext();
}
} }
const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *rdir) const char *retro_vfs_dirent_get_name_impl(
libretro_vfs_implementation_dir *rdir)
{ {
if (rdir->entry_name) if (rdir->entry_name)
free(rdir->entry_name); free(rdir->entry_name);
rdir->entry_name = utf16_to_utf8_string_alloc(rdir->entry->Current->Name->Data()); rdir->entry_name = utf16_to_utf8_string_alloc(
rdir->entry->Current->Name->Data());
return rdir->entry_name; return rdir->entry_name;
} }
@ -747,11 +802,13 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir)
bool uwp_drive_exists(const char *path) bool uwp_drive_exists(const char *path)
{ {
wchar_t *path_wide;
Platform::String^ path_str;
if (!path || !*path) if (!path || !*path)
return 0; return 0;
wchar_t *path_wide = utf8_to_utf16_string_alloc(path); path_wide = utf8_to_utf16_string_alloc(path);
Platform::String^ path_str = ref new Platform::String(path_wide); path_str = ref new Platform::String(path_wide);
free(path_wide); free(path_wide);
return RunAsyncAndCatchErrors<bool>([&]() { return RunAsyncAndCatchErrors<bool>([&]() {