This commit is contained in:
twinaphex 2020-06-25 14:01:44 +02:00
parent 596ab8a25a
commit 44c8c11348
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));
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.
* Loading will probably fail. */

View File

@ -571,7 +571,7 @@ void path_parent_dir(char *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);
@ -1004,7 +1004,7 @@ void fill_pathname_expand_special(char *out_path,
out_path += 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);
retro_assert(src_size < size);
@ -1035,7 +1035,7 @@ void fill_pathname_expand_special(char *out_path,
out_path += 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);
retro_assert(src_size < size);
@ -1098,7 +1098,7 @@ void fill_pathname_abbreviate_special(char *out_path,
size -= src_size;
in_path += strlen(candidates[i]);
if (!path_char_is_slash(*in_path))
if (!PATH_CHAR_IS_SLASH(*in_path))
{
retro_assert(strlcpy(out_path,
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);
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);
#endif

View File

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

View File

@ -59,10 +59,13 @@ namespace
{
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) */
/* 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 == '/')
@ -139,15 +142,21 @@ namespace
/* Look for a matching directory we can use */
for each (StorageFolder^ folder in accessible_directories)
{
std::wstring file_path;
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 */
if (folder_path[folder_path.size() - 1] == '\\')
folder_path.erase(folder_path.size() - 1);
std::wstring file_path = path->Data();
if (folder_path[folder_path_size - 1] == '\\')
folder_path.erase(folder_path_size - 1);
file_path = path->Data();
if (file_path.find(folder_path) == 0)
{
/* 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())));
}
}
@ -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_capacity = capacity;
@ -292,33 +302,38 @@ struct libretro_vfs_implementation_file
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)
return NULL;
/* Something tried to access files from current directory.
* This is not allowed on UWP. */
if (!path_is_absolute(path))
{
/* Something tried to access files from current directory. This is not allowed on UWP. */
return NULL;
}
/* 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;
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);
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);
dirpath_str = ref new Platform::String(dirpath_wide);
free(dirpath_wide);
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);
wchar_t *filename_wide = utf8_to_utf16_string_alloc(filename);
Platform::String^ filename_str = ref new Platform::String(filename_wide);
filename_wide = utf8_to_utf16_string_alloc(filename);
filename_str = ref new Platform::String(filename_wide);
free(filename_wide);
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 ?
CreationCollisionOption::OpenIfExists : CreationCollisionOption::ReplaceExisting);
}).then([&](StorageFile^ file) {
FileAccessMode accessMode = mode == RETRO_VFS_FILE_ACCESS_READ ?
FileAccessMode accessMode = (mode == RETRO_VFS_FILE_ACCESS_READ) ?
FileAccessMode::Read : FileAccessMode::ReadWrite;
return file->OpenAsync(accessMode);
}).then([&](IRandomAccessStream^ fpstream) {
@ -340,13 +355,14 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns
if (!stream)
return (libretro_vfs_implementation_file*)NULL;
stream->orig_path = strdup(path);
stream->fp = fpstream;
stream->orig_path = strdup(path);
stream->fp = fpstream;
stream->fp->Seek(0);
// Preallocate a small buffer for manually buffered IO, makes short read faster
int buf_size = 8 * 1024;
stream->buffer = (char*)malloc(buf_size);
stream->bufferp = CreateNativeBuffer(stream->buffer, buf_size, 0);
/* Preallocate a small buffer for manually buffered I/O,
* makes short read faster */
int buf_size = 8 * 1024;
stream->buffer = (char*)malloc(buf_size);
stream->bufferp = CreateNativeBuffer(stream->buffer, buf_size, 0);
stream->buffer_left = 0;
stream->buffer_fill = 0;
stream->buffer_size = buf_size;
@ -395,116 +411,131 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream)
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)
return -1;
if (!stream || !stream->fp)
return -1;
switch (seek_position)
{
case RETRO_VFS_SEEK_POSITION_START:
stream->fp->Seek(offset);
break;
switch (seek_position)
{
case RETRO_VFS_SEEK_POSITION_START:
stream->fp->Seek(offset);
break;
case RETRO_VFS_SEEK_POSITION_CURRENT:
stream->fp->Seek(retro_vfs_file_tell_impl(stream) + offset);
break;
case RETRO_VFS_SEEK_POSITION_CURRENT:
stream->fp->Seek(retro_vfs_file_tell_impl(stream) + offset);
break;
case RETRO_VFS_SEEK_POSITION_END:
stream->fp->Seek(stream->fp->Size - offset);
break;
}
case RETRO_VFS_SEEK_POSITION_END:
stream->fp->Seek(stream->fp->Size - offset);
break;
}
// For simplicity always flush the buffer on seek
stream->buffer_left = 0;
// For simplicity always flush the buffer on seek
stream->buffer_left = 0;
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)
return -1;
int64_t bytes_read = 0;
if (len <= stream->buffer_size)
{
/* Small read, use manually buffered I/O */
if (stream->buffer_left < len)
{
/* Exhaust the buffer */
memcpy(s,
&stream->buffer[stream->buffer_fill - stream->buffer_left],
stream->buffer_left);
len -= stream->buffer_left;
bytes_read += stream->buffer_left;
stream->buffer_left = 0;
if (len <= stream->buffer_size) {
// Small read, use manually buffered IO
if (stream->buffer_left < len) {
// Exhaust the buffer
memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], stream->buffer_left);
len -= stream->buffer_left;
bytes_read += stream->buffer_left;
stream->buffer_left = 0;
/* Fill buffer */
stream->buffer_left = RunAsyncAndCatchErrors<int64_t>([&]() {
return concurrency::create_task(stream->fp->ReadAsync(stream->bufferp, stream->bufferp->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) {
retro_assert(stream->bufferp == buf);
return (int64_t)stream->bufferp->Length;
});
}, -1);
stream->buffer_fill = stream->buffer_left;
// Fill buffer
stream->buffer_left = RunAsyncAndCatchErrors<int64_t>([&]() {
return concurrency::create_task(stream->fp->ReadAsync(stream->bufferp, stream->bufferp->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) {
retro_assert(stream->bufferp == buf);
return (int64_t)stream->bufferp->Length;
});
}, -1);
stream->buffer_fill = stream->buffer_left;
if (stream->buffer_left == -1)
{
stream->buffer_left = 0;
stream->buffer_fill = 0;
return -1;
}
if (stream->buffer_left == -1) {
stream->buffer_left = 0;
stream->buffer_fill = 0;
return -1;
}
if (stream->buffer_left < len)
{
/* EOF */
memcpy(&((char*)s)[bytes_read],
stream->buffer, stream->buffer_left);
bytes_read += stream->buffer_left;
stream->buffer_left = 0;
return bytes_read;
}
if (stream->buffer_left < len) {
// EOF
memcpy(&((char*)s)[bytes_read], stream->buffer, stream->buffer_left);
bytes_read += stream->buffer_left;
stream->buffer_left = 0;
return bytes_read;
}
memcpy(&((char*)s)[bytes_read], stream->buffer, len);
bytes_read += len;
stream->buffer_left -= len;
return bytes_read;
}
memcpy(&((char*)s)[bytes_read], stream->buffer, len);
bytes_read += len;
stream->buffer_left -= len;
return bytes_read;
}
/* Internal buffer already contains requested amount */
memcpy(s,
&stream->buffer[stream->buffer_fill - stream->buffer_left],
len);
stream->buffer_left -= len;
return len;
}
// Internal buffer already contains requested amount
memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], len);
stream->buffer_left -= 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);
len -= stream->buffer_left;
bytes_read += stream->buffer_left;
stream->buffer_left = 0;
len -= stream->buffer_left;
bytes_read += stream->buffer_left;
stream->buffer_left = 0;
IBuffer^ buffer = CreateNativeBuffer(&((char*)s)[bytes_read], len, 0);
int64_t ret = RunAsyncAndCatchErrors<int64_t>([&]() {
buffer = CreateNativeBuffer(&((char*)s)[bytes_read], len, 0);
ret = RunAsyncAndCatchErrors<int64_t>([&]() {
return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity - bytes_read, InputStreamOptions::None)).then([&](IBuffer^ buf) {
retro_assert(buf == buffer);
return (int64_t)buffer->Length;
});
}, -1);
if (ret == -1) {
if (ret == -1)
return -1;
}
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)
{
if (!stream || !stream->fp || !s)
return -1;
IBuffer^ buffer;
if (!stream || !stream->fp || !s)
return -1;
// 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);
return RunAsyncAndCatchErrors<int64_t>([&]() {
return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) {
return (int64_t)written;
});
}, -1);
/* const_cast to remove const modifier is undefined behaviour, but the buffer is only read, should be safe */
buffer = CreateNativeBuffer(const_cast<void*>(s), len, len);
return RunAsyncAndCatchErrors<int64_t>([&]() {
return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) {
return (int64_t)written;
});
}, -1);
}
int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream)
@ -523,12 +554,15 @@ int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream)
int retro_vfs_file_remove_impl(const char *path)
{
wchar_t *path_wide;
Platform::String^ path_str;
if (!path || !*path)
return -1;
wchar_t *path_wide = utf8_to_utf16_string_alloc(path);
path_wide = utf8_to_utf16_string_alloc(path);
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);
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 */
int retro_vfs_file_rename_impl(const char *old_path, const char *new_path)
{
if (!old_path || !*old_path || !new_path || !*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)
return -1;
wchar_t* old_path_wide = utf8_to_utf16_string_alloc(old_path);
Platform::String^ old_path_str = ref new Platform::String(old_path_wide);
old_path_wide = utf8_to_utf16_string_alloc(old_path);
old_path_str = ref new Platform::String(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);
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);
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);
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);
wchar_t *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_wide = utf8_to_utf16_string_alloc(new_file_name);
new_file_name_str = ref new Platform::String(new_file_name_wide);
free(new_file_name_wide);
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)
{
wchar_t *path_wide;
Platform::String^ path_str;
IStorageItem^ item;
if (!path || !*path)
return 0;
wchar_t *path_wide = utf8_to_utf16_string_alloc(path);
path_wide = utf8_to_utf16_string_alloc(path);
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);
IStorageItem^ item = LocateStorageFileOrFolder(path_str);
item = LocateStorageFileOrFolder(path_str);
if (!item)
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)
{
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)
return -1;
char* dir_local = strdup(dir);
/* If the path ends with a slash, we have to remove it for basename to work */
char* tmp = dir_local + strlen(dir_local) - 1;
if (path_char_is_slash(*tmp))
*tmp = 0;
/* If the path ends with a slash, we have to remove
* it for basename to work */
dir_local = strdup(dir);
tmp = dir_local + strlen(dir_local) - 1;
char* dir_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
if (PATH_CHAR_IS_SLASH(*tmp))
*tmp = 0;
dir_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
fill_pathname_base(dir_name, dir_local, PATH_MAX_LENGTH);
wchar_t *dir_name_wide = utf8_to_utf16_string_alloc(dir_name);
Platform::String^ dir_name_str = ref new Platform::String(dir_name_wide);
dir_name_wide = utf8_to_utf16_string_alloc(dir_name);
dir_name_str = ref new Platform::String(dir_name_wide);
free(dir_name_wide);
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);
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);
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);
retro_assert(!dir_name_str->IsEmpty() && !parent_path_str->IsEmpty());
retro_assert(!dir_name_str->IsEmpty()
&& !parent_path_str->IsEmpty());
free(dir_local);
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);
}).then([&](concurrency::task<StorageFolder^> new_dir) {
try
@ -678,6 +732,8 @@ struct libretro_vfs_implementation_dir
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;
if (!name || !*name)
@ -687,9 +743,9 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i
if (!rdir)
return NULL;
wchar_t *name_wide = utf8_to_utf16_string_alloc(name);
name_wide = utf8_to_utf16_string_alloc(name);
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);
rdir->directory = RunAsyncAndCatchErrors<IVectorView<IStorageItem^>^>([&]() {
@ -712,17 +768,16 @@ bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *rdir)
rdir->entry = rdir->directory->First();
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)
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;
}
@ -738,7 +793,7 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir)
if (rdir->entry_name)
free(rdir->entry_name);
rdir->entry = nullptr;
rdir->entry = nullptr;
rdir->directory = nullptr;
free(rdir);
@ -747,18 +802,20 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir)
bool uwp_drive_exists(const char *path)
{
if (!path || !*path)
return 0;
wchar_t *path_wide;
Platform::String^ path_str;
if (!path || !*path)
return 0;
wchar_t *path_wide = utf8_to_utf16_string_alloc(path);
Platform::String^ path_str = ref new Platform::String(path_wide);
free(path_wide);
path_wide = utf8_to_utf16_string_alloc(path);
path_str = ref new Platform::String(path_wide);
free(path_wide);
return RunAsyncAndCatchErrors<bool>([&]() {
return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(path_str)).then([](StorageFolder^ properties) {
return true;
});
}, false);
return RunAsyncAndCatchErrors<bool>([&]() {
return concurrency::create_task(StorageFolder::GetFolderFromPathAsync(path_str)).then([](StorageFolder^ properties) {
return true;
});
}, false);
}
char* uwp_trigger_picker(void)