make dir stuff more like the normal win32 stuff (#13006)

Co-authored-by: Tunip3 <tunip3@users.noreply.github.com>
This commit is contained in:
tunip3 2021-09-17 16:41:56 +01:00 committed by GitHub
parent 0a5bb29c43
commit 895676430f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1106,151 +1106,106 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
return 0; return 0;
} }
#ifdef VFS_FRONTEND #ifdef VFS_FRONTEND
struct retro_vfs_dir_handle struct retro_vfs_dir_handle
#else #else
struct libretro_vfs_implementation_dir struct libretro_vfs_implementation_dir
#endif #endif
{ {
IVectorView<IStorageItem^>^ directory; char* orig_path;
IIterator<IStorageItem^>^ entry; WIN32_FIND_DATAW entry;
char *entry_name; HANDLE directory;
bool next;
char path[PATH_MAX_LENGTH];
}; };
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; unsigned path_len;
Platform::String^ name_str; char path_buf[1024];
size_t copied = 0;
wchar_t* path_wide = NULL;
libretro_vfs_implementation_dir* rdir; libretro_vfs_implementation_dir* rdir;
if (!name || !*name) /*Reject null or empty string paths*/
if (!name || (*name == 0))
return NULL; return NULL;
/*Allocate RDIR struct. Tidied later with retro_closedir*/
rdir = (libretro_vfs_implementation_dir*)calloc(1, sizeof(*rdir)); rdir = (libretro_vfs_implementation_dir*)calloc(1, sizeof(*rdir));
if (!rdir) if (!rdir)
return NULL; return NULL;
name_wide = utf8_to_utf16_string_alloc(name); rdir->orig_path = strdup(name);
windowsize_path(name_wide);
name_str = ref new Platform::String(name_wide);
free(name_wide);
path_buf[0] = '\0';
path_len = strlen(name);
WIN32_FILE_ATTRIBUTE_DATA lpFileInfo; copied = strlcpy(path_buf, name, sizeof(path_buf));
std::filesystem::path dir(name);
if (dir.empty()) /* Non-NT platforms don't like extra slashes in the path */
return NULL; if (name[path_len - 1] != '\\')
path_buf[copied++] = '\\';
if (!(rdir->directory)) path_buf[copied] = '*';
{ path_buf[copied + 1] = '\0';
//check if file attributes can be gotten successfully
if (GetFileAttributesExFromAppW(dir.parent_path().wstring().c_str(), GetFileExInfoStandard, &lpFileInfo))
{
//check that the files attributes are not null or empty
if (lpFileInfo.dwFileAttributes != INVALID_FILE_ATTRIBUTES && lpFileInfo.dwFileAttributes != 0)
{
if (lpFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
std::wstring filteredPath(dir.wstring().c_str());
WIN32_FIND_DATA findDataResult;
if (filteredPath[filteredPath.size() - 1] == '\\')
filteredPath.erase(filteredPath.size() - 1);
filteredPath += L"\\*.*";
HANDLE searchResults = FindFirstFileExFromAppW(filteredPath.c_str(), FindExInfoBasic, &findDataResult, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_LARGE_FETCH);
if (searchResults != INVALID_HANDLE_VALUE)
{
Platform::Collections::Vector<IStorageItem^>^ result = ref new Platform::Collections::Vector<IStorageItem^>();
do
{
if (wcscmp(findDataResult.cFileName, L".") != 0 && wcscmp(findDataResult.cFileName, L"..") != 0)
{
if (!((findDataResult.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) || (findDataResult.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)))
{
std::filesystem::path temp_new = dir;
temp_new /= findDataResult.cFileName;
std::wstring temp_path = temp_new.generic_wstring(); path_wide = utf8_to_utf16_string_alloc(path_buf);
while (true) { rdir->directory = FindFirstFileExFromAppW(path_wide, FindExInfoStandard, &rdir->entry, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_LARGE_FETCH);
size_t p = temp_path.find(L"/");
if (p == std::wstring::npos) break;
temp_path.replace(p, 1, L"\\");
}
IStorageItem^ item;
if (findDataResult.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
item = RunAsyncAndCatchErrors<StorageFolder^>([&]() {
return concurrency::create_task(LocateStorageItem<StorageFolder>(ref new Platform::String(temp_path.c_str())));
}, nullptr);
}
else
{
item = RunAsyncAndCatchErrors<StorageFile^>([&]() {
return concurrency::create_task(LocateStorageItem<StorageFile>(ref new Platform::String(temp_path.c_str())));
}, nullptr);
}
if (item) if (path_wide)
if (result) free(path_wide);
result->Append(item);
}
}
} while (FindNextFile(searchResults, &findDataResult));
FindClose(searchResults);
if (result)
rdir->directory = result->GetView();
}
}
}
}
}
if (rdir->directory)
return rdir;
free(rdir); if (include_hidden)
return NULL; rdir->entry.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
else
rdir->entry.dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN;
if (rdir->directory && rdir != INVALID_HANDLE_VALUE)
return rdir;
retro_vfs_closedir_impl(rdir);
return NULL;
} }
bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *rdir) bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir* rdir)
{ {
if (!rdir->entry) if (rdir->next)
{ return (FindNextFileW(rdir->directory, &rdir->entry) != 0);
rdir->entry = rdir->directory->First();
return rdir->entry->HasCurrent; rdir->next = true;
} return (rdir->directory != INVALID_HANDLE_VALUE);
return rdir->entry->MoveNext();
} }
const char *retro_vfs_dirent_get_name_impl( const char* retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir* rdir)
libretro_vfs_implementation_dir *rdir)
{ {
if (rdir->entry_name) char* name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
free(rdir->entry_name); memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
rdir->entry_name = utf16_to_utf8_string_alloc( strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
rdir->entry->Current->Name->Data()); if (name)
return rdir->entry_name; free(name);
return (char*)rdir->entry.cFileName;
} }
bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *rdir) bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir* rdir)
{ {
return rdir->entry->Current->IsOfType(StorageItemTypes::Folder); const WIN32_FIND_DATA* entry = (const WIN32_FIND_DATA*)&rdir->entry;
return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
} }
int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir) int retro_vfs_closedir_impl(libretro_vfs_implementation_dir* rdir)
{ {
if (!rdir) if (!rdir)
return -1; return -1;
if (rdir->entry_name) if (rdir->directory != INVALID_HANDLE_VALUE)
free(rdir->entry_name); FindClose(rdir->directory);
rdir->entry = nullptr;
rdir->directory = nullptr;
free(rdir); if (rdir->orig_path)
return 0; free(rdir->orig_path);
free(rdir);
return 0;
} }
char* uwp_trigger_picker(void) char* uwp_trigger_picker(void)