Major update
This commit is contained in:
parent
cb5d18cb03
commit
05776ee6af
41 changed files with 396 additions and 3885 deletions
|
@ -6,10 +6,7 @@
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
#include <fileapifromapp.h>
|
#include <fileapifromapp.h>
|
||||||
#if !defined(__LIBRETRO__)
|
#include <UWP/UWPHelpers/StorageManager.h>
|
||||||
#include "UWP/UWPHelpers/StorageManager.h"
|
|
||||||
#include "UWP/UWPHelpers/PPSSPPTypesHelpers.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
@ -71,11 +68,6 @@ bool GetFileInfo(const Path &path, FileInfo * fileInfo) {
|
||||||
WIN32_FILE_ATTRIBUTE_DATA attrs;
|
WIN32_FILE_ATTRIBUTE_DATA attrs;
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
if (!GetFileAttributesExFromAppW(path.ToWString().c_str(), GetFileExInfoStandard, &attrs)) {
|
if (!GetFileAttributesExFromAppW(path.ToWString().c_str(), GetFileExInfoStandard, &attrs)) {
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
if (GetFileInfoUWP(path.ToString(), fileInfo)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
if (!GetFileAttributesExW(path.ToWString().c_str(), GetFileExInfoStandard, &attrs)) {
|
if (!GetFileAttributesExW(path.ToWString().c_str(), GetFileExInfoStandard, &attrs)) {
|
||||||
#endif
|
#endif
|
||||||
|
@ -230,11 +222,9 @@ bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const ch
|
||||||
#endif
|
#endif
|
||||||
if (hFind == INVALID_HANDLE_VALUE) {
|
if (hFind == INVALID_HANDLE_VALUE) {
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
||||||
// Getting folder contents need extra work
|
// This step just to avoid empty results by adding fake folders
|
||||||
// request must be done within StorageManager
|
// It will help also to navigate back between selected folder
|
||||||
auto contents = GetFolderContents(directory.ToString());
|
if(GetFakeFolders(directory, files, filter, filters)){
|
||||||
if (ItemsInfoUWPToFilesInfo(contents, files, filter, filters)) {
|
|
||||||
std::sort(files->begin(), files->end());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -337,14 +327,8 @@ std::vector<std::string> GetWindowsDrives()
|
||||||
{
|
{
|
||||||
CHAR driveName[] = { (CHAR)(TEXT('A') + i), TEXT(':'), TEXT('\\'), TEXT('\0') };
|
CHAR driveName[] = { (CHAR)(TEXT('A') + i), TEXT(':'), TEXT('\\'), TEXT('\0') };
|
||||||
std::string str(driveName);
|
std::string str(driveName);
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
if (CheckDriveAccess(driveName, true)) {
|
|
||||||
drives.push_back(driveName);
|
drives.push_back(driveName);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
drives.push_back(driveName);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return drives;
|
return drives;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -53,10 +53,8 @@
|
||||||
#include <direct.h> // getcwd
|
#include <direct.h> // getcwd
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
#include <fileapifromapp.h>
|
#include <fileapifromapp.h>
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
#include "UWP/UWPHelpers/StorageManager.h"
|
#include "UWP/UWPHelpers/StorageManager.h"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -161,13 +159,13 @@ FILE *OpenCFile(const Path &path, const char *mode) {
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(UNICODE)
|
#if defined(_WIN32) && defined(UNICODE)
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
||||||
// We shouldn't use _wfopen specificly for custom memory stick location
|
// We shouldn't use _wfopen here,
|
||||||
|
// this function is not allowed to read outside Local and Installation folders
|
||||||
|
// FileSystem (broadFileSystemAccess) doesn't apply on _wfopen
|
||||||
|
// if we have custom memory stick location _wfopen will return null
|
||||||
|
// 'GetFileStreamFromApp' will convert 'mode' to [access, share, creationDisposition]
|
||||||
|
// then it will call 'CreateFile2FromAppW' -> convert HANDLE to FILE*
|
||||||
FILE* file = GetFileStreamFromApp(path.ToString(), mode);
|
FILE* file = GetFileStreamFromApp(path.ToString(), mode);
|
||||||
|
|
||||||
if (!file) {
|
|
||||||
// Call UWP storage helper
|
|
||||||
file = GetFileStream(path.ToString(), mode);
|
|
||||||
}
|
|
||||||
return file;
|
return file;
|
||||||
#else
|
#else
|
||||||
return _wfopen(path.ToWString().c_str(), ConvertUTF8ToWString(mode).c_str());
|
return _wfopen(path.ToWString().c_str(), ConvertUTF8ToWString(mode).c_str());
|
||||||
|
@ -272,10 +270,6 @@ static bool ResolvePathVista(const std::wstring &path, wchar_t *buf, DWORD bufSi
|
||||||
if (getFinalPathNameByHandleW) {
|
if (getFinalPathNameByHandleW) {
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
HANDLE hFile = CreateFile2FromAppW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
|
HANDLE hFile = CreateFile2FromAppW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
//Use UWP StorageManager to get handle
|
|
||||||
hFile = CreateFileUWP(path, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING);
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
@ -391,11 +385,6 @@ bool Exists(const Path &path) {
|
||||||
WIN32_FILE_ATTRIBUTE_DATA data{};
|
WIN32_FILE_ATTRIBUTE_DATA data{};
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
if (!GetFileAttributesExFromAppW(path.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
|
if (!GetFileAttributesExFromAppW(path.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
if (IsExistsUWP(path.ToString())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -434,11 +423,6 @@ bool IsDirectory(const Path &filename) {
|
||||||
WIN32_FILE_ATTRIBUTE_DATA data{};
|
WIN32_FILE_ATTRIBUTE_DATA data{};
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
if (!GetFileAttributesExFromAppW(filename.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
|
if (!GetFileAttributesExFromAppW(filename.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
if (IsDirectoryUWP(filename.ToString())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
if (!GetFileAttributesEx(filename.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
|
if (!GetFileAttributesEx(filename.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
|
||||||
#endif
|
#endif
|
||||||
|
@ -492,11 +476,6 @@ bool Delete(const Path &filename) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
if (!DeleteFileFromAppW(filename.ToWString().c_str())) {
|
if (!DeleteFileFromAppW(filename.ToWString().c_str())) {
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
if (DeleteUWP(filename.ToString())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s", filename.c_str(), GetLastErrorMsg().c_str());
|
WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s", filename.c_str(), GetLastErrorMsg().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -551,19 +530,8 @@ bool CreateDir(const Path &path) {
|
||||||
DEBUG_LOG(COMMON, "CreateDir('%s')", path.c_str());
|
DEBUG_LOG(COMMON, "CreateDir('%s')", path.c_str());
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
if (CreateDirectoryFromAppW(path.ToWString().c_str(), NULL)) {
|
if (CreateDirectoryFromAppW(path.ToWString().c_str(), NULL))
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
else {
|
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
if (File::Exists(path)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CreateDirectoryUWP(path.ToString());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (::CreateDirectory(path.ToWString().c_str(), NULL))
|
if (::CreateDirectory(path.ToWString().c_str(), NULL))
|
||||||
return true;
|
return true;
|
||||||
|
@ -657,16 +625,8 @@ bool DeleteDir(const Path &path) {
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
if (RemoveDirectoryFromAppW(path.ToWString().c_str())) {
|
if (RemoveDirectoryFromAppW(path.ToWString().c_str()))
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
else {
|
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
if (DeleteUWP(path.ToString())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (::RemoveDirectory(path.ToWString().c_str()))
|
if (::RemoveDirectory(path.ToWString().c_str()))
|
||||||
return true;
|
return true;
|
||||||
|
@ -710,16 +670,14 @@ bool Rename(const Path &srcFilename, const Path &destFilename) {
|
||||||
INFO_LOG(COMMON, "Rename: %s --> %s", srcFilename.c_str(), destFilename.c_str());
|
INFO_LOG(COMMON, "Rename: %s --> %s", srcFilename.c_str(), destFilename.c_str());
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(UNICODE)
|
#if defined(_WIN32) && defined(UNICODE)
|
||||||
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
|
if (MoveFileFromAppW(srcFilename.ToWString().c_str(), destFilename.ToWString().c_str()))
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
std::wstring srcw = srcFilename.ToWString();
|
std::wstring srcw = srcFilename.ToWString();
|
||||||
std::wstring destw = destFilename.ToWString();
|
std::wstring destw = destFilename.ToWString();
|
||||||
if (_wrename(srcw.c_str(), destw.c_str()) == 0)
|
if (_wrename(srcw.c_str(), destw.c_str()) == 0)
|
||||||
return true;
|
return true;
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
|
||||||
else {
|
|
||||||
if (RenameUWP(srcFilename.ToString(), destFilename.ToString())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
if (rename(srcFilename.c_str(), destFilename.c_str()) == 0)
|
if (rename(srcFilename.c_str(), destFilename.c_str()) == 0)
|
||||||
|
@ -755,13 +713,6 @@ bool Copy(const Path &srcFilename, const Path &destFilename) {
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
if (CopyFileFromAppW(srcFilename.ToWString().c_str(), destFilename.ToWString().c_str(), FALSE))
|
if (CopyFileFromAppW(srcFilename.ToWString().c_str(), destFilename.ToWString().c_str(), FALSE))
|
||||||
return true;
|
return true;
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
else {
|
|
||||||
if (CopyUWP(srcFilename.ToString(), destFilename.ToString())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
if (CopyFile(srcFilename.ToWString().c_str(), destFilename.ToWString().c_str(), FALSE))
|
if (CopyFile(srcFilename.ToWString().c_str(), destFilename.ToWString().c_str(), FALSE))
|
||||||
return true;
|
return true;
|
||||||
|
@ -846,11 +797,6 @@ bool Move(const Path &srcFilename, const Path &destFilename) {
|
||||||
} else if (Copy(srcFilename, destFilename)) {
|
} else if (Copy(srcFilename, destFilename)) {
|
||||||
return Delete(srcFilename);
|
return Delete(srcFilename);
|
||||||
} else {
|
} else {
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
|
||||||
if (MoveUWP(srcFilename.ToString(), destFilename.ToString())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -900,9 +846,6 @@ uint64_t GetFileSize(const Path &filename) {
|
||||||
WIN32_FILE_ATTRIBUTE_DATA attr;
|
WIN32_FILE_ATTRIBUTE_DATA attr;
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
if (!GetFileAttributesExFromAppW(filename.ToWString().c_str(), GetFileExInfoStandard, &attr)) {
|
if (!GetFileAttributesExFromAppW(filename.ToWString().c_str(), GetFileExInfoStandard, &attr)) {
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
return (uint64_t)GetSizeUWP(filename.ToString());
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
if (!GetFileAttributesEx(filename.ToWString().c_str(), GetFileExInfoStandard, &attr)){
|
if (!GetFileAttributesEx(filename.ToWString().c_str(), GetFileExInfoStandard, &attr)){
|
||||||
#endif
|
#endif
|
||||||
|
@ -1020,9 +963,7 @@ bool OpenFileInEditor(const Path &fileName) {
|
||||||
|
|
||||||
#if PPSSPP_PLATFORM(WINDOWS)
|
#if PPSSPP_PLATFORM(WINDOWS)
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
OpenFile(fileName.ToString());
|
OpenFile(fileName.ToString());
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
ShellExecuteW(nullptr, L"open", fileName.ToWString().c_str(), nullptr, nullptr, SW_SHOW);
|
ShellExecuteW(nullptr, L"open", fileName.ToWString().c_str(), nullptr, nullptr, SW_SHOW);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,9 +33,6 @@
|
||||||
#include "Common/CommonWindows.h"
|
#include "Common/CommonWindows.h"
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
#include <fileapifromapp.h>
|
#include <fileapifromapp.h>
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
#include "UWP/UWPHelpers/StorageManager.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -110,17 +107,9 @@ LocalFileLoader::LocalFileLoader(const Path &filename)
|
||||||
#else
|
#else
|
||||||
handle_ = CreateFile(filename.ToWString().c_str(), access, share, nullptr, mode, flags, nullptr);
|
handle_ = CreateFile(filename.ToWString().c_str(), access, share, nullptr, mode, flags, nullptr);
|
||||||
#endif
|
#endif
|
||||||
if (handle_ == INVALID_HANDLE_VALUE) {
|
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
|
||||||
//Use UWP StorageManager to get handle
|
|
||||||
handle_ = CreateFileUWP(filename_.ToString(), access, share, mode);
|
|
||||||
if (handle_ == INVALID_HANDLE_VALUE) {
|
if (handle_ == INVALID_HANDLE_VALUE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
LARGE_INTEGER end_offset;
|
LARGE_INTEGER end_offset;
|
||||||
const LARGE_INTEGER zero{};
|
const LARGE_INTEGER zero{};
|
||||||
if (SetFilePointerEx(handle_, zero, &end_offset, FILE_END) == 0) {
|
if (SetFilePointerEx(handle_, zero, &end_offset, FILE_END) == 0) {
|
||||||
|
@ -170,11 +159,7 @@ bool LocalFileLoader::Exists() {
|
||||||
if (File::GetFileInfo(filename_, &info)) {
|
if (File::GetFileInfo(filename_, &info)) {
|
||||||
return info.exists;
|
return info.exists;
|
||||||
} else {
|
} else {
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
|
||||||
return IsExistsUWP(filename_.ToString());
|
|
||||||
#else
|
|
||||||
return false;
|
return false;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,11 +168,7 @@ bool LocalFileLoader::IsDirectory() {
|
||||||
if (File::GetFileInfo(filename_, &info)) {
|
if (File::GetFileInfo(filename_, &info)) {
|
||||||
return info.exists && info.isDirectory;
|
return info.exists && info.isDirectory;
|
||||||
}
|
}
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
|
||||||
return IsDirectoryUWP(filename_.ToString());
|
|
||||||
#else
|
|
||||||
return false;
|
return false;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 LocalFileLoader::FileSize() {
|
s64 LocalFileLoader::FileSize() {
|
||||||
|
|
|
@ -52,10 +52,6 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
#include <fileapifromapp.h>
|
#include <fileapifromapp.h>
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
#include "UWP/UWPHelpers/StorageManager.h"
|
|
||||||
#include "UWP/UWPHelpers/PPSSPPTypesHelpers.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#undef FILE_OPEN
|
#undef FILE_OPEN
|
||||||
#else
|
#else
|
||||||
|
@ -175,13 +171,6 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File
|
||||||
hFile = CreateFile(fullName.ToWString().c_str(), desired, sharemode, 0, openmode, 0, 0);
|
hFile = CreateFile(fullName.ToWString().c_str(), desired, sharemode, 0, openmode, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
bool success = hFile != INVALID_HANDLE_VALUE;
|
bool success = hFile != INVALID_HANDLE_VALUE;
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
|
||||||
if (!success) {
|
|
||||||
//Use UWP StorageManager to get handle
|
|
||||||
hFile = CreateFileUWP(fullName.ToString(), desired, sharemode, openmode);
|
|
||||||
success = hFile != INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
DWORD w32err = GetLastError();
|
DWORD w32err = GetLastError();
|
||||||
|
|
||||||
|
@ -194,13 +183,6 @@ bool DirectoryFileHandle::Open(const Path &basePath, std::string &fileName, File
|
||||||
hFile = CreateFile(fullName.ToWString().c_str(), desired, sharemode, 0, openmode, 0, 0);
|
hFile = CreateFile(fullName.ToWString().c_str(), desired, sharemode, 0, openmode, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
success = hFile != INVALID_HANDLE_VALUE;
|
success = hFile != INVALID_HANDLE_VALUE;
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
|
||||||
if (!success) {
|
|
||||||
//Use UWP StorageManager to get handle
|
|
||||||
hFile = CreateFileUWP(fullName.ToString(), desired, sharemode, openmode);
|
|
||||||
success = hFile != INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
w32err = GetLastError();
|
w32err = GetLastError();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,10 +41,6 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#if PPSSPP_PLATFORM(UWP)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
#include <fileapifromapp.h>
|
#include <fileapifromapp.h>
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
#include "UWP/UWPHelpers/StorageManager.h"
|
|
||||||
#include "UWP/UWPHelpers/PPSSPPTypesHelpers.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
@ -688,40 +684,6 @@ std::vector<PSPFileInfo> VirtualDiscFileSystem::GetDirListing(const std::string
|
||||||
hFind = FindFirstFileEx(w32path.c_str(), FindExInfoStandard, &findData, FindExSearchNameMatch, NULL, 0);
|
hFind = FindFirstFileEx(w32path.c_str(), FindExInfoStandard, &findData, FindExSearchNameMatch, NULL, 0);
|
||||||
#endif
|
#endif
|
||||||
if (hFind == INVALID_HANDLE_VALUE) {
|
if (hFind == INVALID_HANDLE_VALUE) {
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
|
||||||
// Getting folder contents will need extra work
|
|
||||||
// request must be done within StorageManager
|
|
||||||
auto contents = GetFolderContents(w32path);
|
|
||||||
if (!contents.empty()) {
|
|
||||||
//Copy files data from 'files' to 'myVector'
|
|
||||||
for each (auto item in contents) {
|
|
||||||
PSPFileInfo entry;
|
|
||||||
if (item.isDirectory) {
|
|
||||||
entry.type = FILETYPE_DIRECTORY;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entry.type = FILETYPE_NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry.access = 0555;
|
|
||||||
entry.exists = true;
|
|
||||||
entry.size = item.size;
|
|
||||||
entry.name = item.name;
|
|
||||||
//tmFromFiletime(entry.atime, file.atime); //find solution if this value is important
|
|
||||||
//tmFromFiletime(entry.ctime, file.ctime); //find solution if this value is important
|
|
||||||
//tmFromFiletime(entry.mtime, file.mtime); //find solution if this value is important
|
|
||||||
entry.isOnSectorSystem = true;
|
|
||||||
|
|
||||||
std::string fullRelativePath = path + "/" + entry.name;
|
|
||||||
int fileIndex = getFileListIndex(fullRelativePath);
|
|
||||||
if (fileIndex != -1)
|
|
||||||
entry.startSector = fileList[fileIndex].firstBlock;
|
|
||||||
|
|
||||||
myVector.push_back(entry);
|
|
||||||
}
|
|
||||||
return myVector;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (exists)
|
if (exists)
|
||||||
*exists = false;
|
*exists = false;
|
||||||
return myVector; //the empty list
|
return myVector; //the empty list
|
||||||
|
|
|
@ -48,10 +48,6 @@
|
||||||
#include "Core/Util/GameManager.h"
|
#include "Core/Util/GameManager.h"
|
||||||
#include "Common/Data/Text/I18n.h"
|
#include "Common/Data/Text/I18n.h"
|
||||||
|
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
|
||||||
#include "UWP/UWPHelpers/StorageManager.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GameManager g_GameManager;
|
GameManager g_GameManager;
|
||||||
|
|
||||||
static struct zip *ZipOpenPath(Path fileName) {
|
static struct zip *ZipOpenPath(Path fileName) {
|
||||||
|
@ -79,12 +75,6 @@ GameManager::GameManager() {
|
||||||
|
|
||||||
Path GameManager::GetTempFilename() const {
|
Path GameManager::GetTempFilename() const {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
|
||||||
std::string tmpFile = GetTempFile("PSP.tmp");
|
|
||||||
if (!tmpFile.empty()) {
|
|
||||||
return Path(tmpFile);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
wchar_t tempPath[MAX_PATH];
|
wchar_t tempPath[MAX_PATH];
|
||||||
GetTempPath(MAX_PATH, tempPath);
|
GetTempPath(MAX_PATH, tempPath);
|
||||||
wchar_t buffer[MAX_PATH];
|
wchar_t buffer[MAX_PATH];
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
#include "UI/ControlMappingScreen.h"
|
#include "UI/ControlMappingScreen.h"
|
||||||
#include "UI/GameSettingsScreen.h"
|
#include "UI/GameSettingsScreen.h"
|
||||||
|
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
#if PPSSPP_PLATFORM(UWP)
|
||||||
#include "UWP/UWPHelpers/StorageManager.h"
|
#include "UWP/UWPHelpers/StorageManager.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -522,7 +522,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||||
else {
|
else {
|
||||||
INFO_LOG(SYSTEM, "No memstick directory file found (tried to open '%s')", pathResolved.c_str());
|
INFO_LOG(SYSTEM, "No memstick directory file found (tried to open '%s')", pathResolved.c_str());
|
||||||
}
|
}
|
||||||
SetWorkingFolder(g_Config.memStickDirectory.ToString());
|
|
||||||
#elif PPSSPP_PLATFORM(IOS)
|
#elif PPSSPP_PLATFORM(IOS)
|
||||||
g_Config.defaultCurrentDirectory = g_Config.internalDataDirectory;
|
g_Config.defaultCurrentDirectory = g_Config.internalDataDirectory;
|
||||||
g_Config.memStickDirectory = DarwinFileSystemServices::appropriateMemoryStickDirectoryToUse();
|
g_Config.memStickDirectory = DarwinFileSystemServices::appropriateMemoryStickDirectoryToUse();
|
||||||
|
@ -788,7 +787,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||||
DEBUG_LOG(SYSTEM, "ScreenManager!");
|
DEBUG_LOG(SYSTEM, "ScreenManager!");
|
||||||
g_screenManager = new ScreenManager();
|
g_screenManager = new ScreenManager();
|
||||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
||||||
if (g_Config.memStickDirectory.empty() || (IsFirstStart() && isLocalState(g_Config.memStickDirectory.ToString()))) {
|
if (g_Config.memStickDirectory.empty() || (g_Config.bFirstRun && isLocalState(g_Config.memStickDirectory.ToString()))) {
|
||||||
#else
|
#else
|
||||||
if (g_Config.memStickDirectory.empty()) {
|
if (g_Config.memStickDirectory.empty()) {
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
#include <ppltasks.h>
|
#include <ppltasks.h>
|
||||||
|
|
||||||
#include <UWPHelpers/StorageExtensions.h>
|
|
||||||
#include <UWPHelpers/LaunchItem.h>
|
#include <UWPHelpers/LaunchItem.h>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
|
|
|
@ -134,8 +134,6 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptr<DX::DeviceResourc
|
||||||
|
|
||||||
// Set log file location
|
// Set log file location
|
||||||
if (g_Config.bEnableLogging) {
|
if (g_Config.bEnableLogging) {
|
||||||
// Do cleanup first
|
|
||||||
CleanupLogs();
|
|
||||||
LogManager::GetInstance()->ChangeFileLog(GetLogFile().c_str());
|
LogManager::GetInstance()->ChangeFileLog(GetLogFile().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +588,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
|
||||||
{
|
{
|
||||||
auto dataPackage = ref new DataPackage();
|
auto dataPackage = ref new DataPackage();
|
||||||
dataPackage->RequestedOperation = DataPackageOperation::Copy;
|
dataPackage->RequestedOperation = DataPackageOperation::Copy;
|
||||||
dataPackage->SetText(convert(param1));
|
dataPackage->SetText(ToPlatformString(param1));
|
||||||
Clipboard::SetContent(dataPackage);
|
Clipboard::SetContent(dataPackage);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
|
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
|
||||||
<Identity Name="0ad29e1a-1069-4cf5-8c97-620892505f0c" Publisher="CN=Henrik" Version="1.14.4.0" />
|
<Identity Name="0ad29e1a-1069-4cf5-8c97-620892505f0c" Publisher="CN=Henrik" Version="1.14.4.0" />
|
||||||
<mp:PhoneIdentity PhoneProductId="0ad29e1a-1069-4cf5-8c97-620892505f0c" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
<mp:PhoneIdentity PhoneProductId="0ad29e1a-1069-4cf5-8c97-620892505f0c" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||||
|
@ -48,6 +48,6 @@
|
||||||
<rescap:Capability Name="broadFileSystemAccess" />
|
<rescap:Capability Name="broadFileSystemAccess" />
|
||||||
<rescap:Capability Name="expandedResources" />
|
<rescap:Capability Name="expandedResources" />
|
||||||
<Capability Name="internetClientServer"/>
|
<Capability Name="internetClientServer"/>
|
||||||
<Capability Name="privateNetworkClientServer"/> <!-- For features like remote disk streaming -->
|
<Capability Name="privateNetworkClientServer"/><!-- For features like remote disc streaming -->
|
||||||
</Capabilities>
|
</Capabilities>
|
||||||
</Package>
|
</Package>
|
||||||
|
|
|
@ -52,6 +52,6 @@
|
||||||
<rescap:Capability Name="broadFileSystemAccess" />
|
<rescap:Capability Name="broadFileSystemAccess" />
|
||||||
<rescap:Capability Name="expandedResources" />
|
<rescap:Capability Name="expandedResources" />
|
||||||
<Capability Name="internetClientServer"/>
|
<Capability Name="internetClientServer"/>
|
||||||
<Capability Name="privateNetworkClientServer"/> <!-- For features like remote disk streaming -->
|
<Capability Name="privateNetworkClientServer"/><!-- For features like remote disc streaming -->
|
||||||
</Capabilities>
|
</Capabilities>
|
||||||
</Package>
|
</Package>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
|
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
|
||||||
<Identity Name="0ad29e1a-1069-4cf5-8c97-620892505f0c" Publisher="CN=Henrik" Version="1.14.4.0" />
|
<Identity Name="0ad29e1a-1069-4cf5-8c97-620892505f0c" Publisher="CN=Henrik" Version="1.14.4.0" />
|
||||||
<mp:PhoneIdentity PhoneProductId="0ad29e1a-1069-4cf5-8c97-620892505f0c" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
<mp:PhoneIdentity PhoneProductId="0ad29e1a-1069-4cf5-8c97-620892505f0c" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||||
|
@ -48,6 +48,6 @@
|
||||||
<rescap:Capability Name="broadFileSystemAccess" />
|
<rescap:Capability Name="broadFileSystemAccess" />
|
||||||
<rescap:Capability Name="expandedResources" />
|
<rescap:Capability Name="expandedResources" />
|
||||||
<Capability Name="internetClientServer"/>
|
<Capability Name="internetClientServer"/>
|
||||||
<Capability Name="privateNetworkClientServer"/> <!-- For features like remote disk streaming -->
|
<Capability Name="privateNetworkClientServer"/><!-- For features like remote disc streaming -->
|
||||||
</Capabilities>
|
</Capabilities>
|
||||||
</Package>
|
</Package>
|
||||||
|
|
|
@ -89,12 +89,14 @@
|
||||||
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
|
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
|
||||||
<AppxSymbolPackageEnabled>False</AppxSymbolPackageEnabled>
|
<AppxSymbolPackageEnabled>False</AppxSymbolPackageEnabled>
|
||||||
<AppxBundle>Never</AppxBundle>
|
<AppxBundle>Never</AppxBundle>
|
||||||
<PackageCertificateThumbprint>C8DEB388B9BC89D1DC61324E4E9D9FE6A796B7AA</PackageCertificateThumbprint>
|
|
||||||
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||||
<AppInstallerUpdateFrequency>1</AppInstallerUpdateFrequency>
|
<AppInstallerUpdateFrequency>0</AppInstallerUpdateFrequency>
|
||||||
<AppInstallerCheckForUpdateFrequency>OnApplicationRun</AppInstallerCheckForUpdateFrequency>
|
<AppInstallerCheckForUpdateFrequency>OnApplicationRun</AppInstallerCheckForUpdateFrequency>
|
||||||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
||||||
<PackageCertificateKeyFile>PPSSPP_UWP_TemporaryKey.pfx</PackageCertificateKeyFile>
|
<PackageCertificateKeyFile>PPSSPP_UWP_TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||||
|
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
|
||||||
|
<GenerateTestArtifacts>True</GenerateTestArtifacts>
|
||||||
|
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||||
<Link>
|
<Link>
|
||||||
|
@ -458,21 +460,10 @@
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="UWPUtil.h" />
|
<ClInclude Include="UWPUtil.h" />
|
||||||
<ClInclude Include="XAudioSoundStream.h" />
|
<ClInclude Include="XAudioSoundStream.h" />
|
||||||
<ClInclude Include="UWPHelpers\PPSSPPTypesHelpers.h" />
|
|
||||||
<ClInclude Include="UWPHelpers\StorageAccess.h" />
|
<ClInclude Include="UWPHelpers\StorageAccess.h" />
|
||||||
<ClInclude Include="UWPHelpers\StorageAsync.h" />
|
<ClInclude Include="UWPHelpers\StorageAsync.h" />
|
||||||
<ClInclude Include="UWPHelpers\StorageConfig.h" />
|
|
||||||
<ClInclude Include="UWPHelpers\StorageExtensions.h" />
|
|
||||||
<ClInclude Include="UWPHelpers\StorageFileW.h" />
|
|
||||||
<ClInclude Include="UWPHelpers\StorageFolderW.h" />
|
|
||||||
<ClInclude Include="UWPHelpers\StorageHandler.h" />
|
|
||||||
<ClInclude Include="UWPHelpers\StorageInfo.h" />
|
|
||||||
<ClInclude Include="UWPHelpers\StorageItemW.h" />
|
|
||||||
<ClInclude Include="UWPHelpers\StorageLog.h" />
|
|
||||||
<ClInclude Include="UWPHelpers\StorageManager.h" />
|
<ClInclude Include="UWPHelpers\StorageManager.h" />
|
||||||
<ClInclude Include="UWPHelpers\StoragePath.h" />
|
|
||||||
<ClInclude Include="UWPHelpers\StoragePickers.h" />
|
<ClInclude Include="UWPHelpers\StoragePickers.h" />
|
||||||
<ClInclude Include="UWPHelpers\UWP2C.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\git-version.cpp">
|
<ClCompile Include="..\git-version.cpp">
|
||||||
|
@ -485,15 +476,10 @@
|
||||||
<ClCompile Include="NKCodeFromWindowsSystem.cpp" />
|
<ClCompile Include="NKCodeFromWindowsSystem.cpp" />
|
||||||
<ClCompile Include="PPSSPP_UWPMain.cpp" />
|
<ClCompile Include="PPSSPP_UWPMain.cpp" />
|
||||||
<ClCompile Include="UWPHelpers\LaunchItem.h" />
|
<ClCompile Include="UWPHelpers\LaunchItem.h" />
|
||||||
<ClCompile Include="UWPHelpers\PPSSPPTypesHelpers.cpp" />
|
|
||||||
<ClCompile Include="UWPHelpers\StorageAccess.cpp" />
|
<ClCompile Include="UWPHelpers\StorageAccess.cpp" />
|
||||||
<ClCompile Include="UWPHelpers\StorageAsync.cpp" />
|
<ClCompile Include="UWPHelpers\StorageAsync.cpp" />
|
||||||
<ClCompile Include="UWPHelpers\StorageExtensions.cpp" />
|
|
||||||
<ClCompile Include="UWPHelpers\StorageHandler.cpp" />
|
|
||||||
<ClCompile Include="UWPHelpers\StorageManager.cpp" />
|
<ClCompile Include="UWPHelpers\StorageManager.cpp" />
|
||||||
<ClCompile Include="UWPHelpers\StoragePath.cpp" />
|
|
||||||
<ClCompile Include="UWPHelpers\StoragePickers.cpp" />
|
<ClCompile Include="UWPHelpers\StoragePickers.cpp" />
|
||||||
<ClCompile Include="UWPHelpers\UWP2C.cpp" />
|
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -17,78 +17,30 @@
|
||||||
<UniqueIdentifier>a5564d79-b131-4b27-9f5f-d80671731d94</UniqueIdentifier>
|
<UniqueIdentifier>a5564d79-b131-4b27-9f5f-d80671731d94</UniqueIdentifier>
|
||||||
<Extensions>bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png</Extensions>
|
<Extensions>bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png</Extensions>
|
||||||
</Filter>
|
</Filter>
|
||||||
<ClInclude Include="UWPHelpers\PPSSPPTypesHelpers.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="UWPHelpers\StorageAccess.h">
|
<ClInclude Include="UWPHelpers\StorageAccess.h">
|
||||||
<Filter>UWPHelpers</Filter>
|
<Filter>UWPHelpers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="UWPHelpers\StorageAsync.h">
|
<ClInclude Include="UWPHelpers\StorageAsync.h">
|
||||||
<Filter>UWPHelpers</Filter>
|
<Filter>UWPHelpers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="UWPHelpers\StorageConfig.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="UWPHelpers\StorageExtensions.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="UWPHelpers\StorageFileW.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="UWPHelpers\StorageFolderW.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="UWPHelpers\StorageHandler.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="UWPHelpers\StorageInfo.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="UWPHelpers\StorageItemW.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="UWPHelpers\StorageLog.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="UWPHelpers\StorageManager.h">
|
<ClInclude Include="UWPHelpers\StorageManager.h">
|
||||||
<Filter>UWPHelpers</Filter>
|
<Filter>UWPHelpers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="UWPHelpers\StoragePath.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="UWPHelpers\StoragePickers.h">
|
<ClInclude Include="UWPHelpers\StoragePickers.h">
|
||||||
<Filter>UWPHelpers</Filter>
|
<Filter>UWPHelpers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="UWPHelpers\UWP2C.h">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClCompile Include="UWPHelpers\PPSSPPTypesHelpers.cpp">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="UWPHelpers\StorageAccess.cpp">
|
<ClCompile Include="UWPHelpers\StorageAccess.cpp">
|
||||||
<Filter>UWPHelpers</Filter>
|
<Filter>UWPHelpers</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="UWPHelpers\StorageAsync.cpp">
|
<ClCompile Include="UWPHelpers\StorageAsync.cpp">
|
||||||
<Filter>UWPHelpers</Filter>
|
<Filter>UWPHelpers</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="UWPHelpers\StorageExtensions.cpp">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="UWPHelpers\StorageHandler.cpp">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="UWPHelpers\StorageManager.cpp">
|
<ClCompile Include="UWPHelpers\StorageManager.cpp">
|
||||||
<Filter>UWPHelpers</Filter>
|
<Filter>UWPHelpers</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="UWPHelpers\StoragePath.cpp">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="UWPHelpers\StoragePickers.cpp">
|
<ClCompile Include="UWPHelpers\StoragePickers.cpp">
|
||||||
<Filter>UWPHelpers</Filter>
|
<Filter>UWPHelpers</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="UWPHelpers\UWP2C.cpp">
|
|
||||||
<Filter>UWPHelpers</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClInclude Include="Common\DirectXHelper.h">
|
<ClInclude Include="Common\DirectXHelper.h">
|
||||||
<Filter>Common</Filter>
|
<Filter>Common</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "Common/Log.h"
|
#include "Common/Log.h"
|
||||||
#include "StorageExtensions.h"
|
#include "UWPUtil.h"
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ public:
|
||||||
|
|
||||||
if (arg->Name == "cmd")
|
if (arg->Name == "cmd")
|
||||||
{
|
{
|
||||||
auto command = convert(arg->Value);
|
auto command = FromPlatformString(arg->Value);
|
||||||
DEBUG_LOG(FILESYS, "Launch command %s", command.c_str());
|
DEBUG_LOG(FILESYS, "Launch command %s", command.c_str());
|
||||||
|
|
||||||
std::regex rgx("\"(.+\[^\/]+)\"");
|
std::regex rgx("\"(.+\[^\/]+)\"");
|
||||||
|
@ -59,7 +59,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (arg->Name == "launchOnExit") {
|
else if (arg->Name == "launchOnExit") {
|
||||||
launchOnExit = convert(arg->Value);
|
launchOnExit = FromPlatformString(arg->Value);
|
||||||
DEBUG_LOG(FILESYS, "On exit URI %s", launchOnExit.c_str());
|
DEBUG_LOG(FILESYS, "On exit URI %s", launchOnExit.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ public:
|
||||||
std::string GetFilePath() {
|
std::string GetFilePath() {
|
||||||
std::string path = launchPath;
|
std::string path = launchPath;
|
||||||
if (storageFile != nullptr) {
|
if (storageFile != nullptr) {
|
||||||
path = convert(storageFile->Path);
|
path = FromPlatformString(storageFile->Path);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ public:
|
||||||
|
|
||||||
if (!launchOnExit.empty()) {
|
if (!launchOnExit.empty()) {
|
||||||
DEBUG_LOG(FILESYS, "Calling back %s", launchOnExit.c_str());
|
DEBUG_LOG(FILESYS, "Calling back %s", launchOnExit.c_str());
|
||||||
auto uri = ref new Windows::Foundation::Uri(convert(launchOnExit));
|
auto uri = ref new Windows::Foundation::Uri(ToPlatformString(launchOnExit));
|
||||||
Windows::System::Launcher::LaunchUriAsync(uri);
|
Windows::System::Launcher::LaunchUriAsync(uri);
|
||||||
}
|
}
|
||||||
launchOnExit = std::string();
|
launchOnExit = std::string();
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
#include "PPSSPPTypesHelpers.h"
|
|
||||||
#include "StorageManager.h"
|
|
||||||
#include "Common/Log.h"
|
|
||||||
|
|
||||||
bool ItemsInfoUWPToFilesInfo(std::list<ItemInfoUWP> items, std::vector<File::FileInfo>* files, const char* filter, std::set<std::string> filters) {
|
|
||||||
bool state = false;
|
|
||||||
if (!items.empty()) {
|
|
||||||
for each (auto item in items) {
|
|
||||||
File::FileInfo info;
|
|
||||||
info.name = item.name;
|
|
||||||
info.fullName = Path(item.fullName);
|
|
||||||
info.exists = true;
|
|
||||||
info.size = item.size;
|
|
||||||
info.isDirectory = item.isDirectory;
|
|
||||||
info.isWritable = (item.attributes & FILE_ATTRIBUTE_READONLY) == 0;
|
|
||||||
info.atime = item.lastAccessTime;
|
|
||||||
info.mtime = item.lastWriteTime;
|
|
||||||
info.ctime = item.creationTime;
|
|
||||||
if (item.attributes & FILE_ATTRIBUTE_READONLY) {
|
|
||||||
info.access = 0444; // Read
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
info.access = 0666; // Read/Write
|
|
||||||
}
|
|
||||||
if (item.attributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
||||||
info.access |= 0111; // Execute
|
|
||||||
}
|
|
||||||
if (!info.isDirectory) {
|
|
||||||
std::string ext = info.fullName.GetFileExtension();
|
|
||||||
if (!ext.empty()) {
|
|
||||||
ext = ext.substr(1); // Remove the dot.
|
|
||||||
if (filter && filters.find(ext) == filters.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
files->push_back(info);
|
|
||||||
}
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateFileInfoByItemInfo(ItemInfoUWP item, File::FileInfo* info) {
|
|
||||||
info->name = item.name;
|
|
||||||
info->fullName = Path(item.fullName);
|
|
||||||
info->exists = true;
|
|
||||||
info->size = item.size;
|
|
||||||
info->isDirectory = item.isDirectory;
|
|
||||||
info->isWritable = (item.attributes & FILE_ATTRIBUTE_READONLY) == 0;
|
|
||||||
info->atime = item.lastAccessTime;
|
|
||||||
info->mtime = item.lastWriteTime;
|
|
||||||
info->ctime = item.creationTime;
|
|
||||||
if (item.attributes & FILE_ATTRIBUTE_READONLY) {
|
|
||||||
info->access = 0444; // Read
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
info->access = 0666; // Read/Write
|
|
||||||
}
|
|
||||||
if (item.attributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
||||||
info->access |= 0111; // Execute
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetFileInfoUWP(std::string path, File::FileInfo* info) {
|
|
||||||
bool state = false;
|
|
||||||
VERBOSE_LOG(FILESYS, "GetFileInfoUWP (%s)", path.c_str());
|
|
||||||
auto itemInfo = GetItemInfoUWP(path);
|
|
||||||
if (itemInfo.attributes != INVALID_FILE_ATTRIBUTES) {
|
|
||||||
UpdateFileInfoByItemInfo(itemInfo, info);
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
VERBOSE_LOG(FILESYS, "GetFileInfoUWP failed! (%s)", path.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <list>
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include "StorageInfo.h"
|
|
||||||
#include "Common/File/Path.h"
|
|
||||||
#include "Common/File/DirListing.h"
|
|
||||||
|
|
||||||
bool ItemsInfoUWPToFilesInfo(std::list<ItemInfoUWP> items,std::vector<File::FileInfo>* files, const char* filter, std::set<std::string> filters);
|
|
||||||
bool GetFileInfoUWP(std::string path, File::FileInfo* info);
|
|
|
@ -4,30 +4,10 @@
|
||||||
// Telegram: @basharastifan
|
// Telegram: @basharastifan
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
// GitHub: https://github.com/basharast/UWP2Win32
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// GetDataFromLocalSettings(Platform::String^ key)
|
|
||||||
// AddDataToLocalSettings(Platform::String^ key, Platform::String^ data, bool replace)
|
|
||||||
//
|
|
||||||
// AddFolderToFutureList(StorageFolder^ folder)
|
|
||||||
// AddFileToFutureList(StorageFile^ file)
|
|
||||||
//
|
|
||||||
// AddToAccessibleDirectories(StorageFolder^ folder)
|
|
||||||
// AddToAccessibleFiles(StorageFile^ file)
|
|
||||||
// UpdateDirectoriesByFutureList()
|
|
||||||
// UpdateFilesByFutureList()
|
|
||||||
// FillAccessLists()
|
|
||||||
//
|
|
||||||
// GetFolderByKey(Platform::String^ key)
|
|
||||||
// GetFileByKey(Platform::String^ key)
|
|
||||||
// AppendFolderByToken(Platform::String^ token)
|
|
||||||
// AppendFileByToken(Platform::String^ token)
|
|
||||||
|
|
||||||
#include "StorageConfig.h"
|
|
||||||
#include "StorageLog.h"
|
|
||||||
#include "StorageExtensions.h"
|
|
||||||
#include "StorageAsync.h"
|
#include "StorageAsync.h"
|
||||||
#include "StorageAccess.h"
|
#include "StorageAccess.h"
|
||||||
#include "StorageItemW.h"
|
#include "UWPUtil.h"
|
||||||
|
#include <Common/File/Path.h>
|
||||||
|
|
||||||
using namespace Platform;
|
using namespace Platform;
|
||||||
using namespace Windows::Storage;
|
using namespace Windows::Storage;
|
||||||
|
@ -36,8 +16,12 @@ using namespace Windows::Foundation::Collections;
|
||||||
using namespace Windows::Storage::AccessCache;
|
using namespace Windows::Storage::AccessCache;
|
||||||
using namespace Windows::ApplicationModel;
|
using namespace Windows::ApplicationModel;
|
||||||
|
|
||||||
// Main lookup list
|
std::list<std::string> alist;
|
||||||
std::list<StorageItemW> FutureAccessItems;
|
void AppendToAccessList(Platform::String^ path)
|
||||||
|
{
|
||||||
|
Path p(FromPlatformString(path));
|
||||||
|
alist.push_back(p.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
// Get value from app local settings
|
// Get value from app local settings
|
||||||
Platform::String^ GetDataFromLocalSettings(Platform::String^ key) {
|
Platform::String^ GetDataFromLocalSettings(Platform::String^ key) {
|
||||||
|
@ -54,7 +38,7 @@ Platform::String^ GetDataFromLocalSettings(Platform::String^ key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDataFromLocalSettings(std::string key) {
|
std::string GetDataFromLocalSettings(std::string key) {
|
||||||
return convert(GetDataFromLocalSettings(convert(key)));
|
return FromPlatformString(GetDataFromLocalSettings(ToPlatformString(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add or replace value in app local settings
|
// Add or replace value in app local settings
|
||||||
|
@ -77,31 +61,15 @@ bool AddDataToLocalSettings(Platform::String^ key, Platform::String^ data, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddDataToLocalSettings(std::string key, std::string data, bool replace) {
|
bool AddDataToLocalSettings(std::string key, std::string data, bool replace) {
|
||||||
return AddDataToLocalSettings(convert(key), convert(data),replace);
|
return AddDataToLocalSettings(ToPlatformString(key), ToPlatformString(data),replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add item to history list (FutureAccessItems)
|
|
||||||
void AddToAccessibleItems(IStorageItem^ item) {
|
|
||||||
bool isFolderAddedBefore = false;
|
|
||||||
for each (auto folderItem in FutureAccessItems) {
|
|
||||||
if (folderItem.Equal(item)) {
|
|
||||||
isFolderAddedBefore = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isFolderAddedBefore) {
|
|
||||||
FutureAccessItems.push_back(StorageItemW(item));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Add folder to future list (to avoid request picker again)
|
// Add folder to future list (to avoid request picker again)
|
||||||
void AddItemToFutureList(IStorageItem^ item) {
|
void AddItemToFutureList(IStorageItem^ item) {
|
||||||
try {
|
try {
|
||||||
if (item != nullptr) {
|
if (item != nullptr) {
|
||||||
Platform::String^ folderToken = AccessCache::StorageApplicationPermissions::FutureAccessList->Add(item);
|
Platform::String^ folderToken = AccessCache::StorageApplicationPermissions::FutureAccessList->Add(item);
|
||||||
AddToAccessibleItems(item);
|
AppendToAccessList(item->Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Platform::COMException^ e) {
|
catch (Platform::COMException^ e) {
|
||||||
|
@ -120,104 +88,30 @@ IStorageItem^ GetItemByKey(Platform::String^ key) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append folder by token to (FutureAccessFolders)
|
std::list<std::string> GetFutureAccessList() {
|
||||||
void AppendItemByToken(Platform::String^ token) {
|
if (alist.empty()) {
|
||||||
|
auto AccessList = AccessCache::StorageApplicationPermissions::FutureAccessList->Entries;
|
||||||
|
for (auto it = 0; it != AccessList->Size; ++it){
|
||||||
|
auto item = AccessList->GetAt(it);
|
||||||
try {
|
try {
|
||||||
|
auto token = item.Token;
|
||||||
if (token != nullptr && AccessCache::StorageApplicationPermissions::FutureAccessList->ContainsItem(token)) {
|
if (token != nullptr && AccessCache::StorageApplicationPermissions::FutureAccessList->ContainsItem(token)) {
|
||||||
IStorageItem^ storageItem;
|
IStorageItem^ storageItem;
|
||||||
ExecuteTask(storageItem, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(token));
|
ExecuteTask(storageItem, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(token));
|
||||||
AddToAccessibleItems(storageItem);
|
if (storageItem != nullptr) {
|
||||||
}
|
AppendToAccessList(storageItem->Path);
|
||||||
}
|
|
||||||
catch (Platform::COMException^ e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the history list by the future list (to restore all the picked items)
|
|
||||||
void UpdateItemsByFutureList() {
|
|
||||||
auto AccessList = AccessCache::StorageApplicationPermissions::FutureAccessList->Entries;
|
|
||||||
for each (auto ListItem in AccessList) {
|
|
||||||
Platform::String^ itemToken = ListItem.Token;
|
|
||||||
AppendItemByToken(itemToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fillListsCalled = false;
|
|
||||||
bool fillListInProgress = false;
|
|
||||||
void FillLookupList() {
|
|
||||||
if (fillListsCalled) {
|
|
||||||
// Should be called only once
|
|
||||||
// but let's wait in case we got too calls at once
|
|
||||||
CoreWindow^ corewindow = CoreWindow::GetForCurrentThread();
|
|
||||||
while (fillListInProgress)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (corewindow) {
|
|
||||||
corewindow->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
corewindow = CoreWindow::GetForCurrentThread();
|
AccessCache::StorageApplicationPermissions::FutureAccessList->Remove(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (...) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fillListsCalled = true;
|
|
||||||
fillListInProgress = true;
|
|
||||||
// Clean access list from any deleted/moved items
|
|
||||||
for each (auto listItem in AccessCache::StorageApplicationPermissions::FutureAccessList->Entries) {
|
|
||||||
try {
|
|
||||||
IStorageItem^ test;
|
|
||||||
ExecuteTask(test, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(listItem.Token));
|
|
||||||
if (test == nullptr) {
|
|
||||||
// Access denied or file moved/deleted
|
|
||||||
AccessCache::StorageApplicationPermissions::FutureAccessList->Remove(listItem.Token);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Platform::COMException^ e) {
|
catch (Platform::COMException^ e) {
|
||||||
// Access denied or file moved/deleted
|
|
||||||
AccessCache::StorageApplicationPermissions::FutureAccessList->Remove(listItem.Token);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get files/folders selected by the user
|
AppendToAccessList(ApplicationData::Current->LocalFolder->Path);
|
||||||
UpdateItemsByFutureList();
|
AppendToAccessList(ApplicationData::Current->TemporaryFolder->Path);
|
||||||
|
}
|
||||||
// Append known folders
|
return alist;
|
||||||
#if APPEND_APP_LOCALDATA_LOCATION
|
|
||||||
AddToAccessibleItems(ApplicationData::Current->LocalFolder);
|
|
||||||
AddToAccessibleItems(ApplicationData::Current->TemporaryFolder);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if APPEND_APP_INSTALLATION_LOCATION
|
|
||||||
AddToAccessibleItems(Package::Current->InstalledLocation);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if APPEND_DOCUMENTS_LOCATION
|
|
||||||
// >>>>DOCUMENTS (requires 'documentsLibrary' capability)
|
|
||||||
AddToAccessibleItems(KnownFolders::DocumentsLibrary);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if APPEND_VIDEOS_LOCATION
|
|
||||||
// >>>>VIDEOS (requires 'videosLibrary' capability)
|
|
||||||
AddToAccessibleItems(KnownFolders::VideosLibrary);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if APPEND_PICTURES_LOCATION
|
|
||||||
// >>>>VIDEOS (requires 'picturesLibrary' capability)
|
|
||||||
AddToAccessibleItems(KnownFolders::PicturesLibrary);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if APPEND_MUSIC_LOCATION
|
|
||||||
// >>>>MUSIC (requires 'musicLibrary' capability)
|
|
||||||
AddToAccessibleItems(KnownFolders::MusicLibrary);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// No need to append `RemovableDevices`
|
|
||||||
// they will be allowed for access once you added the capability
|
|
||||||
|
|
||||||
fillListInProgress = false;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,12 @@
|
||||||
// Telegram: @basharastifan
|
// Telegram: @basharastifan
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
// GitHub: https://github.com/basharast/UWP2Win32
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// GetDataFromLocalSettings(std::string key)
|
|
||||||
// AddDataToLocalSettings(std::string key, std::string data, bool replace)
|
|
||||||
//
|
|
||||||
// FillLookupList()
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// Local settings
|
// Local settings
|
||||||
std::string GetDataFromLocalSettings(std::string key);
|
std::string GetDataFromLocalSettings(std::string key);
|
||||||
bool AddDataToLocalSettings(std::string key, std::string data, bool replace);
|
bool AddDataToLocalSettings(std::string key, std::string data, bool replace);
|
||||||
|
std::list<std::string> GetFutureAccessList();
|
||||||
// Lookup list
|
|
||||||
void FillLookupList();
|
|
||||||
|
|
|
@ -7,20 +7,20 @@
|
||||||
// Thanks to RetroArch/Libretro team for this idea
|
// Thanks to RetroArch/Libretro team for this idea
|
||||||
// This is improved version of the original idea
|
// This is improved version of the original idea
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// ExecuteTask(out, task) [for IAsyncOperation]
|
|
||||||
// ExecuteTask(out, task, def) [for IAsyncOperation]
|
|
||||||
// ExecuteTask(action) [for IAsyncAction such as 'Delete']
|
|
||||||
|
|
||||||
#include "StorageAsync.h"
|
#include "StorageAsync.h"
|
||||||
|
|
||||||
bool ActionPass(Windows::Foundation::IAsyncAction^ action)
|
bool ActionPass(Windows::Foundation::IAsyncAction^ action)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
return TaskHandler<bool>([&]() {
|
return TaskHandler<bool>([&]() {
|
||||||
return concurrency::create_task(action).then([]() {
|
return concurrency::create_task(action).then([]() {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}, false);
|
}, false);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async action such as 'Delete' file
|
// Async action such as 'Delete' file
|
||||||
|
|
|
@ -7,11 +7,6 @@
|
||||||
// Thanks to RetroArch/Libretro team for this idea
|
// Thanks to RetroArch/Libretro team for this idea
|
||||||
// This is improved version of the original idea
|
// This is improved version of the original idea
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// ExecuteTask(out, task) [for IAsyncOperation]
|
|
||||||
// ExecuteTask(out, task, def) [for IAsyncOperation]
|
|
||||||
// ExecuteTask(action) [for IAsyncAction such as 'Delete']
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
@ -20,8 +15,8 @@
|
||||||
#include <wrl.h>
|
#include <wrl.h>
|
||||||
#include <wrl/implements.h>
|
#include <wrl/implements.h>
|
||||||
|
|
||||||
#include "StorageLog.h"
|
#include "Common/Log.h"
|
||||||
#include "StorageExtensions.h"
|
#include "UWPUtil.h"
|
||||||
|
|
||||||
using namespace Windows::UI::Core;
|
using namespace Windows::UI::Core;
|
||||||
|
|
||||||
|
@ -42,7 +37,7 @@ T TaskHandler(std::function<concurrency::task<T>()> wtask, T def)
|
||||||
}
|
}
|
||||||
catch (Platform::Exception^ exception_)
|
catch (Platform::Exception^ exception_)
|
||||||
{
|
{
|
||||||
UWP_ERROR_LOG(UWPSMT, convertToChar(exception_->Message));
|
ERROR_LOG(FILESYS, FromPlatformString(exception_->Message).c_str());
|
||||||
}
|
}
|
||||||
done = true;
|
done = true;
|
||||||
});
|
});
|
||||||
|
@ -86,7 +81,12 @@ bool ActionPass(Windows::Foundation::IAsyncAction^ action);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation<T>^ task)
|
void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation<T>^ task)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
out = TaskPass<T>(task, T());
|
out = TaskPass<T>(task, T());
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
out = T();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// For specific return default value
|
// For specific return default value
|
||||||
|
@ -96,7 +96,12 @@ void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation<T>^ task)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation<T>^ task, T def)
|
void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation<T>^ task, T def)
|
||||||
{
|
{
|
||||||
|
try{
|
||||||
out = TaskPass<T>(task, def);
|
out = TaskPass<T>(task, def);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
out = def;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// Known locations
|
|
||||||
// ACTIVATE BELOW ONLY IF YOU ADDED THE CAPABILITY
|
|
||||||
#define APPEND_APP_LOCALDATA_LOCATION 1 // recommended to be always 1
|
|
||||||
#define APPEND_APP_INSTALLATION_LOCATION 1 // recommended to be always 1
|
|
||||||
#define APPEND_DOCUMENTS_LOCATION 0 // (requires 'documentsLibrary' capability)
|
|
||||||
#define APPEND_VIDEOS_LOCATION 0 // (requires 'videosLibrary' capability)
|
|
||||||
#define APPEND_MUSIC_LOCATION 0 // (requires musicLibrary' capability)
|
|
||||||
#define APPEND_PICTURES_LOCATION 0 // (requires 'picturesLibrary' capability)
|
|
||||||
|
|
||||||
|
|
||||||
// Working folder
|
|
||||||
// set this value by calling `SetWorkingFolder` from `StorageManager.h`
|
|
||||||
static std::string AppWorkingFolder;
|
|
|
@ -1,316 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// replace(std::string& str, const std::string& from, const std::string& to)
|
|
||||||
// replace2(const std::string str, const std::string& from, const std::string& to)
|
|
||||||
// split(const std::string s, char seperator)
|
|
||||||
//
|
|
||||||
// isChild(std::string parent, std::string child)
|
|
||||||
// isParent(std::string parent, std::string child, std::string childName)
|
|
||||||
//
|
|
||||||
// iequals(const std::string a, const std::string b) case-insenstive
|
|
||||||
// equals(const std::string a, const std::string b) case-senstive
|
|
||||||
// ends_with(std::string const& value, std::string const& ending)
|
|
||||||
// starts_with(std::string str, std::string prefix)
|
|
||||||
//
|
|
||||||
// convert(const std::string input)
|
|
||||||
// convertToWString(const std::string input)
|
|
||||||
// convert(Platform::String^ input)
|
|
||||||
// convert(std::wstring input)
|
|
||||||
// convert(const char* input)
|
|
||||||
// convertToLPCWSTR(Platform::String^ input)
|
|
||||||
// convertToLPCWSTR(std::string input)
|
|
||||||
// convertToChar(Platform::String^ input)
|
|
||||||
//
|
|
||||||
// tolower(std::string& input)
|
|
||||||
// tolower(Platform::String^ &input)
|
|
||||||
// toupper(std::string& input)
|
|
||||||
// toupper(Platform::String^& input)
|
|
||||||
//
|
|
||||||
// windowsPath(std::string& path)
|
|
||||||
// windowsPath(Platform::String^ &path)
|
|
||||||
// merge(std::string targetFullPath, std::string subFullPath)
|
|
||||||
//
|
|
||||||
// findInList(std::list<T>& inputList, T& str)
|
|
||||||
// isWriteMode(const char* mode)
|
|
||||||
// getSubRoot(std::string parent, std::string child)
|
|
||||||
|
|
||||||
#include "StorageExtensions.h"
|
|
||||||
|
|
||||||
#pragma region Inernal Helpers
|
|
||||||
std::string make_string(const std::wstring& wstring)
|
|
||||||
{
|
|
||||||
if (wstring.empty())
|
|
||||||
{
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
size_t pos;
|
|
||||||
size_t begin = 0;
|
|
||||||
std::string ret;
|
|
||||||
size_t size;
|
|
||||||
pos = wstring.find(static_cast<wchar_t>(0), begin);
|
|
||||||
while (pos != std::wstring::npos && begin < wstring.length())
|
|
||||||
{
|
|
||||||
std::wstring segment = std::wstring(&wstring[begin], pos - begin);
|
|
||||||
size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &segment[0], (int)segment.size(), NULL, 0, NULL, NULL);
|
|
||||||
std::string converted = std::string(size, 0);
|
|
||||||
WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &segment[0], (int)segment.size(), &converted[0], (int)converted.size(), NULL, NULL);
|
|
||||||
ret.append(converted);
|
|
||||||
ret.append({ 0 });
|
|
||||||
begin = pos + 1;
|
|
||||||
pos = wstring.find(static_cast<wchar_t>(0), begin);
|
|
||||||
}
|
|
||||||
if (begin <= wstring.length())
|
|
||||||
{
|
|
||||||
std::wstring segment = std::wstring(&wstring[begin], wstring.length() - begin);
|
|
||||||
size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &segment[0], (int)segment.size(), NULL, 0, NULL, NULL);
|
|
||||||
std::string converted = std::string(size, 0);
|
|
||||||
WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &segment[0], (int)segment.size(), &converted[0], (int)converted.size(), NULL, NULL);
|
|
||||||
ret.append(converted);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring make_wstring(const std::string& string)
|
|
||||||
{
|
|
||||||
size_t requiredSize = 0;
|
|
||||||
std::wstring answer;
|
|
||||||
wchar_t* pWTempString = NULL;
|
|
||||||
|
|
||||||
requiredSize = mbstowcs(NULL, string.c_str(), 0) + 1;
|
|
||||||
|
|
||||||
pWTempString = (wchar_t*)malloc(requiredSize * sizeof(wchar_t));
|
|
||||||
if (pWTempString != NULL)
|
|
||||||
{
|
|
||||||
size_t size = mbstowcs(pWTempString, string.c_str(), requiredSize);
|
|
||||||
if (size != (size_t)(-1))
|
|
||||||
{
|
|
||||||
answer = pWTempString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pWTempString != NULL)
|
|
||||||
{
|
|
||||||
free(pWTempString);
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
bool replace(std::string& str, const std::string& from, const std::string& to) {
|
|
||||||
size_t start_pos = str.find(from);
|
|
||||||
if (start_pos == std::string::npos)
|
|
||||||
return false;
|
|
||||||
str.replace(start_pos, from.length(), to);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string replace2(const std::string str, const std::string& from, const std::string& to) {
|
|
||||||
std::string cpy = str;
|
|
||||||
size_t start_pos = cpy.find(from);
|
|
||||||
if (start_pos == std::string::npos)
|
|
||||||
return str;
|
|
||||||
cpy.replace(start_pos, from.length(), to);
|
|
||||||
return cpy;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> split(const std::string s, char seperator)
|
|
||||||
{
|
|
||||||
std::vector<std::string> output;
|
|
||||||
|
|
||||||
std::string::size_type prev_pos = 0, pos = 0;
|
|
||||||
|
|
||||||
while ((pos = s.find(seperator, pos)) != std::string::npos)
|
|
||||||
{
|
|
||||||
std::string substring(s.substr(prev_pos, pos - prev_pos));
|
|
||||||
|
|
||||||
output.push_back(substring);
|
|
||||||
|
|
||||||
prev_pos = ++pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
output.push_back(s.substr(prev_pos, pos - prev_pos));
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isChild(std::string parent, std::string child) {
|
|
||||||
windowsPath(parent);
|
|
||||||
windowsPath(child);
|
|
||||||
tolower(parent);
|
|
||||||
tolower(child);
|
|
||||||
|
|
||||||
return child.find(parent) != std::string::npos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parent full path, child full path, child name only
|
|
||||||
bool isParent(std::string parent, std::string child, std::string childName) {
|
|
||||||
windowsPath(parent);
|
|
||||||
windowsPath(child);
|
|
||||||
tolower(parent);
|
|
||||||
tolower(child);
|
|
||||||
tolower(childName);
|
|
||||||
|
|
||||||
parent.append("\\"+ childName);
|
|
||||||
return parent == child;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iequals(const std::string a, const std::string b)
|
|
||||||
{
|
|
||||||
auto result = _stricmp(a.c_str(), b.c_str());
|
|
||||||
return result == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool equals(const std::string a, const std::string b)
|
|
||||||
{
|
|
||||||
auto result = strcmp(a.c_str(), b.c_str());
|
|
||||||
return result == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ends_with(std::string const& value, std::string const& ending)
|
|
||||||
{
|
|
||||||
if (ending.size() > value.size()) return false;
|
|
||||||
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool starts_with(std::string str, std::string prefix)
|
|
||||||
{
|
|
||||||
return str.size() >= prefix.size() && 0 == str.compare(0, prefix.size(), prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
Platform::String^ convert(const std::string input)
|
|
||||||
{
|
|
||||||
auto wstr = make_wstring(input);
|
|
||||||
Platform::String^ output = ref new Platform::String(wstr.c_str());
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring convertToWString(const std::string input)
|
|
||||||
{
|
|
||||||
auto wstr = make_wstring(input);
|
|
||||||
return wstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string convert(Platform::String^ input) {
|
|
||||||
std::wstring wsstr(input->Data());
|
|
||||||
auto utf8Str = make_string(wsstr); // UTF8-encoded text
|
|
||||||
|
|
||||||
return utf8Str;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string convert(std::wstring input) {
|
|
||||||
auto utf8Str = make_string(input); // UTF8-encoded text
|
|
||||||
|
|
||||||
return utf8Str;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string convert(const char* input) {
|
|
||||||
std::wstring wsstr((const wchar_t*)input);
|
|
||||||
auto utf8Str = make_string(wsstr); // UTF8-encoded text
|
|
||||||
|
|
||||||
return utf8Str;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPCWSTR convertToLPCWSTR(std::string input) {
|
|
||||||
std::wstring stemp = make_wstring(input);
|
|
||||||
LPCWSTR sw = stemp.c_str();
|
|
||||||
|
|
||||||
return sw;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPCWSTR convertToLPCWSTR(Platform::String^ input) {
|
|
||||||
std::string inputString = convert(input);
|
|
||||||
std::wstring stemp = make_wstring(inputString);
|
|
||||||
LPCWSTR sw = stemp.c_str();
|
|
||||||
|
|
||||||
return sw;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* convertToChar(Platform::String^ input) {
|
|
||||||
std::string output = convert(input);
|
|
||||||
return output.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void tolower(std::string& input) {
|
|
||||||
std::transform(input.begin(), input.end(), input.begin(), std::tolower);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tolower(Platform::String^ &input) {
|
|
||||||
std::string temp = convert(input);
|
|
||||||
tolower(temp);
|
|
||||||
input = convert(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void toupper(std::string& input) {
|
|
||||||
std::transform(input.begin(), input.end(), input.begin(), std::toupper);
|
|
||||||
}
|
|
||||||
|
|
||||||
void toupper(Platform::String^& input) {
|
|
||||||
std::string temp = convert(input);
|
|
||||||
toupper(temp);
|
|
||||||
input = convert(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void windowsPath(std::string& path) {
|
|
||||||
std::replace(path.begin(), path.end(), '/', '\\');
|
|
||||||
}
|
|
||||||
|
|
||||||
void windowsPath(Platform::String^ &path) {
|
|
||||||
std::string temp = convert(path);
|
|
||||||
windowsPath(temp);
|
|
||||||
path = convert(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string merge(std::string targetFullPath, std::string subFullPath) {
|
|
||||||
size_t pos = subFullPath.rfind('\\');
|
|
||||||
if (pos != std::string::npos) {
|
|
||||||
auto itemName = subFullPath.substr(pos + 1);
|
|
||||||
std::string newPath = targetFullPath + "\\" + itemName;
|
|
||||||
return newPath;
|
|
||||||
}
|
|
||||||
return targetFullPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string& rtrim(std::string& s, const char* t)
|
|
||||||
{
|
|
||||||
s.erase(s.find_last_not_of(t) + 1);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// trim from beginning of string (left)
|
|
||||||
std::string& ltrim(std::string& s, const char* t)
|
|
||||||
{
|
|
||||||
s.erase(0, s.find_first_not_of(t));
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// trim from both ends of string (right then left)
|
|
||||||
std::string& trim(std::string& s, const char* t)
|
|
||||||
{
|
|
||||||
return ltrim(rtrim(s, t), t);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isWriteMode(const char* mode) {
|
|
||||||
return (!strcmp(mode, "w") || !strcmp(mode, "wb") || !strcmp(mode, "wt") || !strcmp(mode, "at") || !strcmp(mode, "a"));
|
|
||||||
}
|
|
||||||
bool isAppendMode(const char* mode) {
|
|
||||||
return (!strcmp(mode, "at") || !strcmp(mode, "a"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parent and child full path
|
|
||||||
std::string getSubRoot(std::string parent, std::string child) {
|
|
||||||
windowsPath(parent);
|
|
||||||
windowsPath(child);
|
|
||||||
auto childCut = child;
|
|
||||||
replace(childCut, (parent + "\\"), "");
|
|
||||||
size_t len = childCut.find_first_of('\\', 0);
|
|
||||||
auto subRoot = childCut.substr(0, len);
|
|
||||||
|
|
||||||
return parent + "\\"+ subRoot;
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// replace(std::string& str, const std::string& from, const std::string& to)
|
|
||||||
// replace2(const std::string str, const std::string& from, const std::string& to)
|
|
||||||
// split(const std::string s, char seperator)
|
|
||||||
//
|
|
||||||
// isChild(std::string parent, std::string child)
|
|
||||||
// isParent(std::string parent, std::string child, std::string childName)
|
|
||||||
//
|
|
||||||
// iequals(const std::string a, const std::string b) case-insenstive
|
|
||||||
// equals(const std::string a, const std::string b) case-senstive
|
|
||||||
// ends_with(std::string const& value, std::string const& ending)
|
|
||||||
//
|
|
||||||
// convert(const std::string input)
|
|
||||||
// convertToWString(const std::string input)
|
|
||||||
// convert(Platform::String^ input)
|
|
||||||
// convert(std::wstring input)
|
|
||||||
// convert(const char* input)
|
|
||||||
// convertToLPCWSTR(Platform::String^ input)
|
|
||||||
// convertToLPCWSTR(std::string input)
|
|
||||||
// convertToChar(Platform::String^ input)
|
|
||||||
//
|
|
||||||
// tolower(std::string& input)
|
|
||||||
// tolower(Platform::String^ &input)
|
|
||||||
// toupper(std::string& input)
|
|
||||||
// toupper(Platform::String^& input)
|
|
||||||
//
|
|
||||||
// windowsPath(std::string& path)
|
|
||||||
// windowsPath(Platform::String^ &path)
|
|
||||||
// merge(std::string targetFullPath, std::string subFullPath)
|
|
||||||
//
|
|
||||||
// findInList(std::list<T>& inputList, T& str)
|
|
||||||
// isWriteMode(const char* mode)
|
|
||||||
// getSubRoot(std::string parent, std::string child)
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
bool replace(std::string& str, const std::string& from, const std::string& to);
|
|
||||||
std::string replace2(const std::string str, const std::string& from, const std::string& to);
|
|
||||||
std::vector<std::string> split(const std::string s, char seperator);
|
|
||||||
// Parent full path, child full path
|
|
||||||
bool isChild(std::string parent, std::string child);
|
|
||||||
// Parent full path, child full path, child name only
|
|
||||||
bool isParent(std::string parent, std::string child, std::string childName);
|
|
||||||
|
|
||||||
bool iequals(const std::string a, const std::string b);
|
|
||||||
bool equals(const std::string a, const std::string b);
|
|
||||||
bool ends_with(std::string const& value, std::string const& ending);
|
|
||||||
bool starts_with(std::string str, std::string prefix);
|
|
||||||
|
|
||||||
Platform::String^ convert(const std::string input);
|
|
||||||
std::wstring convertToWString(const std::string input);
|
|
||||||
std::string convert(Platform::String^ input);
|
|
||||||
std::string convert(std::wstring input);
|
|
||||||
std::string convert(const char* input);
|
|
||||||
LPCWSTR convertToLPCWSTR(std::string input);
|
|
||||||
LPCWSTR convertToLPCWSTR(Platform::String^ input);
|
|
||||||
const char* convertToChar(Platform::String^ input);
|
|
||||||
|
|
||||||
void tolower(std::string& input);
|
|
||||||
void tolower(Platform::String^& input);
|
|
||||||
void toupper(std::string& input);
|
|
||||||
void toupper(Platform::String^& input);
|
|
||||||
|
|
||||||
void windowsPath(std::string& path);
|
|
||||||
void windowsPath(Platform::String^& path);
|
|
||||||
|
|
||||||
std::string merge(std::string targetFullPath, std::string subFullPath);
|
|
||||||
|
|
||||||
std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v");
|
|
||||||
std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v");
|
|
||||||
std::string& trim(std::string& s, const char* t = " \t\n\r\f\v");
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool findInList(std::list<T>& inputList, T& str) {
|
|
||||||
return (std::find(inputList.begin(), inputList.end(), str) != inputList.end());
|
|
||||||
};
|
|
||||||
|
|
||||||
bool isWriteMode(const char* mode);
|
|
||||||
bool isAppendMode(const char* mode);
|
|
||||||
// Parent and child full path
|
|
||||||
std::string getSubRoot(std::string parent, std::string child);
|
|
||||||
|
|
|
@ -1,281 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// IsValid()
|
|
||||||
// Delete()
|
|
||||||
// Rename(std::string name)
|
|
||||||
// Copy(StorageFolder^ folder)
|
|
||||||
// Move(StorageFolder^ folder)
|
|
||||||
// GetPath()
|
|
||||||
// GetName()
|
|
||||||
// Equal(std::string path)
|
|
||||||
// Equal(Path path)
|
|
||||||
// Equal(Platform::String^ path)
|
|
||||||
// Equal(StorageFile^ file)
|
|
||||||
// GetProperties()
|
|
||||||
// GetSize(bool updateCache)
|
|
||||||
// GetHandle(HANDLE* handle, HANDLE_ACCESS_OPTIONS access)
|
|
||||||
// GetStream(const char* mode)
|
|
||||||
// GetHandle(FILE* file)
|
|
||||||
// GetStorageFile()
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include <io.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "Common/Log.h"
|
|
||||||
|
|
||||||
#include "StorageLog.h"
|
|
||||||
#include "StoragePath.h"
|
|
||||||
#include "StorageExtensions.h"
|
|
||||||
#include "StorageHandler.h"
|
|
||||||
#include "StorageAsync.h"
|
|
||||||
#include "StorageInfo.h"
|
|
||||||
|
|
||||||
using namespace Platform;
|
|
||||||
using namespace Windows::Storage;
|
|
||||||
using namespace Windows::Foundation;
|
|
||||||
using namespace Windows::Storage::FileProperties;
|
|
||||||
|
|
||||||
class StorageFileW {
|
|
||||||
public:
|
|
||||||
StorageFileW() {
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageFileW(StorageFile^ file) {
|
|
||||||
storageFile = file;
|
|
||||||
fileSize = 0;
|
|
||||||
}
|
|
||||||
StorageFileW(IStorageItem^ file) {
|
|
||||||
storageFile = (StorageFile^)file;
|
|
||||||
fileSize = 0;
|
|
||||||
}
|
|
||||||
~StorageFileW() {
|
|
||||||
delete storageFile;
|
|
||||||
delete properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect if main storage file is not null
|
|
||||||
bool IsValid() {
|
|
||||||
return (storageFile != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete file
|
|
||||||
bool Delete() {
|
|
||||||
bool state = ExecuteTask(storageFile->DeleteAsync());
|
|
||||||
if (state) {
|
|
||||||
storageFile = nullptr;
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rename file
|
|
||||||
bool Rename(std::string name) {
|
|
||||||
auto path = PathUWP(name);
|
|
||||||
if (path.IsAbsolute()) {
|
|
||||||
name = path.GetFilename();
|
|
||||||
}
|
|
||||||
return ExecuteTask(storageFile->RenameAsync(convert(name)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy file
|
|
||||||
bool Copy(StorageFolder^ folder, std::string name) {
|
|
||||||
bool state = false;
|
|
||||||
StorageFile^ newFile;
|
|
||||||
ExecuteTask(newFile, storageFile->CopyAsync(folder, convert(name), NameCollisionOption::ReplaceExisting));
|
|
||||||
if (newFile != nullptr) {
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move file
|
|
||||||
bool Move(StorageFolder^ folder, std::string name) {
|
|
||||||
bool state = false;
|
|
||||||
IStorageItem^ newFile;
|
|
||||||
state = ExecuteTask(storageFile->MoveAsync(folder, convert(name), NameCollisionOption::GenerateUniqueName));
|
|
||||||
if (state) {
|
|
||||||
ExecuteTask(newFile, folder->TryGetItemAsync(storageFile->Name));
|
|
||||||
if (newFile != nullptr) {
|
|
||||||
storageFile = (StorageFile^)newFile;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
state = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file path
|
|
||||||
std::string GetPath() {
|
|
||||||
return convert(storageFile->Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file name
|
|
||||||
std::string GetName() {
|
|
||||||
return convert(storageFile->Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare file with std::string
|
|
||||||
bool Equal(std::string path) {
|
|
||||||
std::string filePath = GetPath();
|
|
||||||
|
|
||||||
// Fix slashs back from '/' to '\'
|
|
||||||
windowsPath(path);
|
|
||||||
return iequals(filePath, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare file with Platform::String
|
|
||||||
bool Equal(Platform::String^ path) {
|
|
||||||
return storageFile->Path->Equals(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare file with Path
|
|
||||||
bool Equal(PathUWP path) {
|
|
||||||
return Equal(path.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare file with StorageFile
|
|
||||||
bool Equal(StorageFile^ file) {
|
|
||||||
return Equal(file->Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file size
|
|
||||||
__int64 GetSize(bool updateCache = false) {
|
|
||||||
if (fileSize == 0 || updateCache) {
|
|
||||||
// Let's try getting size by handle first
|
|
||||||
HANDLE handle;
|
|
||||||
HRESULT hr = GetHandle(&handle);
|
|
||||||
if (handle == INVALID_HANDLE_VALUE || hr != S_OK) {
|
|
||||||
// We have no other option, fallback to UWP
|
|
||||||
fileSize = FetchProperties()->Size;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LARGE_INTEGER size{ 0 };
|
|
||||||
if (FALSE == GetFileSizeEx(handle, &size)) {
|
|
||||||
LARGE_INTEGER end_offset;
|
|
||||||
const LARGE_INTEGER zero{};
|
|
||||||
if (SetFilePointerEx(handle, zero, &end_offset, FILE_END) == 0) {
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fileSize = end_offset.QuadPart;
|
|
||||||
SetFilePointerEx(handle, zero, nullptr, FILE_BEGIN);
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fileSize = size.QuadPart;
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file handle
|
|
||||||
HRESULT GetHandle(HANDLE* handle, int accessMode = GENERIC_READ, int shareMode = FILE_SHARE_READ) {
|
|
||||||
return GetFileHandle(storageFile, handle, GetAccessMode(accessMode), GetShareMode(shareMode));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file stream
|
|
||||||
FILE* GetStream(const char* mode) {
|
|
||||||
HANDLE handle;
|
|
||||||
auto access = GENERIC_READ;
|
|
||||||
auto share = FILE_SHARE_READ;
|
|
||||||
bool isWrite = isWriteMode(mode);
|
|
||||||
if (isWrite) {
|
|
||||||
access = GENERIC_WRITE;
|
|
||||||
share = FILE_SHARE_WRITE;
|
|
||||||
}
|
|
||||||
HRESULT hr = GetHandle(&handle, access, share);
|
|
||||||
|
|
||||||
FILE* file{};
|
|
||||||
if (hr == S_OK && handle != INVALID_HANDLE_VALUE) {
|
|
||||||
int flags = _O_RDONLY;
|
|
||||||
if (isWrite) {
|
|
||||||
flags = _O_RDWR;
|
|
||||||
}
|
|
||||||
DEBUG_LOG(FILESYS, "Opening file (%s) with flag:%d mode:%s", GetPath().c_str(), flags, mode);
|
|
||||||
file = _fdopen(_open_osfhandle((intptr_t)handle, flags), mode);
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file handle from stream
|
|
||||||
HANDLE GetHandle(FILE* file) {
|
|
||||||
return (HANDLE)_get_osfhandle(_fileno(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file properties
|
|
||||||
FILE_BASIC_INFO* GetProperties() {
|
|
||||||
HANDLE handle;
|
|
||||||
HRESULT hr = GetHandle(&handle);
|
|
||||||
|
|
||||||
size_t size = sizeof(FILE_BASIC_INFO);
|
|
||||||
FILE_BASIC_INFO* information = (FILE_BASIC_INFO*)(malloc(size));
|
|
||||||
if(hr == S_OK && handle != INVALID_HANDLE_VALUE && information){
|
|
||||||
information->FileAttributes = (DWORD)storageFile->Attributes;
|
|
||||||
|
|
||||||
if (FALSE == GetFileInformationByHandleEx(handle, FileBasicInfo, information, (DWORD)size)) {
|
|
||||||
// Fallback to UWP method (Slow)
|
|
||||||
auto props = FetchProperties();
|
|
||||||
information->ChangeTime.QuadPart = props->DateModified.UniversalTime;
|
|
||||||
information->CreationTime.QuadPart = props->ItemDate.UniversalTime;
|
|
||||||
information->LastAccessTime.QuadPart = props->DateModified.UniversalTime;
|
|
||||||
information->LastWriteTime.QuadPart = props->DateModified.UniversalTime;
|
|
||||||
}
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return information;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get main storage file
|
|
||||||
StorageFile^ GetStorageFile() {
|
|
||||||
return storageFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t filetime_to_timet(LARGE_INTEGER ull) const {
|
|
||||||
return ull.QuadPart / 10000000ULL - 11644473600ULL;
|
|
||||||
}
|
|
||||||
ItemInfoUWP GetFileInfo() {
|
|
||||||
ItemInfoUWP info;
|
|
||||||
info.name = GetName();
|
|
||||||
info.fullName = GetPath();
|
|
||||||
info.isDirectory = false;
|
|
||||||
|
|
||||||
auto sProperties = GetProperties();
|
|
||||||
|
|
||||||
info.size = (uint64_t)GetSize();
|
|
||||||
info.lastAccessTime = (uint64_t)filetime_to_timet(sProperties->LastAccessTime);
|
|
||||||
info.lastWriteTime = (uint64_t)filetime_to_timet(sProperties->LastWriteTime);
|
|
||||||
info.changeTime = (uint64_t)filetime_to_timet(sProperties->ChangeTime);
|
|
||||||
info.creationTime = (uint64_t)filetime_to_timet(sProperties->CreationTime);
|
|
||||||
|
|
||||||
|
|
||||||
info.attributes = sProperties->FileAttributes;
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
StorageFile^ storageFile;
|
|
||||||
BasicProperties^ properties;
|
|
||||||
__int64 fileSize = 0;
|
|
||||||
|
|
||||||
BasicProperties^ FetchProperties() {
|
|
||||||
if (properties == nullptr) {
|
|
||||||
// Very bad and slow way in UWP to get size and other properties
|
|
||||||
// not preferred to be used on big list of files
|
|
||||||
ExecuteTask(properties, storageFile->GetBasicPropertiesAsync());
|
|
||||||
}
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,577 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// IsValid()
|
|
||||||
// GetPath()
|
|
||||||
// GetName()
|
|
||||||
// Delete()
|
|
||||||
// Equal(std::string path)
|
|
||||||
// Equal(Path path)
|
|
||||||
// Equal(Platform::String^ path)
|
|
||||||
// Equal(StorageFolder^ folder)
|
|
||||||
// GetSize(bool updateCache)
|
|
||||||
// CreateFolder(std::string name, bool replaceExisting)
|
|
||||||
// CreateFile(std::string name)
|
|
||||||
// Rename(std::string name)
|
|
||||||
// GetAllFiles(bool useWindowsIndexer)
|
|
||||||
// GetAllFolders(bool useWindowsIndexer)
|
|
||||||
// Contains(Path path, IStorageItem^& storageItem)
|
|
||||||
// Contains(std::string item)
|
|
||||||
// Copy(StorageFolderW folder)
|
|
||||||
// Move(StorageFolderW destination)
|
|
||||||
// GetHandle(HANDLE* handle, HANDLE_ACCESS_OPTIONS access)
|
|
||||||
// GetProperties()
|
|
||||||
// GetStorageFolder()
|
|
||||||
// GetFileStream(std::string name, const char* mode)
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include <collection.h>
|
|
||||||
|
|
||||||
#include "Common/Log.h"
|
|
||||||
|
|
||||||
#include "StorageLog.h"
|
|
||||||
#include "StoragePath.h"
|
|
||||||
#include "StorageExtensions.h"
|
|
||||||
#include "StorageHandler.h"
|
|
||||||
#include "StorageAsync.h"
|
|
||||||
#include "StorageFileW.h"
|
|
||||||
#include "StorageInfo.h"
|
|
||||||
|
|
||||||
using namespace Platform;
|
|
||||||
using namespace Windows::Storage;
|
|
||||||
using namespace Windows::Foundation;
|
|
||||||
using namespace Windows::Foundation::Collections;
|
|
||||||
using namespace Windows::Storage::FileProperties;
|
|
||||||
using namespace Windows::Storage::Search;
|
|
||||||
|
|
||||||
class StorageFolderW {
|
|
||||||
public:
|
|
||||||
StorageFolderW() {
|
|
||||||
}
|
|
||||||
StorageFolderW(StorageFolder^ folder) {
|
|
||||||
storageFolder = folder;
|
|
||||||
folderSize = 0;
|
|
||||||
}
|
|
||||||
StorageFolderW(IStorageItem^ folder) {
|
|
||||||
storageFolder = (StorageFolder^)folder;
|
|
||||||
folderSize = 0;
|
|
||||||
}
|
|
||||||
~StorageFolderW() {
|
|
||||||
delete storageFolder;
|
|
||||||
delete properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect if storage folder is not null
|
|
||||||
bool IsValid() {
|
|
||||||
return (storageFolder != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get folder path
|
|
||||||
std::string GetPath() {
|
|
||||||
return convert(storageFolder->Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete folder
|
|
||||||
bool Delete() {
|
|
||||||
bool state = ExecuteTask(storageFolder->DeleteAsync());
|
|
||||||
if (state) {
|
|
||||||
storageFolder = nullptr;
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare folder with std::string
|
|
||||||
bool Equal(std::string path) {
|
|
||||||
std::string folderPath = GetPath();
|
|
||||||
|
|
||||||
// Fix slashs back from '/' to '\'
|
|
||||||
windowsPath(path);
|
|
||||||
return iequals(folderPath, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare folder with Platform::String
|
|
||||||
bool Equal(Platform::String^ path) {
|
|
||||||
return storageFolder->Path->Equals(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare folder with Path
|
|
||||||
bool Equal(PathUWP path) {
|
|
||||||
return Equal(path.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare folder with StorageFolder
|
|
||||||
bool Equal(StorageFolder^ folder) {
|
|
||||||
return Equal(folder->Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get folder name
|
|
||||||
std::string GetName() {
|
|
||||||
return convert(storageFolder->Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new folder
|
|
||||||
bool CreateFolder(std::string name, bool replaceExisting = true) {
|
|
||||||
bool state = false;
|
|
||||||
StorageFolder^ newFolder;
|
|
||||||
ExecuteTask(newFolder, storageFolder->CreateFolderAsync(convert(name), replaceExisting ? CreationCollisionOption::ReplaceExisting : CreationCollisionOption::GenerateUniqueName));
|
|
||||||
|
|
||||||
if (newFolder != nullptr) {
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete newFolder;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new file
|
|
||||||
bool CreateFile(std::string name, bool replaceExisting = true) {
|
|
||||||
bool state = false;
|
|
||||||
StorageFile^ newFile;
|
|
||||||
ExecuteTask(newFile, storageFolder->CreateFileAsync(convert(name), replaceExisting ? CreationCollisionOption::ReplaceExisting : CreationCollisionOption::GenerateUniqueName));
|
|
||||||
|
|
||||||
if (newFile != nullptr) {
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete newFile;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rename folder
|
|
||||||
bool Rename(std::string name) {
|
|
||||||
auto path = PathUWP(name);
|
|
||||||
if (path.IsAbsolute()) {
|
|
||||||
name = path.GetFilename();
|
|
||||||
}
|
|
||||||
return ExecuteTask(storageFolder->RenameAsync(convert(name)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get files 1st level only, no deep scan
|
|
||||||
std::list<StorageFileW> GetFiles() {
|
|
||||||
std::list<StorageFileW> files;
|
|
||||||
|
|
||||||
IVectorView<StorageFile^>^ sFiles;
|
|
||||||
VERBOSE_LOG(FILESYS, "Getting files for %s", GetPath().c_str());
|
|
||||||
|
|
||||||
ExecuteTask(sFiles, storageFolder->GetFilesAsync());
|
|
||||||
if (sFiles != nullptr) {
|
|
||||||
for (auto it = 0; it != sFiles->Size; ++it) {
|
|
||||||
auto sItem = sFiles->GetAt(it);
|
|
||||||
if (sItem != nullptr) {
|
|
||||||
files.push_back(StorageFileW(sItem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete sFiles;
|
|
||||||
VERBOSE_LOG(FILESYS, "Total files added (%d) in (%s)", files.size(), GetPath().c_str());
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::list<StorageFolderW> GetFolders() {
|
|
||||||
std::list<StorageFolderW> folders;
|
|
||||||
|
|
||||||
IVectorView<StorageFolder^>^ sFolders;
|
|
||||||
VERBOSE_LOG(FILESYS, "Getting folders for %s", GetPath().c_str());
|
|
||||||
|
|
||||||
ExecuteTask(sFolders, storageFolder->GetFoldersAsync());
|
|
||||||
if (sFolders != nullptr) {
|
|
||||||
VERBOSE_LOG(FILESYS, "Sub folders founded (%d) in (%s)", sFolders->Size, GetPath().c_str());
|
|
||||||
for (auto it = 0; it != sFolders->Size; ++it) {
|
|
||||||
auto sItem = sFolders->GetAt(it);
|
|
||||||
if (sItem != nullptr) {
|
|
||||||
folders.push_back(StorageFolderW(sItem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete sFolders;
|
|
||||||
VERBOSE_LOG(FILESYS, "Total folders added (%d) in (%s)", folders.size(), GetPath().c_str());
|
|
||||||
|
|
||||||
return folders;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all files including files in sub folders (deep scan)
|
|
||||||
std::list<StorageFileW> GetAllFiles(bool useWindowsIndexer = false) {
|
|
||||||
std::list<StorageFileW> files; // No structure one-level list
|
|
||||||
|
|
||||||
VERBOSE_LOG(FILESYS, "Getting all files for %s", GetPath().c_str());
|
|
||||||
IVectorView<StorageFile^>^ sFiles;
|
|
||||||
|
|
||||||
// Set query options to create groups of files within result
|
|
||||||
QueryOptions^ queryOptions = ref new QueryOptions(CommonFolderQuery::DefaultQuery);
|
|
||||||
queryOptions->FolderDepth = FolderDepth::Deep; // Search in all levels
|
|
||||||
|
|
||||||
// Windows indexer is very bad, it will return missing results if the files recently copied
|
|
||||||
// It's better to search without it, even if it will be slower
|
|
||||||
queryOptions->IndexerOption = useWindowsIndexer ? IndexerOption::UseIndexerWhenAvailable : IndexerOption::DoNotUseIndexer;
|
|
||||||
StorageFileQueryResult^ filesResult = storageFolder->CreateFileQueryWithOptions(queryOptions);
|
|
||||||
|
|
||||||
// Windows search query is slow but it's the only solution (or we need to build safe recursive function)
|
|
||||||
// Regular 'StorageFolder->GetFilesAsync()' will not search in sub dirs
|
|
||||||
ExecuteTask(sFiles, filesResult->GetFilesAsync());
|
|
||||||
|
|
||||||
if (sFiles != nullptr) {
|
|
||||||
for (auto it = 0; it != sFiles->Size; ++it) {
|
|
||||||
auto sItem = sFiles->GetAt(it);
|
|
||||||
if (sItem != nullptr) {
|
|
||||||
files.push_back(StorageFileW(sItem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete sFiles;
|
|
||||||
|
|
||||||
VERBOSE_LOG(FILESYS, "Total files added (%d) in (%s)", files.size(), GetPath().c_str());
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all sub folders (deep scan)
|
|
||||||
std::list<StorageFolderW> GetAllFolders(bool useWindowsIndexer = false) {
|
|
||||||
std::list<StorageFolderW> folders;
|
|
||||||
|
|
||||||
IVectorView<StorageFolder^>^ sFolders;
|
|
||||||
VERBOSE_LOG(FILESYS, "Getting all folders for %s", GetPath().c_str());
|
|
||||||
|
|
||||||
// Set query options to create groups of files within result
|
|
||||||
QueryOptions^ queryOptions = ref new QueryOptions(CommonFolderQuery::DefaultQuery);
|
|
||||||
queryOptions->FolderDepth = FolderDepth::Deep; // Search in all levels
|
|
||||||
|
|
||||||
// Windows indexer is very bad, it will return missing results if the files recently copied
|
|
||||||
// It's better to search without it, even if it will be slower
|
|
||||||
queryOptions->IndexerOption = useWindowsIndexer ? IndexerOption::UseIndexerWhenAvailable : IndexerOption::DoNotUseIndexer;
|
|
||||||
StorageFolderQueryResult^ foldersResult = storageFolder->CreateFolderQueryWithOptions(queryOptions);
|
|
||||||
|
|
||||||
// Windows search query is slow but it's the only solution (or we need to build safe recursive function)
|
|
||||||
// Regular 'StorageFolder->GetFoldersAsync()' will not search in sub dirs
|
|
||||||
ExecuteTask(sFolders, foldersResult->GetFoldersAsync());
|
|
||||||
if (sFolders != nullptr) {
|
|
||||||
VERBOSE_LOG(FILESYS, "Sub folders founded (%d) in (%s)", sFolders->Size, GetPath().c_str());
|
|
||||||
for (auto it = 0; it != sFolders->Size; ++it) {
|
|
||||||
auto sItem = sFolders->GetAt(it);
|
|
||||||
if (sItem != nullptr) {
|
|
||||||
folders.push_back(StorageFolderW(sItem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete sFolders;
|
|
||||||
VERBOSE_LOG(FILESYS, "Total folders added (%d) in (%s)", folders.size(), GetPath().c_str());
|
|
||||||
|
|
||||||
return folders;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure item path without root
|
|
||||||
std::string CleanItemPath(PathUWP& path) {
|
|
||||||
std::string itemName = path.ToString();
|
|
||||||
// Ensure slashs changed from '/' to '\'
|
|
||||||
windowsPath(itemName);
|
|
||||||
|
|
||||||
if (path.IsAbsolute()) {
|
|
||||||
|
|
||||||
// If full path detected item in sub location,
|
|
||||||
// root path must be removed
|
|
||||||
replace(itemName, convert(storageFolder->Path + "\\"), "");
|
|
||||||
replace(itemName, GetPath(), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do some fixes because 'TryGetItemAsync' is very sensetive
|
|
||||||
replace(itemName, "\\\\", "\\");
|
|
||||||
replace(itemName, "//", "/");
|
|
||||||
replace(itemName, "*", "");
|
|
||||||
rtrim(itemName, ":"); // remove ':' at the end of the path (if any)
|
|
||||||
|
|
||||||
path = PathUWP(itemName);
|
|
||||||
|
|
||||||
return itemName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if folder contains item by name or path
|
|
||||||
bool Contains(PathUWP path, IStorageItem^& storageItem) {
|
|
||||||
auto pathString = CleanItemPath(path);
|
|
||||||
|
|
||||||
// If the path is for parent then ignore
|
|
||||||
if (!path.IsAbsolute()) {
|
|
||||||
VERBOSE_LOG(FILESYS, "Looking for (%s) in (%s)", pathString.c_str(), GetPath().c_str());
|
|
||||||
ExecuteTask(storageItem, storageFolder->TryGetItemAsync(convert(pathString)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return storageItem != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Contains(std::string path) {
|
|
||||||
IStorageItem^ tempItem;
|
|
||||||
return Contains(PathUWP(path), tempItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BuildStructure(StorageFolder^& folder, std::string path) {
|
|
||||||
std::string folderName;
|
|
||||||
std::vector<std::string> locationParts = split(path, '\\');
|
|
||||||
for each (auto dir in locationParts) {
|
|
||||||
folderName.append(dir);
|
|
||||||
// Create folder
|
|
||||||
ExecuteTask(folder, storageFolder->CreateFolderAsync(convert(folderName), CreationCollisionOption::OpenIfExists));
|
|
||||||
folderName.append("\\");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BuildStructure(StorageFolder^& folder, std::string path, StorageFolder^ target) {
|
|
||||||
IStorageItem^ test = nullptr;
|
|
||||||
ExecuteTask(test, target->TryGetItemAsync(convert(path)));
|
|
||||||
if (test == nullptr) {
|
|
||||||
std::string folderName;
|
|
||||||
std::vector<std::string> locationParts = split(path, '\\');
|
|
||||||
for each (auto dir in locationParts) {
|
|
||||||
folderName.append(dir);
|
|
||||||
// Create folder
|
|
||||||
ExecuteTask(folder, target->CreateFolderAsync(convert(folderName), CreationCollisionOption::OpenIfExists));
|
|
||||||
folderName.append("\\");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
folder = (StorageFolder^)test;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageFolder^ GetOrCreateFolder(PathUWP path) {
|
|
||||||
StorageFolder^ folder;
|
|
||||||
auto pathString = CleanItemPath(path);
|
|
||||||
BuildStructure(folder, pathString);
|
|
||||||
|
|
||||||
return folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageFile^ GetOrCreateFile(PathUWP path) {
|
|
||||||
StorageFile^ file;
|
|
||||||
StorageFolder^ folder;
|
|
||||||
auto name = path.GetFilename();
|
|
||||||
auto dir = PathUWP(path.GetDirectory());
|
|
||||||
auto dirString = CleanItemPath(dir);
|
|
||||||
BuildStructure(folder, dirString);
|
|
||||||
if (folder != nullptr) {
|
|
||||||
ExecuteTask(file, folder->CreateFileAsync(convert(name), CreationCollisionOption::OpenIfExists));
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy to another folder
|
|
||||||
bool Copy(StorageFolderW folder, bool move = false) {
|
|
||||||
auto files = GetAllFiles();
|
|
||||||
bool state = false;
|
|
||||||
int failedCount = 0;
|
|
||||||
if (!files.empty()) {
|
|
||||||
auto destination = folder.GetStorageFolder();
|
|
||||||
|
|
||||||
// Copy files one by one to avoid 'access violation' issues with deep-level tasks
|
|
||||||
std::string rootName = convert(storageFolder->Name);
|
|
||||||
std::string rootPath = PathUWP(GetPath()).GetDirectory();
|
|
||||||
windowsPath(rootPath);
|
|
||||||
|
|
||||||
if (destination != nullptr) {
|
|
||||||
for each (auto file in files) {
|
|
||||||
auto fItem = file.GetStorageFile();
|
|
||||||
|
|
||||||
// Get file full path
|
|
||||||
std::string targetLocation = convert(fItem->Path);
|
|
||||||
// Remove root path but keep the parent name
|
|
||||||
replace(targetLocation, rootPath, "");
|
|
||||||
replace(targetLocation, convert("\\" + fItem->Name), "");
|
|
||||||
ltrim(targetLocation, "\\");
|
|
||||||
rtrim(targetLocation, "\\");
|
|
||||||
|
|
||||||
// Build folder structure
|
|
||||||
StorageFolder^ targetFolder;
|
|
||||||
BuildStructure(targetFolder, targetLocation, destination);
|
|
||||||
|
|
||||||
if (targetFolder != nullptr) {
|
|
||||||
// Copy file
|
|
||||||
StorageFile^ testFile;
|
|
||||||
if (move) {
|
|
||||||
ExecuteTask(fItem->MoveAsync((IStorageFolder^)targetFolder, fItem->Name, NameCollisionOption::ReplaceExisting));
|
|
||||||
ExecuteTask(testFile, targetFolder->GetFileAsync(fItem->Name)); // testing, it can be ignored
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ExecuteTask(testFile, fItem->CopyAsync((IStorageFolder^)targetFolder, fItem->Name, NameCollisionOption::ReplaceExisting));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (testFile == nullptr) {
|
|
||||||
// File failed to copy, we can handle this later
|
|
||||||
failedCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Try to get the new folder
|
|
||||||
IStorageItem^ newFolder;
|
|
||||||
ExecuteTask(newFolder, destination->TryGetItemAsync(convert(rootName)));
|
|
||||||
if (newFolder != nullptr) {
|
|
||||||
if (move) {
|
|
||||||
if (failedCount == 0) {
|
|
||||||
// If all files moved, we can safely remove the folder
|
|
||||||
ExecuteTask(storageFolder->DeleteAsync());
|
|
||||||
}
|
|
||||||
storageFolder = (StorageFolder^)newFolder;
|
|
||||||
}
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy to another folder using StorageFolder^
|
|
||||||
bool Copy(StorageFolder^ folder, bool move = false) {
|
|
||||||
return Copy(StorageFolderW(folder), move);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move to another folder
|
|
||||||
bool Move(StorageFolderW destination) {
|
|
||||||
return Copy(destination, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get storage folder handle
|
|
||||||
HRESULT GetHandle(HANDLE* handle, int accessMode = GENERIC_READ, int shareMode = FILE_SHARE_READ) {
|
|
||||||
return GetFolderHandle(storageFolder, handle, GetAccessMode(accessMode),GetShareMode(shareMode));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get storage folder handle
|
|
||||||
HRESULT GetHandleForFile(HANDLE* handle, std::string filename, int accessMode = GENERIC_READ, int shareMode = FILE_SHARE_READ, int openMode = OPEN_EXISTING) {
|
|
||||||
return GetFileHandleFromFolder(storageFolder, filename, handle, GetAccessMode(accessMode), GetShareMode(shareMode), GetOpenMode(openMode));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file stream
|
|
||||||
FILE* GetFileStream(std::string name, const char* mode) {
|
|
||||||
FILE* file{};
|
|
||||||
|
|
||||||
bool createIfNotExists = isWriteMode(mode);
|
|
||||||
bool isAppend = isAppendMode(mode);
|
|
||||||
|
|
||||||
StorageFile^ sfile;
|
|
||||||
|
|
||||||
if (createIfNotExists) {
|
|
||||||
auto createMode = isAppend ? CreationCollisionOption::OpenIfExists : CreationCollisionOption::ReplaceExisting;
|
|
||||||
ExecuteTask(sfile, storageFolder->CreateFileAsync(convert(name), createMode));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
IStorageItem^ tempItem;
|
|
||||||
ExecuteTask(tempItem, storageFolder->TryGetItemAsync(convert(name)));
|
|
||||||
sfile = (StorageFile^)tempItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageFileW storageFile(sfile);
|
|
||||||
if (storageFile.IsValid()) {
|
|
||||||
file = storageFile.GetStream(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get folder size
|
|
||||||
__int64 GetSize(bool updateCache = false) {
|
|
||||||
if (folderSize == 0 || updateCache) {
|
|
||||||
// Let's try getting size by handle first
|
|
||||||
HANDLE handle;
|
|
||||||
HRESULT hr = GetHandle(&handle);
|
|
||||||
if (handle == INVALID_HANDLE_VALUE || hr != S_OK) {
|
|
||||||
// We have no other option, fallback to UWP
|
|
||||||
// This need to sum all files inside
|
|
||||||
auto files = GetAllFiles(true);
|
|
||||||
for each (auto file in files) {
|
|
||||||
folderSize += file.GetSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LARGE_INTEGER size{ 0 };
|
|
||||||
if (FALSE == GetFileSizeEx(handle, &size)) {
|
|
||||||
LARGE_INTEGER end_offset;
|
|
||||||
const LARGE_INTEGER zero{};
|
|
||||||
if (SetFilePointerEx(handle, zero, &end_offset, FILE_END) == 0) {
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
folderSize = end_offset.QuadPart;
|
|
||||||
SetFilePointerEx(handle, zero, nullptr, FILE_BEGIN);
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
folderSize = size.QuadPart;
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return folderSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get folder basic properties
|
|
||||||
FILE_BASIC_INFO* GetProperties() {
|
|
||||||
HANDLE handle;
|
|
||||||
HRESULT hr = GetHandle(&handle);
|
|
||||||
|
|
||||||
size_t size = sizeof(FILE_BASIC_INFO);
|
|
||||||
FILE_BASIC_INFO* information = (FILE_BASIC_INFO*)(malloc(size));
|
|
||||||
if (hr == S_OK && handle != INVALID_HANDLE_VALUE && information) {
|
|
||||||
information->FileAttributes = (DWORD)storageFolder->Attributes;
|
|
||||||
|
|
||||||
if (FALSE == GetFileInformationByHandleEx(handle, FileBasicInfo, information, (DWORD)size)) {
|
|
||||||
// Fallback to UWP method (Slow)
|
|
||||||
auto props = FetchProperties();
|
|
||||||
information->ChangeTime.QuadPart = props->DateModified.UniversalTime;
|
|
||||||
information->CreationTime.QuadPart = props->ItemDate.UniversalTime;
|
|
||||||
information->LastAccessTime.QuadPart = props->DateModified.UniversalTime;
|
|
||||||
information->LastWriteTime.QuadPart = props->DateModified.UniversalTime;
|
|
||||||
}
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return information;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get main storage folder
|
|
||||||
StorageFolder^ GetStorageFolder() {
|
|
||||||
return storageFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t filetime_to_timet(LARGE_INTEGER ull) const {
|
|
||||||
return ull.QuadPart / 10000000ULL - 11644473600ULL;
|
|
||||||
}
|
|
||||||
ItemInfoUWP GetFolderInfo() {
|
|
||||||
ItemInfoUWP info;
|
|
||||||
info.name = GetName();
|
|
||||||
info.fullName = GetPath();
|
|
||||||
info.isDirectory = true;
|
|
||||||
|
|
||||||
|
|
||||||
auto sProperties = GetProperties();
|
|
||||||
|
|
||||||
info.size = (uint64_t)GetSize();
|
|
||||||
info.lastAccessTime = (uint64_t)filetime_to_timet(sProperties->LastAccessTime);
|
|
||||||
info.lastWriteTime = (uint64_t)filetime_to_timet(sProperties->LastWriteTime);
|
|
||||||
info.changeTime = (uint64_t)filetime_to_timet(sProperties->ChangeTime);
|
|
||||||
info.creationTime = (uint64_t)filetime_to_timet(sProperties->CreationTime);
|
|
||||||
|
|
||||||
|
|
||||||
info.attributes = sProperties->FileAttributes;
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
StorageFolder^ storageFolder;
|
|
||||||
BasicProperties^ properties;
|
|
||||||
__int64 folderSize = 0;
|
|
||||||
|
|
||||||
BasicProperties^ FetchProperties() {
|
|
||||||
if (properties == nullptr) {
|
|
||||||
// Very bad and slow way in UWP to get size and other properties
|
|
||||||
// not preferred to be used on big list of files
|
|
||||||
ExecuteTask(properties, storageFolder->GetBasicPropertiesAsync());
|
|
||||||
}
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,132 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// GetFileHandle(StorageFile^ file, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode)
|
|
||||||
// GetFileHandleFromFolder(StorageFolder^ folder, std::string filename, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode, HANDLE_CREATION_OPTIONS openMode)
|
|
||||||
// GetFolderHandle(StorageFolder^ folder, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode)
|
|
||||||
//
|
|
||||||
// GetAccessMode(int accessMode)
|
|
||||||
// GetShareMode(int shareMode)
|
|
||||||
// GetOpenMode(int openMode)
|
|
||||||
|
|
||||||
#include "StorageHandler.h"
|
|
||||||
#include "StorageExtensions.h"
|
|
||||||
|
|
||||||
using namespace Windows::Storage;
|
|
||||||
|
|
||||||
HRESULT GetFileHandle(StorageFile^ file, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode)
|
|
||||||
{
|
|
||||||
if (file != nullptr) {
|
|
||||||
Microsoft::WRL::ComPtr<IUnknown> abiPointer(reinterpret_cast<IUnknown*>(file));
|
|
||||||
Microsoft::WRL::ComPtr<IStorageItemHandleAccess> handleAccess;
|
|
||||||
if (SUCCEEDED(abiPointer.As(&handleAccess)))
|
|
||||||
{
|
|
||||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
if (SUCCEEDED(handleAccess->Create(accessMode,
|
|
||||||
shareMode,
|
|
||||||
HO_NONE,
|
|
||||||
nullptr,
|
|
||||||
&hFile)))
|
|
||||||
{
|
|
||||||
*handle = hFile;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT GetFileHandleFromFolder(StorageFolder^ folder, std::string filename, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode, HANDLE_CREATION_OPTIONS openMode)
|
|
||||||
{
|
|
||||||
if (folder != nullptr) {
|
|
||||||
Microsoft::WRL::ComPtr<IUnknown> abiPointer(reinterpret_cast<IUnknown*>(folder));
|
|
||||||
Microsoft::WRL::ComPtr<IStorageFolderHandleAccess> handleAccess;
|
|
||||||
if (SUCCEEDED(abiPointer.As(&handleAccess)))
|
|
||||||
{
|
|
||||||
HANDLE hFolder = INVALID_HANDLE_VALUE;
|
|
||||||
auto fn = convertToLPCWSTR(filename);
|
|
||||||
if (SUCCEEDED(handleAccess->Create(fn,
|
|
||||||
openMode,
|
|
||||||
accessMode,
|
|
||||||
shareMode,
|
|
||||||
HO_NONE,
|
|
||||||
nullptr,
|
|
||||||
&hFolder)))
|
|
||||||
{
|
|
||||||
*handle = hFolder;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT GetFolderHandle(StorageFolder^ folder, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode)
|
|
||||||
{
|
|
||||||
if (folder != nullptr) {
|
|
||||||
Microsoft::WRL::ComPtr<IUnknown> abiPointer(reinterpret_cast<IUnknown*>(folder));
|
|
||||||
Microsoft::WRL::ComPtr<IStorageItemHandleAccess> handleAccess;
|
|
||||||
if (SUCCEEDED(abiPointer.As(&handleAccess)))
|
|
||||||
{
|
|
||||||
HANDLE hFolder = INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
if (SUCCEEDED(handleAccess->Create(accessMode,
|
|
||||||
shareMode,
|
|
||||||
HO_NONE,
|
|
||||||
nullptr,
|
|
||||||
&hFolder)))
|
|
||||||
{
|
|
||||||
*handle = hFolder;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE_ACCESS_OPTIONS GetAccessMode(int accessMode) {
|
|
||||||
switch (accessMode) {
|
|
||||||
case GENERIC_READ:
|
|
||||||
return HAO_READ | HAO_READ_ATTRIBUTES;
|
|
||||||
case GENERIC_WRITE:
|
|
||||||
return HAO_WRITE | HAO_READ;
|
|
||||||
case GENERIC_ALL:
|
|
||||||
return HAO_READ | HAO_READ_ATTRIBUTES | HAO_WRITE | HAO_DELETE;
|
|
||||||
default:
|
|
||||||
return HAO_READ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE_SHARING_OPTIONS GetShareMode(int shareMode) {
|
|
||||||
switch (shareMode)
|
|
||||||
{
|
|
||||||
case FILE_SHARE_READ:
|
|
||||||
return HSO_SHARE_READ;
|
|
||||||
case FILE_SHARE_WRITE:
|
|
||||||
return HSO_SHARE_READ | HSO_SHARE_WRITE;
|
|
||||||
case FILE_SHARE_DELETE:
|
|
||||||
return HSO_SHARE_DELETE;
|
|
||||||
default:
|
|
||||||
return HSO_SHARE_READ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE_CREATION_OPTIONS GetOpenMode(int openMode) {
|
|
||||||
switch (openMode)
|
|
||||||
{
|
|
||||||
case CREATE_NEW:
|
|
||||||
return HCO_CREATE_NEW;
|
|
||||||
case CREATE_ALWAYS:
|
|
||||||
return HCO_CREATE_ALWAYS;
|
|
||||||
case OPEN_ALWAYS:
|
|
||||||
return HCO_OPEN_ALWAYS;
|
|
||||||
case OPEN_EXISTING:
|
|
||||||
return HCO_OPEN_EXISTING;
|
|
||||||
default:
|
|
||||||
return HCO_OPEN_EXISTING;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,137 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// GetFileHandle(StorageFile^ file, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode)
|
|
||||||
// GetFileHandleFromFolder(StorageFolder^ folder, std::string filename, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode, HANDLE_CREATION_OPTIONS openMode)
|
|
||||||
// GetFolderHandle(StorageFolder^ folder, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode)
|
|
||||||
//
|
|
||||||
// GetAccessMode(int accessMode)
|
|
||||||
// GetShareMode(int shareMode)
|
|
||||||
// GetOpenMode(int openMode)
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include <ppl.h>
|
|
||||||
#include <ppltasks.h>
|
|
||||||
#include <wrl.h>
|
|
||||||
#include <wrl/implements.h>
|
|
||||||
|
|
||||||
using namespace Windows::Storage;
|
|
||||||
|
|
||||||
#pragma region WindowsStorageCOM
|
|
||||||
// These APIs have been accidentally placed inside the WINAPI_PARTITION_DESKTOP partition
|
|
||||||
// (they're not desktop-specific; they're available to UWPs).
|
|
||||||
// This will be addressed in future SDK updates.
|
|
||||||
// These are copied from WindowsStorageCOM.h
|
|
||||||
// You can remove this region once the real file has been updated
|
|
||||||
// to fix the WINAPI_PARTITION_DESKTOP block
|
|
||||||
// Source: https://stackoverflow.com/questions/42799235/how-can-i-get-a-win32-handle-for-a-storagefile-or-storagefolder-in-uwp
|
|
||||||
|
|
||||||
typedef interface IOplockBreakingHandler IOplockBreakingHandler;
|
|
||||||
typedef interface IStorageItemHandleAccess IStorageItemHandleAccess;
|
|
||||||
typedef interface IStorageFolderHandleAccess IStorageFolderHandleAccess;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef
|
|
||||||
enum HANDLE_OPTIONS
|
|
||||||
{
|
|
||||||
HO_NONE = 0,
|
|
||||||
HO_OPEN_REQUIRING_OPLOCK = 0x40000,
|
|
||||||
HO_DELETE_ON_CLOSE = 0x4000000,
|
|
||||||
HO_SEQUENTIAL_SCAN = 0x8000000,
|
|
||||||
HO_RANDOM_ACCESS = 0x10000000,
|
|
||||||
HO_NO_BUFFERING = 0x20000000,
|
|
||||||
HO_OVERLAPPED = 0x40000000,
|
|
||||||
HO_WRITE_THROUGH = 0x80000000
|
|
||||||
} HANDLE_OPTIONS;
|
|
||||||
|
|
||||||
DEFINE_ENUM_FLAG_OPERATORS(HANDLE_OPTIONS);
|
|
||||||
typedef
|
|
||||||
enum HANDLE_ACCESS_OPTIONS
|
|
||||||
{
|
|
||||||
HAO_NONE = 0,
|
|
||||||
HAO_READ_ATTRIBUTES = 0x80,
|
|
||||||
HAO_READ = 0x120089,
|
|
||||||
HAO_WRITE = 0x120116,
|
|
||||||
HAO_DELETE = 0x10000
|
|
||||||
} HANDLE_ACCESS_OPTIONS;
|
|
||||||
|
|
||||||
DEFINE_ENUM_FLAG_OPERATORS(HANDLE_ACCESS_OPTIONS);
|
|
||||||
typedef
|
|
||||||
enum HANDLE_SHARING_OPTIONS
|
|
||||||
{
|
|
||||||
HSO_SHARE_NONE = 0,
|
|
||||||
HSO_SHARE_READ = 0x1,
|
|
||||||
HSO_SHARE_WRITE = 0x2,
|
|
||||||
HSO_SHARE_DELETE = 0x4
|
|
||||||
} HANDLE_SHARING_OPTIONS;
|
|
||||||
|
|
||||||
DEFINE_ENUM_FLAG_OPERATORS(HANDLE_SHARING_OPTIONS);
|
|
||||||
typedef
|
|
||||||
enum HANDLE_CREATION_OPTIONS
|
|
||||||
{
|
|
||||||
HCO_CREATE_NEW = 0x1,
|
|
||||||
HCO_CREATE_ALWAYS = 0x2,
|
|
||||||
HCO_OPEN_EXISTING = 0x3,
|
|
||||||
HCO_OPEN_ALWAYS = 0x4,
|
|
||||||
HCO_TRUNCATE_EXISTING = 0x5
|
|
||||||
} HANDLE_CREATION_OPTIONS;
|
|
||||||
|
|
||||||
|
|
||||||
EXTERN_C const IID IID_IOplockBreakingHandler;
|
|
||||||
MIDL_INTERFACE("826ABE3D-3ACD-47D3-84F2-88AAEDCF6304")
|
|
||||||
IOplockBreakingHandler : public IUnknown
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE OplockBreaking(void) = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
EXTERN_C const IID IID_IStorageItemHandleAccess;
|
|
||||||
MIDL_INTERFACE("5CA296B2-2C25-4D22-B785-B885C8201E6A")
|
|
||||||
IStorageItemHandleAccess : public IUnknown
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE Create(
|
|
||||||
HANDLE_ACCESS_OPTIONS accessOptions,
|
|
||||||
HANDLE_SHARING_OPTIONS sharingOptions,
|
|
||||||
HANDLE_OPTIONS options,
|
|
||||||
__RPC__in_opt IOplockBreakingHandler * oplockBreakingHandler,
|
|
||||||
__RPC__deref_out_opt HANDLE * interopHandle) = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
EXTERN_C const IID IID_IStorageFolderHandleAccess;
|
|
||||||
MIDL_INTERFACE("DF19938F-5462-48A0-BE65-D2A3271A08D6")
|
|
||||||
IStorageFolderHandleAccess : public IUnknown
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE Create(
|
|
||||||
__RPC__in_string LPCWSTR fileName,
|
|
||||||
HANDLE_CREATION_OPTIONS creationOptions,
|
|
||||||
HANDLE_ACCESS_OPTIONS accessOptions,
|
|
||||||
HANDLE_SHARING_OPTIONS sharingOptions,
|
|
||||||
HANDLE_OPTIONS options,
|
|
||||||
__RPC__in_opt IOplockBreakingHandler * oplockBreakingHandler,
|
|
||||||
__RPC__deref_out_opt HANDLE * interopHandle) = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
HRESULT GetFileHandle(StorageFile^ file, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode);
|
|
||||||
HRESULT GetFileHandleFromFolder(StorageFolder^ folder, std::string filename, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode, HANDLE_CREATION_OPTIONS openMode);
|
|
||||||
HRESULT GetFolderHandle(StorageFolder^ folder, HANDLE* handle, HANDLE_ACCESS_OPTIONS accessMode, HANDLE_SHARING_OPTIONS shareMode);
|
|
||||||
|
|
||||||
HANDLE_ACCESS_OPTIONS GetAccessMode(int accessMode);
|
|
||||||
HANDLE_SHARING_OPTIONS GetShareMode(int shareMode);
|
|
||||||
HANDLE_CREATION_OPTIONS GetOpenMode(int openMode);
|
|
|
@ -1,24 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// For updates check: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
struct ItemInfoUWP {
|
|
||||||
std::string name;
|
|
||||||
std::string fullName;
|
|
||||||
|
|
||||||
bool isDirectory = false;
|
|
||||||
|
|
||||||
uint64_t size = 0;
|
|
||||||
uint64_t lastAccessTime = 0;
|
|
||||||
uint64_t lastWriteTime = 0;
|
|
||||||
uint64_t changeTime = 0;
|
|
||||||
uint64_t creationTime = 0;
|
|
||||||
|
|
||||||
DWORD attributes = 0;
|
|
||||||
};
|
|
|
@ -1,324 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include <io.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "StorageLog.h"
|
|
||||||
#include "StoragePath.h"
|
|
||||||
#include "StorageExtensions.h"
|
|
||||||
#include "StorageHandler.h"
|
|
||||||
#include "StorageAsync.h"
|
|
||||||
#include "StorageFolderW.h"
|
|
||||||
|
|
||||||
using namespace Platform;
|
|
||||||
using namespace Windows::Storage;
|
|
||||||
using namespace Windows::Foundation;
|
|
||||||
using namespace Windows::Storage::FileProperties;
|
|
||||||
|
|
||||||
class StorageItemW {
|
|
||||||
public:
|
|
||||||
StorageItemW() {
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageItemW(IStorageItem^ item) {
|
|
||||||
storageItem = item;
|
|
||||||
itemSize = 0;
|
|
||||||
if (item != nullptr) {
|
|
||||||
isDirectory = storageItem->IsOfType(StorageItemTypes::Folder);
|
|
||||||
if (isDirectory) {
|
|
||||||
storageFolderW = StorageFolderW(item);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
storageFileW = StorageFileW(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StorageItemW(StorageFolderW folder) {
|
|
||||||
StorageItemW((IStorageItem^)folder.GetStorageFolder());
|
|
||||||
}
|
|
||||||
StorageItemW(StorageFileW file) {
|
|
||||||
StorageItemW((IStorageItem^)file.GetStorageFile());
|
|
||||||
}
|
|
||||||
~StorageItemW() {
|
|
||||||
delete storageItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsDirectory() {
|
|
||||||
return isDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect if main storage item is not null
|
|
||||||
bool IsValid() {
|
|
||||||
return (storageItem != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete item
|
|
||||||
bool Delete() {
|
|
||||||
bool state = ExecuteTask(storageItem->DeleteAsync());
|
|
||||||
if (state) {
|
|
||||||
storageItem = nullptr;
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rename item
|
|
||||||
bool Rename(std::string name) {
|
|
||||||
auto path = PathUWP(name);
|
|
||||||
if (path.IsAbsolute()) {
|
|
||||||
name = path.GetFilename();
|
|
||||||
}
|
|
||||||
return ExecuteTask(storageItem->RenameAsync(convert(name)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy item
|
|
||||||
bool Copy(StorageFolder^ folder) {
|
|
||||||
bool state = false;
|
|
||||||
if (IsDirectory()) {
|
|
||||||
state = storageFolderW.Copy(folder);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
state = storageFileW.Copy(folder, storageFileW.GetName());
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Copy item
|
|
||||||
bool Copy(StorageItemW folder) {
|
|
||||||
return Copy(folder.GetStorageFolder());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Copy(StorageFolder^ folder, std::string name) {
|
|
||||||
bool state = false;
|
|
||||||
if (IsDirectory()) {
|
|
||||||
state = storageFolderW.Copy(folder);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
state = storageFileW.Copy(folder, name);
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Copy(StorageItemW folder, std::string name) {
|
|
||||||
return Copy(folder.GetStorageFolder(), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move item
|
|
||||||
bool Move(StorageFolder^ folder) {
|
|
||||||
bool state = false;
|
|
||||||
if (IsDirectory()) {
|
|
||||||
state = storageFolderW.Copy(folder, true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
state = storageFileW.Move(folder, storageFileW.GetName());
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Move(StorageItemW folder) {
|
|
||||||
return Move(folder.GetStorageFolder());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move item
|
|
||||||
bool Move(StorageFolder^ folder, std::string name) {
|
|
||||||
bool state = false;
|
|
||||||
if (IsDirectory()) {
|
|
||||||
state = storageFolderW.Copy(folder, true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
state = storageFileW.Move(folder, name);
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Move(StorageItemW folder, std::string name) {
|
|
||||||
return Move(folder.GetStorageFolder(), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get item path
|
|
||||||
std::string GetPath() {
|
|
||||||
return convert(storageItem->Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get item name
|
|
||||||
std::string GetName() {
|
|
||||||
return convert(storageItem->Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare item with std::string
|
|
||||||
bool Equal(std::string path) {
|
|
||||||
std::string itemPath = GetPath();
|
|
||||||
|
|
||||||
// Fix slashs back from '/' to '\'
|
|
||||||
windowsPath(path);
|
|
||||||
return iequals(itemPath, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare item with Platform::String
|
|
||||||
bool Equal(Platform::String^ path) {
|
|
||||||
return storageItem->Path->Equals(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare item with Path
|
|
||||||
bool Equal(PathUWP path) {
|
|
||||||
return Equal(path.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare item with StorageItem
|
|
||||||
bool Equal(IStorageItem^ item) {
|
|
||||||
return Equal(item->Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get item size
|
|
||||||
__int64 GetSize(bool updateCache = false) {
|
|
||||||
if (itemSize == 0 || updateCache) {
|
|
||||||
if (IsDirectory()) {
|
|
||||||
itemSize = storageFolderW.GetSize(updateCache);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
itemSize = storageFileW.GetSize(updateCache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return itemSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get item handle
|
|
||||||
HRESULT GetHandle(HANDLE* handle, int accessMode = GENERIC_READ, int shareMode = FILE_SHARE_READ) {
|
|
||||||
HRESULT hr = E_FAIL;
|
|
||||||
if(IsDirectory()){
|
|
||||||
hr = GetFolderHandle(storageFolderW.GetStorageFolder(), handle, GetAccessMode(accessMode), GetShareMode(shareMode));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
hr = GetFileHandle(storageFileW.GetStorageFile(), handle, GetAccessMode(accessMode), GetShareMode(shareMode));
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file stream
|
|
||||||
FILE* GetStream(const char* mode) {
|
|
||||||
FILE* file{};
|
|
||||||
if (!IsDirectory()) {
|
|
||||||
file = storageFileW.GetStream(mode);
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get files stream from folder
|
|
||||||
FILE* GetFileStream(std::string name, const char* mode) {
|
|
||||||
FILE* file{};
|
|
||||||
if (IsDirectory()) {
|
|
||||||
file = storageFolderW.GetFileStream(name, mode);
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get item handle from stream
|
|
||||||
HANDLE GetHandleFromStream(FILE* file) {
|
|
||||||
return (HANDLE)_get_osfhandle(_fileno(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Create or open folder if exists
|
|
||||||
StorageFolderW CreateFolder(PathUWP path) {
|
|
||||||
return StorageFolderW(storageFolderW.GetOrCreateFolder(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create or open file if exists
|
|
||||||
StorageFileW CreateFile(PathUWP path) {
|
|
||||||
return StorageFileW(storageFolderW.GetOrCreateFile(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new folder
|
|
||||||
bool CreateFolder(std::string name, bool replaceExisting = true) {
|
|
||||||
return storageFolderW.CreateFolder(name, replaceExisting);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new file
|
|
||||||
bool CreateFile(std::string name, bool replaceExisting = true) {
|
|
||||||
return storageFolderW.CreateFile(name, replaceExisting);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if folder contains item by name or path
|
|
||||||
bool Contains(PathUWP path, IStorageItem^& storageItem) {
|
|
||||||
return storageFolderW.Contains(path, storageItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all sub folders (deep scan)
|
|
||||||
std::list<StorageFolderW> GetAllFolders(bool useWindowsIndexer = false) {
|
|
||||||
return storageFolderW.GetAllFolders(useWindowsIndexer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all files including files in sub folders (deep scan)
|
|
||||||
std::list<StorageFileW> GetAllFiles(bool useWindowsIndexer = false) {
|
|
||||||
return storageFolderW.GetAllFiles(useWindowsIndexer);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::list<StorageFolderW> GetFolders() {
|
|
||||||
return storageFolderW.GetFolders();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::list<StorageFileW> GetFiles() {
|
|
||||||
return storageFolderW.GetFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get item properties
|
|
||||||
FILE_BASIC_INFO* GetProperties() {
|
|
||||||
if (IsDirectory()) {
|
|
||||||
return storageFolderW.GetProperties();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return storageFileW.GetProperties();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get main storage item
|
|
||||||
IStorageItem^ GetStorageItem() {
|
|
||||||
return storageItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Wrapped StorageFolder
|
|
||||||
StorageFolderW GetStorageFolderW() {
|
|
||||||
return storageFolderW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Wrapped StorageFolder
|
|
||||||
StorageFolder^ GetStorageFolder() {
|
|
||||||
return storageFolderW.GetStorageFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Wrapped StorageFile
|
|
||||||
StorageFileW GetStorageFileW() {
|
|
||||||
return storageFileW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get StorageFile^
|
|
||||||
StorageFile^ GetStorageFile() {
|
|
||||||
return storageFileW.GetStorageFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemInfoUWP GetItemInfo() {
|
|
||||||
ItemInfoUWP info;
|
|
||||||
if (IsDirectory()) {
|
|
||||||
info = storageFolderW.GetFolderInfo();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
info = storageFileW.GetFileInfo();
|
|
||||||
}
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
IStorageItem^ storageItem;
|
|
||||||
StorageFileW storageFileW;
|
|
||||||
StorageFolderW storageFolderW;
|
|
||||||
|
|
||||||
__int64 itemSize = 0;
|
|
||||||
bool isDirectory = false;
|
|
||||||
};
|
|
|
@ -1,17 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Link your debug function below
|
|
||||||
// IGNORE THIS FILE FOR PPSSPP
|
|
||||||
// WE ALREADY USING PPSSPP's LOGS FUNCTIONS
|
|
||||||
#define UWP_ERROR_LOG(t,...) do { } while (false)
|
|
||||||
#define UWP_WARN_LOG(t,...) do { } while (false)
|
|
||||||
#define UWP_NOTICE_LOG(t,...) do { } while (false)
|
|
||||||
#define UWP_INFO_LOG(t,...) do { } while (false)
|
|
||||||
#define UWP_DEBUG_LOG(t,...) do { } while (false)
|
|
||||||
#define UWP_VERBOSE_LOG(t,...) do { } while (false)
|
|
|
@ -4,56 +4,20 @@
|
||||||
// Telegram: @basharastifan
|
// Telegram: @basharastifan
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
// GitHub: https://github.com/basharast/UWP2Win32
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// GetWorkingFolder()
|
|
||||||
// SetWorkingFolder(std::string location)
|
|
||||||
// GetInstallationFolder()
|
|
||||||
// GetLocalFolder()
|
|
||||||
// GetTempFolder()
|
|
||||||
// GetPicturesFolder()
|
|
||||||
// GetVideosFolder()
|
|
||||||
// GetDocumentsFolder()
|
|
||||||
// GetMusicFolder()
|
|
||||||
// GetPreviewPath(std::string path)
|
|
||||||
//
|
|
||||||
// CreateFileUWP(std::string path, int accessMode, int shareMode, int openMode)
|
|
||||||
// CreateFileUWP(std::wstring path, int accessMode, int shareMode, int openMode)
|
|
||||||
// GetFileStream(std::string path, const char* mode)
|
|
||||||
// IsValidUWP(std::string path)
|
|
||||||
// IsExistsUWP(std::string path)
|
|
||||||
// IsDirectoryUWP(std::string path)
|
|
||||||
//
|
|
||||||
// GetFolderContents(std::string path, T& files)
|
|
||||||
// GetFolderContents(std::wstring path, T& files)
|
|
||||||
// GetFileInfoUWP(std::string path, T& info)
|
|
||||||
//
|
|
||||||
// GetSizeUWP(std::string path)
|
|
||||||
// DeleteUWP(std::string path)
|
|
||||||
// CreateDirectoryUWP(std::string path, bool replaceExisting)
|
|
||||||
// RenameUWP(std::string path, std::string name)
|
|
||||||
// CopyUWP(std::string path, std::string name)
|
|
||||||
// MoveUWP(std::string path, std::string name)
|
|
||||||
//
|
|
||||||
// OpenFile(std::string path)
|
|
||||||
// OpenFolder(std::string path)
|
|
||||||
// IsFirstStart()
|
|
||||||
//
|
|
||||||
// GetLogFile()
|
|
||||||
// SaveLogs()
|
|
||||||
// CleanupLogs()
|
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
#include <io.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
||||||
#include "Common/Log.h"
|
#include "Common/Log.h"
|
||||||
|
#include "Core/Config.h"
|
||||||
|
#include "Common/File/Path.h"
|
||||||
|
#include "Common/StringUtils.h"
|
||||||
|
#include "UWPUtil.h"
|
||||||
|
|
||||||
#include "StorageConfig.h"
|
|
||||||
#include "StorageManager.h"
|
#include "StorageManager.h"
|
||||||
#include "StorageExtensions.h"
|
|
||||||
#include "StorageHandler.h"
|
|
||||||
#include "StorageAsync.h"
|
#include "StorageAsync.h"
|
||||||
#include "StorageAccess.h"
|
#include "StorageAccess.h"
|
||||||
#include "StorageItemW.h"
|
|
||||||
#include "StorageLog.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace Platform;
|
using namespace Platform;
|
||||||
|
@ -61,37 +25,33 @@ using namespace Windows::Storage;
|
||||||
using namespace Windows::Foundation;
|
using namespace Windows::Foundation;
|
||||||
using namespace Windows::ApplicationModel;
|
using namespace Windows::ApplicationModel;
|
||||||
|
|
||||||
extern std::list<StorageItemW> FutureAccessItems;
|
|
||||||
|
|
||||||
#pragma region Locations
|
#pragma region Locations
|
||||||
std::string GetWorkingFolder() {
|
std::string GetWorkingFolder() {
|
||||||
if (AppWorkingFolder.empty()) {
|
if (g_Config.memStickDirectory.empty()) {
|
||||||
return GetLocalFolder();
|
return GetLocalFolder();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return AppWorkingFolder;
|
return g_Config.memStickDirectory.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void SetWorkingFolder(std::string location) {
|
|
||||||
AppWorkingFolder = location;
|
|
||||||
}
|
|
||||||
std::string GetInstallationFolder() {
|
std::string GetInstallationFolder() {
|
||||||
return convert(Package::Current->InstalledLocation->Path);
|
return FromPlatformString(Package::Current->InstalledLocation->Path);
|
||||||
}
|
}
|
||||||
StorageFolder^ GetLocalStorageFolder() {
|
StorageFolder^ GetLocalStorageFolder() {
|
||||||
return ApplicationData::Current->LocalFolder;
|
return ApplicationData::Current->LocalFolder;
|
||||||
}
|
}
|
||||||
std::string GetLocalFolder() {
|
std::string GetLocalFolder() {
|
||||||
return convert(GetLocalStorageFolder()->Path);
|
return FromPlatformString(GetLocalStorageFolder()->Path);
|
||||||
}
|
}
|
||||||
std::string GetTempFolder() {
|
std::string GetTempFolder() {
|
||||||
return convert(ApplicationData::Current->TemporaryFolder->Path);
|
return FromPlatformString(ApplicationData::Current->TemporaryFolder->Path);
|
||||||
}
|
}
|
||||||
std::string GetTempFile(std::string name) {
|
std::string GetTempFile(std::string name) {
|
||||||
StorageFile^ tmpFile;
|
StorageFile^ tmpFile;
|
||||||
ExecuteTask(tmpFile, ApplicationData::Current->TemporaryFolder->CreateFileAsync(convert(name), CreationCollisionOption::GenerateUniqueName));
|
ExecuteTask(tmpFile, ApplicationData::Current->TemporaryFolder->CreateFileAsync(ToPlatformString(name), CreationCollisionOption::GenerateUniqueName));
|
||||||
if (tmpFile != nullptr) {
|
if (tmpFile != nullptr) {
|
||||||
return convert(tmpFile->Path);
|
return FromPlatformString(tmpFile->Path);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return "";
|
return "";
|
||||||
|
@ -99,231 +59,56 @@ std::string GetTempFile(std::string name) {
|
||||||
}
|
}
|
||||||
std::string GetPicturesFolder() {
|
std::string GetPicturesFolder() {
|
||||||
// Requires 'picturesLibrary' capability
|
// Requires 'picturesLibrary' capability
|
||||||
return convert(KnownFolders::PicturesLibrary->Path);
|
return FromPlatformString(KnownFolders::PicturesLibrary->Path);
|
||||||
}
|
}
|
||||||
std::string GetVideosFolder() {
|
std::string GetVideosFolder() {
|
||||||
// Requires 'videosLibrary' capability
|
// Requires 'videosLibrary' capability
|
||||||
return convert(KnownFolders::VideosLibrary->Path);
|
return FromPlatformString(KnownFolders::VideosLibrary->Path);
|
||||||
}
|
}
|
||||||
std::string GetDocumentsFolder() {
|
std::string GetDocumentsFolder() {
|
||||||
// Requires 'documentsLibrary' capability
|
// Requires 'documentsLibrary' capability
|
||||||
return convert(KnownFolders::DocumentsLibrary->Path);
|
return FromPlatformString(KnownFolders::DocumentsLibrary->Path);
|
||||||
}
|
}
|
||||||
std::string GetMusicFolder() {
|
std::string GetMusicFolder() {
|
||||||
// Requires 'musicLibrary' capability
|
// Requires 'musicLibrary' capability
|
||||||
return convert(KnownFolders::MusicLibrary->Path);
|
return FromPlatformString(KnownFolders::MusicLibrary->Path);
|
||||||
}
|
}
|
||||||
std::string GetPreviewPath(std::string path) {
|
std::string GetPreviewPath(std::string path) {
|
||||||
std::string pathView = path;
|
std::string pathView = path;
|
||||||
windowsPath(pathView);
|
|
||||||
replace(pathView, GetLocalFolder(), "LocalState");
|
pathView = ReplaceAll(pathView, "/", "\\");
|
||||||
replace(pathView, GetTempFolder(), "TempState");
|
pathView = ReplaceAll(pathView, GetLocalFolder(), "LocalState");
|
||||||
replace(pathView, GetInstallationFolder(), "Installation folder");
|
pathView = ReplaceAll(pathView, GetTempFolder(), "TempState");
|
||||||
|
pathView = ReplaceAll(pathView, GetInstallationFolder(), "Installation folder");
|
||||||
return pathView;
|
return pathView;
|
||||||
}
|
}
|
||||||
bool isLocalState(std::string path) {
|
bool isLocalState(std::string path) {
|
||||||
return iequals(GetPreviewPath(path), "LocalState");
|
return !_stricmp(GetPreviewPath(path).c_str(), "LocalState");
|
||||||
}
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Internal
|
#pragma region Internal
|
||||||
PathUWP PathResolver(PathUWP path) {
|
Path PathResolver(Path path) {
|
||||||
auto root = path.GetDirectory();
|
auto root = path.GetDirectory();
|
||||||
auto newPath = path.ToString();
|
auto newPath = path.ToString();
|
||||||
if (path.IsRoot() || iequals(root, "/") || iequals(root, "\\")) {
|
if (path.IsRoot() || !_stricmp(root.c_str(), "/") || !_stricmp(root.c_str(), "\\")) {
|
||||||
// System requesting file from app data
|
// System requesting file from app data
|
||||||
replace(newPath, "/", (GetLocalFolder() + (path.size() > 1 ? "/": "")));
|
newPath = ReplaceAll(newPath, "/", (GetLocalFolder() + (path.size() > 1 ? "/" : "")));
|
||||||
}
|
}
|
||||||
path = PathUWP(newPath);
|
return Path(newPath);
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
PathUWP PathResolver(std::string path) {
|
Path PathResolver(std::string path) {
|
||||||
return PathResolver(PathUWP(path));
|
return PathResolver(Path(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ResolvePathUWP(std::string path) {
|
std::string ResolvePathUWP(std::string path) {
|
||||||
return PathResolver(path).ToString();
|
return PathResolver(path).ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return closer parent
|
|
||||||
StorageItemW GetStorageItemParent(PathUWP path) {
|
|
||||||
path = PathResolver(path);
|
|
||||||
StorageItemW parent;
|
|
||||||
|
|
||||||
for (auto& fItem : FutureAccessItems) {
|
|
||||||
if (isChild(fItem.GetPath(), path.ToString())) {
|
|
||||||
if (fItem.IsDirectory()) {
|
|
||||||
parent = fItem;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageItemW GetStorageItem(PathUWP path, bool createIfNotExists = false, bool forceFolderType = false) {
|
|
||||||
// Fill call will be ignored internally after the first call
|
|
||||||
FillLookupList();
|
|
||||||
|
|
||||||
path = PathResolver(path);
|
|
||||||
StorageItemW item;
|
|
||||||
|
|
||||||
// Look for match in FutureAccessItems
|
|
||||||
for (auto& fItem : FutureAccessItems) {
|
|
||||||
if (fItem.Equal(path)) {
|
|
||||||
item = fItem;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!item.IsValid()) {
|
|
||||||
// Look for match inside FutureAccessFolders
|
|
||||||
for (auto& fItem : FutureAccessItems) {
|
|
||||||
if (fItem.IsDirectory()) {
|
|
||||||
IStorageItem^ storageItem;
|
|
||||||
if (fItem.Contains(path, storageItem)) {
|
|
||||||
item = StorageItemW(storageItem);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!item.IsValid() && createIfNotExists) {
|
|
||||||
// Create and return new folder
|
|
||||||
auto parent = GetStorageItemParent(path);
|
|
||||||
if (parent.IsValid()) {
|
|
||||||
if (!forceFolderType) {
|
|
||||||
// File creation must be called in this case
|
|
||||||
// Create folder usually will be called from 'CreateDirectory'
|
|
||||||
item = StorageItemW(parent.CreateFile(path));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
item = StorageItemW(parent.CreateFolder(path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageItemW GetStorageItem(std::string path, bool createIfNotExists = false, bool forceFolderType = false) {
|
|
||||||
return GetStorageItem(PathUWP(path), createIfNotExists, forceFolderType);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::list<StorageItemW> GetStorageItemsByParent(PathUWP path) {
|
|
||||||
path = PathResolver(path);
|
|
||||||
std::list<StorageItemW> items;
|
|
||||||
|
|
||||||
// Look for match in FutureAccessItems
|
|
||||||
for (auto& fItem : FutureAccessItems) {
|
|
||||||
if (isParent(path.ToString(), fItem.GetPath(), fItem.GetName())) {
|
|
||||||
items.push_back(fItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::list<StorageItemW> GetStorageItemsByParent(std::string path) {
|
|
||||||
return GetStorageItemsByParent(PathUWP(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsContainsAccessibleItems(PathUWP path) {
|
|
||||||
path = PathResolver(path);
|
|
||||||
|
|
||||||
for (auto& fItem : FutureAccessItems) {
|
|
||||||
if (isParent(path.ToString(), fItem.GetPath(), fItem.GetName())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsContainsAccessibleItems(std::string path) {
|
|
||||||
return IsContainsAccessibleItems(PathUWP(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsRootForAccessibleItems(PathUWP path, std::list<std::string>& subRoot, bool breakOnFirstMatch = false) {
|
|
||||||
path = PathResolver(path);
|
|
||||||
|
|
||||||
for (auto& fItem : FutureAccessItems) {
|
|
||||||
if (isChild(path.ToString(), fItem.GetPath())) {
|
|
||||||
if (breakOnFirstMatch) {
|
|
||||||
// Just checking, we don't need to loop for each item
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
auto sub = getSubRoot(path.ToString(), fItem.GetPath());
|
|
||||||
|
|
||||||
// This check can be better, but that's how I can do it in C++
|
|
||||||
if (!ends_with(sub, ":")) {
|
|
||||||
bool alreadyAdded = false;
|
|
||||||
for each (auto sItem in subRoot) {
|
|
||||||
if (iequals(sItem, sub)) {
|
|
||||||
alreadyAdded = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!alreadyAdded) {
|
|
||||||
subRoot.push_back(sub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return !subRoot.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsRootForAccessibleItems(std::string path, std::list<std::string>& subRoot, bool breakOnFirstMatch = false) {
|
|
||||||
return IsRootForAccessibleItems(PathUWP(path), subRoot, breakOnFirstMatch);
|
|
||||||
}
|
|
||||||
bool IsRootForAccessibleItems(std::string path) {
|
|
||||||
std::list<std::string> tmp;
|
|
||||||
return IsRootForAccessibleItems(path, tmp, true);
|
|
||||||
}
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Functions
|
#pragma region Functions
|
||||||
bool CreateIfNotExists(int openMode) {
|
|
||||||
switch (openMode)
|
|
||||||
{
|
|
||||||
case OPEN_ALWAYS:
|
|
||||||
case CREATE_NEW:
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE CreateFileUWP(std::string path, int accessMode, int shareMode, int openMode) {
|
|
||||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
|
||||||
if (IsValidUWP(path)) {
|
|
||||||
bool createIfNotExists = CreateIfNotExists(openMode);
|
|
||||||
auto storageItem = GetStorageItem(path, createIfNotExists);
|
|
||||||
|
|
||||||
if (storageItem.IsValid()) {
|
|
||||||
DEBUG_LOG(FILESYS, "Getting handle (%s)", path.c_str());
|
|
||||||
HRESULT hr = storageItem.GetHandle(&handle, accessMode, shareMode);
|
|
||||||
if (hr == E_FAIL) {
|
|
||||||
handle = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
handle = INVALID_HANDLE_VALUE;
|
|
||||||
DEBUG_LOG(FILESYS, "Couldn't find or access (%s)", path.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE CreateFileUWP(std::wstring path, int accessMode, int shareMode, int openMode) {
|
|
||||||
auto pathString = convert(path);
|
|
||||||
return CreateFileUWP(pathString, accessMode, shareMode, openMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<std::string, bool> accessState;
|
std::map<std::string, bool> accessState;
|
||||||
bool CheckDriveAccess(std::string driveName, bool checkIfContainsFutureAccessItems) {
|
bool CheckDriveAccess(std::string driveName) {
|
||||||
bool state = false;
|
bool state = false;
|
||||||
|
|
||||||
HANDLE searchResults;
|
HANDLE searchResults;
|
||||||
|
@ -334,140 +119,41 @@ bool CheckDriveAccess(std::string driveName, bool checkIfContainsFutureAccessIte
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
wchar_t* filteredPath = _wcsdup(convert(driveName)->Data());
|
wchar_t* filteredPath = _wcsdup(ConvertUTF8ToWString(driveName).c_str());
|
||||||
wcscat_s(filteredPath, sizeof(L"\\*.*"), L"\\*.*");
|
wcscat_s(filteredPath, sizeof(L"\\*.*"), L"\\*.*");
|
||||||
#if !defined(_M_ARM)
|
|
||||||
searchResults = FindFirstFileExFromAppW(
|
searchResults = FindFirstFileExFromAppW(
|
||||||
filteredPath, FindExInfoBasic, &findDataResult,
|
filteredPath, FindExInfoBasic, &findDataResult,
|
||||||
FindExSearchNameMatch, NULL, 0);
|
FindExSearchNameMatch, NULL, 0);
|
||||||
#else
|
|
||||||
searchResults = FindFirstFileEx(
|
|
||||||
filteredPath, FindExInfoBasic, &findDataResult,
|
|
||||||
FindExSearchNameMatch, NULL, 0);
|
|
||||||
#endif
|
|
||||||
state = searchResults != NULL && searchResults != INVALID_HANDLE_VALUE;
|
state = searchResults != NULL && searchResults != INVALID_HANDLE_VALUE;
|
||||||
if (state) {
|
if (state) {
|
||||||
FindClose(searchResults);
|
FindClose(searchResults);
|
||||||
}
|
}
|
||||||
|
// Cache the state
|
||||||
accessState.insert(std::make_pair(driveName, state));
|
accessState.insert(std::make_pair(driveName, state));
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!state) {
|
||||||
if (!state && checkIfContainsFutureAccessItems) {
|
state = IsRootForAccessibleItems(driveName);
|
||||||
// Consider the drive accessible in case it contain files/folder selected before to avoid empty results
|
|
||||||
state = IsRootForAccessibleItems(driveName) || IsContainsAccessibleItems(driveName);
|
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
bool IsValidUWP(std::string path) {
|
|
||||||
auto p = PathResolver(path);
|
|
||||||
|
|
||||||
//Check valid path
|
bool isWriteMode(const char* mode) {
|
||||||
if (p.Type() == PathTypeUWP::UNDEFINED || !p.IsAbsolute()) {
|
return (!strcmp(mode, "w") || !strcmp(mode, "wb") || !strcmp(mode, "wt") || !strcmp(mode, "at") || !strcmp(mode, "a"));
|
||||||
// Nothing to do here
|
|
||||||
VERBOSE_LOG(FILESYS, "File is not valid (%s)", p.ToString().c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool state = false;
|
|
||||||
|
|
||||||
auto resolvedPathStr = p.ToString();
|
|
||||||
if (ends_with(resolvedPathStr, "LocalState") || ends_with(resolvedPathStr, "TempState") || ends_with(resolvedPathStr, "LocalCache")) {
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (isChild(GetLocalFolder(), resolvedPathStr)) {
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
else if (isChild(GetInstallationFolder(), resolvedPathStr)) {
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
else if (isChild(GetTempFolder(), resolvedPathStr)) {
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state)
|
|
||||||
{
|
|
||||||
auto p = PathUWP(path);
|
|
||||||
std::string driveName = p.GetRootVolume().ToString();
|
|
||||||
state = CheckDriveAccess(driveName, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return !state;
|
|
||||||
}
|
}
|
||||||
|
bool isAppendMode(const char* mode) {
|
||||||
bool IsExistsUWP(std::string path) {
|
return (!strcmp(mode, "at") || !strcmp(mode, "a"));
|
||||||
if (IsValidUWP(path)) {
|
|
||||||
auto storageItem = GetStorageItem(path);
|
|
||||||
if (storageItem.IsValid()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If folder is not accessible but contains accessible items
|
|
||||||
// consider it exists
|
|
||||||
if (IsContainsAccessibleItems(path)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If folder is not accessible but is part of accessible items
|
|
||||||
// consider it exists
|
|
||||||
std::list<std::string> tmp;
|
|
||||||
if (IsRootForAccessibleItems(path, tmp, true)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ERROR_LOG(FILESYS, "Couldn't find or access (%s)", path.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsDirectoryUWP(std::string path) {
|
|
||||||
if (IsValidUWP(path)) {
|
|
||||||
auto storageItem = GetStorageItem(path);
|
|
||||||
if (storageItem.IsValid()) {
|
|
||||||
if (storageItem.IsDirectory()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* GetFileStream(std::string path, const char* mode) {
|
|
||||||
FILE* file{};
|
|
||||||
if (IsValidUWP(path)) {
|
|
||||||
auto storageItem = GetStorageItem(path);
|
|
||||||
if (storageItem.IsValid()) {
|
|
||||||
file = storageItem.GetStream(mode);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Forward the request to parent folder
|
|
||||||
auto p = PathUWP(path);
|
|
||||||
auto itemName = p.GetFilename();
|
|
||||||
auto rootPath = p.GetDirectory();
|
|
||||||
if (IsValidUWP(rootPath)) {
|
|
||||||
storageItem = GetStorageItem(rootPath);
|
|
||||||
if (storageItem.IsValid()) {
|
|
||||||
file = storageItem.GetFileStream(itemName, mode);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ERROR_LOG(FILESYS, "Couldn't find or access (%s)", rootPath.c_str());
|
|
||||||
ERROR_LOG(FILESYS, "Couldn't find or access (%s)", path.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* GetFileStreamFromApp(std::string path, const char* mode) {
|
FILE* GetFileStreamFromApp(std::string path, const char* mode) {
|
||||||
|
|
||||||
FILE* file{};
|
FILE* file{};
|
||||||
|
|
||||||
auto pathResolved = PathUWP(ResolvePathUWP(path));
|
auto pathResolved = Path(ResolvePathUWP(path));
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
auto access = GENERIC_READ;
|
auto access = GENERIC_READ;
|
||||||
auto share = FILE_SHARE_READ;
|
auto share = FILE_SHARE_READ;
|
||||||
|
@ -480,11 +166,8 @@ FILE* GetFileStreamFromApp(std::string path, const char* mode) {
|
||||||
share = FILE_SHARE_WRITE;
|
share = FILE_SHARE_WRITE;
|
||||||
creation = isAppend ? OPEN_ALWAYS : CREATE_ALWAYS;
|
creation = isAppend ? OPEN_ALWAYS : CREATE_ALWAYS;
|
||||||
}
|
}
|
||||||
#if !defined(_M_ARM)
|
|
||||||
handle = CreateFile2FromAppW(pathResolved.ToWString().c_str(), access, share, creation, nullptr);
|
handle = CreateFile2FromAppW(pathResolved.ToWString().c_str(), access, share, creation, nullptr);
|
||||||
#else
|
|
||||||
handle = CreateFile2(pathResolved.ToWString().c_str(), access, share, creation, nullptr);
|
|
||||||
#endif
|
|
||||||
if (handle != INVALID_HANDLE_VALUE) {
|
if (handle != INVALID_HANDLE_VALUE) {
|
||||||
int flags = _O_RDONLY;
|
int flags = _O_RDONLY;
|
||||||
if (isWrite) {
|
if (isWrite) {
|
||||||
|
@ -496,262 +179,121 @@ FILE* GetFileStreamFromApp(std::string path, const char* mode) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma region Content Helpers
|
|
||||||
ItemInfoUWP GetFakeFolderInfo(std::string folder) {
|
|
||||||
ItemInfoUWP info;
|
|
||||||
auto folderPath = PathUWP(folder);
|
|
||||||
info.name = folderPath.GetFilename();
|
|
||||||
info.fullName = folderPath.ToString();
|
|
||||||
|
|
||||||
info.isDirectory = true;
|
|
||||||
|
|
||||||
info.size = 1;
|
|
||||||
info.lastAccessTime = 1000;
|
|
||||||
info.lastWriteTime = 1000;
|
|
||||||
info.changeTime = 1000;
|
|
||||||
info.creationTime = 1000;
|
|
||||||
|
|
||||||
info.attributes = FILE_ATTRIBUTE_DIRECTORY;
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
std::list<ItemInfoUWP> GetFolderContents(std::string path, bool deepScan) {
|
#pragma region FakeFolders
|
||||||
std::list<ItemInfoUWP> contents;
|
// Parent and child full path
|
||||||
|
std::string getSubRoot(std::string parent, std::string child) {
|
||||||
|
auto childCut = child;
|
||||||
|
childCut = ReplaceAll(childCut, (parent + "/"), "");
|
||||||
|
size_t len = childCut.find_first_of('/', 0);
|
||||||
|
auto subRoot = childCut.substr(0, len);
|
||||||
|
|
||||||
if (IsValidUWP(path)) {
|
return parent + "/" + subRoot;
|
||||||
auto storageItem = GetStorageItem(path);
|
}
|
||||||
if (storageItem.IsValid()) {
|
|
||||||
|
|
||||||
// Files
|
bool isChild(std::string parent, std::string child) {
|
||||||
// deepScan is slow, try to avoid it
|
return child.find(parent) != std::string::npos;
|
||||||
auto rfiles = deepScan ? storageItem.GetAllFiles() : storageItem.GetFiles();
|
}
|
||||||
for each (auto file in rfiles) {
|
|
||||||
contents.push_back(file.GetFileInfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Folders
|
// Parent full path, child full path, child name only
|
||||||
// deepScan is slow, try to avoid it
|
bool isParent(std::string parent, std::string child, std::string childName) {
|
||||||
auto rfolders = deepScan ? storageItem.GetAllFolders() : storageItem.GetFolders();
|
parent.append("/" + childName);
|
||||||
for each (auto folder in rfolders) {
|
return parent == child;
|
||||||
contents.push_back(folder.GetFolderInfo());
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DEBUG_LOG(FILESYS, "Cannot get contents!, checking for other options.. (%s)", path.c_str());
|
|
||||||
}
|
|
||||||
; }
|
|
||||||
|
|
||||||
if (contents.size() == 0) {
|
bool IsRootForAccessibleItems(Path path, std::list<std::string>& subRoot, bool breakOnFirstMatch = false) {
|
||||||
// Folder maybe not accessible or not exists
|
path = PathResolver(path);
|
||||||
// if not accessible, maybe some items inside it were selected before
|
auto FutureAccessItems = GetFutureAccessList();
|
||||||
// and they already in our accessible list
|
for (auto& fItem : FutureAccessItems) {
|
||||||
if (IsContainsAccessibleItems(path)) {
|
if (isChild(path.ToString(), fItem)) {
|
||||||
DEBUG_LOG(FILESYS, "Folder contains accessible items (%s)", path.c_str());
|
if (breakOnFirstMatch) {
|
||||||
|
// Just checking, we don't need to loop for each item
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
auto sub = getSubRoot(path.ToString(), fItem);
|
||||||
|
|
||||||
// Check contents
|
// This check can be better, but that's how I can do it in C++
|
||||||
auto cItems = GetStorageItemsByParent(path);
|
if (!endsWith(sub, ":")) {
|
||||||
if (!cItems.empty()) {
|
bool alreadyAdded = false;
|
||||||
for each (auto item in cItems) {
|
for each (auto sItem in subRoot) {
|
||||||
VERBOSE_LOG(FILESYS, "Appending accessible item (%s)", item.GetPath().c_str());
|
if (!strcmp(sItem.c_str(), sub.c_str())) {
|
||||||
contents.push_back(item.GetItemInfo());
|
alreadyAdded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!alreadyAdded) {
|
||||||
|
subRoot.push_back(sub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
return !subRoot.empty();
|
||||||
// Check if this folder is root for accessible item
|
}
|
||||||
// then add fake folder as sub root to avoid empty results
|
bool IsRootForAccessibleItems(std::string path)
|
||||||
|
{
|
||||||
|
std::list<std::string> tmp;
|
||||||
|
return IsRootForAccessibleItems(Path(path), tmp, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetFakeFolders(Path path, std::vector<File::FileInfo>* files, const char* filter, std::set<std::string> filters) {
|
||||||
|
bool state = false;
|
||||||
std::list<std::string> subRoot;
|
std::list<std::string> subRoot;
|
||||||
if (IsRootForAccessibleItems(path, subRoot)) {
|
if (IsRootForAccessibleItems(path, subRoot)) {
|
||||||
DEBUG_LOG(FILESYS, "Folder is root for accessible items (%s)", path.c_str());
|
|
||||||
|
|
||||||
if (!subRoot.empty()) {
|
if (!subRoot.empty()) {
|
||||||
for each (auto sItem in subRoot) {
|
for each (auto sItem in subRoot) {
|
||||||
VERBOSE_LOG(FILESYS, "Appending fake folder (%s)", sItem.c_str());
|
auto folderPath = Path(sItem);
|
||||||
contents.push_back(GetFakeFolderInfo(sItem));
|
auto attributes = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
}
|
File::FileInfo info;
|
||||||
}
|
info.name = folderPath.GetFilename();
|
||||||
|
info.fullName = folderPath;
|
||||||
|
info.exists = true;
|
||||||
|
info.size = 1;
|
||||||
|
info.isDirectory = true;
|
||||||
|
info.isWritable = (attributes & FILE_ATTRIBUTE_READONLY) == 0;
|
||||||
|
info.atime = 1000;
|
||||||
|
info.mtime = 1000;
|
||||||
|
info.ctime = 1000;
|
||||||
|
if (attributes & FILE_ATTRIBUTE_READONLY) {
|
||||||
|
info.access = 0444; // Read
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VERBOSE_LOG(FILESYS, "Cannot get any content!.. (%s)", path.c_str());
|
info.access = 0666; // Read/Write
|
||||||
|
}
|
||||||
|
if (attributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
|
info.access |= 0111; // Execute
|
||||||
|
}
|
||||||
|
if (!info.isDirectory) {
|
||||||
|
std::string ext = info.fullName.GetFileExtension();
|
||||||
|
if (!ext.empty()) {
|
||||||
|
ext = ext.substr(1); // Remove the dot.
|
||||||
|
if (filter && filters.find(ext) == filters.end()) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return contents;
|
files->push_back(info);
|
||||||
}
|
state = true;
|
||||||
std::list<ItemInfoUWP> GetFolderContents(std::wstring path, bool deepScan) {
|
}
|
||||||
return GetFolderContents(convert(path), deepScan);
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemInfoUWP GetItemInfoUWP(std::string path) {
|
|
||||||
ItemInfoUWP info;
|
|
||||||
info.size = -1;
|
|
||||||
info.attributes = INVALID_FILE_ATTRIBUTES;
|
|
||||||
|
|
||||||
if (IsValidUWP(path)) {
|
|
||||||
auto storageItem = GetStorageItem(path);
|
|
||||||
if (storageItem.IsValid()) {
|
|
||||||
info = storageItem.GetItemInfo();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ERROR_LOG(FILESYS, "Couldn't find or access (%s)", path.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Basics
|
|
||||||
int64_t GetSizeUWP(std::string path) {
|
|
||||||
int64_t size = 0;
|
|
||||||
if (IsValidUWP(path)) {
|
|
||||||
auto storageItem = GetStorageItem(path);
|
|
||||||
if (storageItem.IsValid()) {
|
|
||||||
size = storageItem.GetSize();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ERROR_LOG(FILESYS, "Couldn't find or access (%s)", path.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeleteUWP(std::string path) {
|
|
||||||
bool state = false;
|
|
||||||
if (IsValidUWP(path)) {
|
|
||||||
auto storageItem = GetStorageItem(path);
|
|
||||||
if (storageItem.IsValid()) {
|
|
||||||
DEBUG_LOG(FILESYS, "Delete (%s)", path.c_str());
|
|
||||||
state = storageItem.Delete();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DEBUG_LOG(FILESYS, "Couldn't find or access (%s)", path.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CreateDirectoryUWP(std::string path, bool replaceExisting) {
|
|
||||||
bool state = false;
|
|
||||||
auto p = PathUWP(path);
|
|
||||||
auto itemName = p.GetFilename();
|
|
||||||
auto rootPath = p.GetDirectory();
|
|
||||||
|
|
||||||
if (IsValidUWP(rootPath)) {
|
|
||||||
auto storageItem = GetStorageItem(rootPath);
|
|
||||||
if (storageItem.IsValid()) {
|
|
||||||
DEBUG_LOG(FILESYS, "Create new folder (%s)", path.c_str());
|
|
||||||
state = storageItem.CreateFolder(itemName, replaceExisting);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ERROR_LOG(FILESYS, "Couldn't find or access (%s)", rootPath.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CopyUWP(std::string path, std::string dest) {
|
|
||||||
bool state = false;
|
|
||||||
|
|
||||||
if (IsValidUWP(path) && IsValidUWP(dest)) {
|
|
||||||
auto srcStorageItem = GetStorageItem(path);
|
|
||||||
if (srcStorageItem.IsValid()) {
|
|
||||||
auto destDir = dest;
|
|
||||||
auto srcName = srcStorageItem.GetName();
|
|
||||||
auto dstPath = PathUWP(dest);
|
|
||||||
auto dstName = dstPath.GetFilename();
|
|
||||||
// Destination must be parent folder
|
|
||||||
destDir = dstPath.GetDirectory();
|
|
||||||
auto dstStorageItem = GetStorageItem(destDir, true, true);
|
|
||||||
if (dstStorageItem.IsValid()) {
|
|
||||||
DEBUG_LOG(FILESYS, "Copy (%s) to (%s)", path.c_str(), dest.c_str());
|
|
||||||
state = srcStorageItem.Copy(dstStorageItem, dstName);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ERROR_LOG(FILESYS, "Couldn't find or access (%s)", dest.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ERROR_LOG(FILESYS, "Couldn't find or access (%s)", path.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MoveUWP(std::string path, std::string dest) {
|
|
||||||
bool state = false;
|
|
||||||
|
|
||||||
if (IsValidUWP(path) && IsValidUWP(dest)) {
|
|
||||||
auto srcStorageItem = GetStorageItem(path);
|
|
||||||
|
|
||||||
if (srcStorageItem.IsValid()) {
|
|
||||||
auto destDir = dest;
|
|
||||||
auto srcName = srcStorageItem.GetName();
|
|
||||||
auto dstPath = PathUWP(dest);
|
|
||||||
auto dstName = dstPath.GetFilename();
|
|
||||||
// Destination must be parent folder
|
|
||||||
destDir = dstPath.GetDirectory();
|
|
||||||
auto dstStorageItem = GetStorageItem(destDir, true, true);
|
|
||||||
if (dstStorageItem.IsValid()) {
|
|
||||||
DEBUG_LOG(FILESYS, "Move (%s) to (%s)", path.c_str(), dest.c_str());
|
|
||||||
state = srcStorageItem.Move(dstStorageItem, dstName);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ERROR_LOG(FILESYS, "Couldn't find or access (%s)", dest.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ERROR_LOG(FILESYS, "Couldn't find or access (%s)", path.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenameUWP(std::string path, std::string name) {
|
|
||||||
bool state = false;
|
|
||||||
|
|
||||||
auto srcRoot = PathUWP(path).GetDirectory();
|
|
||||||
auto dstRoot = PathUWP(name).GetDirectory();
|
|
||||||
// Check if system using rename to move
|
|
||||||
if (iequals(srcRoot, dstRoot)) {
|
|
||||||
auto srcStorageItem = GetStorageItem(path);
|
|
||||||
if (srcStorageItem.IsValid()) {
|
|
||||||
DEBUG_LOG(FILESYS, "Rename (%s) to (%s)", path.c_str(), name.c_str());
|
|
||||||
state = srcStorageItem.Rename(name);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DEBUG_LOG(FILESYS, "Couldn't find or access (%s)", path.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DEBUG_LOG(FILESYS, " Rename used as move -> call move (%s) to (%s)", path.c_str(), name.c_str());
|
|
||||||
state = MoveUWP(path, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
|
|
||||||
#pragma region Helpers
|
#pragma region Helpers
|
||||||
bool OpenFile(std::string path) {
|
bool OpenFile(std::string path) {
|
||||||
bool state = false;
|
bool state = false;
|
||||||
|
path = ReplaceAll(path, "/", "\\");
|
||||||
|
|
||||||
auto storageItem = GetStorageItem(path);
|
StorageFile^ storageItem;
|
||||||
if (storageItem.IsValid()) {
|
ExecuteTask(storageItem, StorageFile::GetFileFromPathAsync(ToPlatformString(path)));
|
||||||
if (!storageItem.IsDirectory()) {
|
if (storageItem != nullptr) {
|
||||||
ExecuteTask(state, Windows::System::Launcher::LaunchFileAsync(storageItem.GetStorageFile()), false);
|
ExecuteTask(state, Windows::System::Launcher::LaunchFileAsync(storageItem), false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto uri = ref new Windows::Foundation::Uri(convert(path));
|
auto uri = ref new Windows::Foundation::Uri(ToPlatformString(path));
|
||||||
ExecuteTask(state, Windows::System::Launcher::LaunchUriAsync(uri), false);
|
ExecuteTask(state, Windows::System::Launcher::LaunchUriAsync(uri), false);
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
|
@ -759,16 +301,12 @@ bool OpenFile(std::string path) {
|
||||||
|
|
||||||
bool OpenFolder(std::string path) {
|
bool OpenFolder(std::string path) {
|
||||||
bool state = false;
|
bool state = false;
|
||||||
auto uri = ref new Windows::Foundation::Uri(convert(path));
|
path = ReplaceAll(path, "/", "\\");
|
||||||
|
|
||||||
auto storageItem = GetStorageItem(path);
|
StorageFolder^ storageItem;
|
||||||
if (storageItem.IsValid()) {
|
ExecuteTask(storageItem, StorageFolder::GetFolderFromPathAsync(ToPlatformString(path)));
|
||||||
if (storageItem.IsDirectory()) {
|
if (storageItem != nullptr) {
|
||||||
ExecuteTask(state, Windows::System::Launcher::LaunchFolderAsync(storageItem.GetStorageFolder()), false);
|
ExecuteTask(state, Windows::System::Launcher::LaunchFolderAsync(storageItem), false);
|
||||||
}
|
|
||||||
else {
|
|
||||||
OpenFile(storageItem.GetPath());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -781,89 +319,13 @@ bool IsFirstStart() {
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Logs
|
#pragma region Logs
|
||||||
// Get log file name
|
|
||||||
std::string currentLogFile;
|
|
||||||
std::string getLogFileName() {
|
|
||||||
//Initial new name each session/launch
|
|
||||||
if (currentLogFile.empty() || currentLogFile.size() == 0) {
|
|
||||||
std::time_t now = std::time(0);
|
|
||||||
char mbstr[100];
|
|
||||||
std::strftime(mbstr, 100, "ppsspp %d-%m-%Y (%T).txt", std::localtime(&now));
|
|
||||||
std::string formatedDate(mbstr);
|
|
||||||
std::replace(formatedDate.begin(), formatedDate.end(), ':', '-');
|
|
||||||
currentLogFile = formatedDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentLogFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current log file location
|
|
||||||
StorageFolder^ GetLogsStorageFolder() {
|
|
||||||
// Ensure 'LOGS' folder is created
|
|
||||||
auto workingFolder = GetStorageItem(GetWorkingFolder());
|
|
||||||
StorageFolder^ logsFolder;
|
|
||||||
if (workingFolder.IsValid()) {
|
|
||||||
auto workingStorageFolder = workingFolder.GetStorageFolder();
|
|
||||||
ExecuteTask(logsFolder, workingStorageFolder->CreateFolderAsync("LOGS", CreationCollisionOption::OpenIfExists));
|
|
||||||
}
|
|
||||||
return logsFolder;
|
|
||||||
}
|
|
||||||
std::string GetLogFile() {
|
std::string GetLogFile() {
|
||||||
std::string logFilePath = "";
|
Path logFilePath = Path(GetWorkingFolder() + "\\PSP\\ppsspp.txt");
|
||||||
|
HANDLE h = CreateFile2FromAppW(logFilePath.ToWString().c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, CREATE_ALWAYS, nullptr);
|
||||||
// Ensure 'LOGS' folder is created
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
StorageFolder^ logsFolder = GetLogsStorageFolder();
|
return std::string();
|
||||||
|
|
||||||
if (logsFolder != nullptr) {
|
|
||||||
auto logFileName = convert(getLogFileName());
|
|
||||||
StorageFile^ logFile;
|
|
||||||
ExecuteTask(logFile, logsFolder->CreateFileAsync(logFileName, CreationCollisionOption::OpenIfExists));
|
|
||||||
|
|
||||||
if (logFile != nullptr) {
|
|
||||||
logFilePath = convert(logFile->Path);
|
|
||||||
}
|
}
|
||||||
}
|
return logFilePath.ToString();
|
||||||
|
|
||||||
return logFilePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save logs to folder selected by the user
|
|
||||||
bool SaveLogs() {
|
|
||||||
try {
|
|
||||||
auto folderPicker = ref new Windows::Storage::Pickers::FolderPicker();
|
|
||||||
folderPicker->SuggestedStartLocation = Windows::Storage::Pickers::PickerLocationId::Desktop;
|
|
||||||
folderPicker->FileTypeFilter->Append("*");
|
|
||||||
|
|
||||||
StorageFolder^ saveFolder;
|
|
||||||
ExecuteTask(saveFolder, folderPicker->PickSingleFolderAsync());
|
|
||||||
|
|
||||||
if (saveFolder != nullptr) {
|
|
||||||
StorageFolder^ logsFolder = GetLogsStorageFolder();
|
|
||||||
|
|
||||||
if (logsFolder != nullptr) {
|
|
||||||
StorageFolderW logsCache(logsFolder);
|
|
||||||
logsCache.Copy(saveFolder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CleanupLogs() {
|
|
||||||
StorageFolder^ logsFolder = GetLogsStorageFolder();
|
|
||||||
if (logsFolder != nullptr) {
|
|
||||||
StorageFolderW logsCache(logsFolder);
|
|
||||||
std::list<StorageFileW> files = logsCache.GetFiles();
|
|
||||||
if (!files.empty()) {
|
|
||||||
for each (auto fItem in files) {
|
|
||||||
if (fItem.GetSize() == 0) {
|
|
||||||
fItem.Delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
|
@ -4,56 +4,18 @@
|
||||||
// Telegram: @basharastifan
|
// Telegram: @basharastifan
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
// GitHub: https://github.com/basharast/UWP2Win32
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// GetWorkingFolder()
|
|
||||||
// SetWorkingFolder(std::string location)
|
|
||||||
// GetInstallationFolder()
|
|
||||||
// GetLocalFolder()
|
|
||||||
// GetTempFolder()
|
|
||||||
// GetPicturesFolder()
|
|
||||||
// GetVideosFolder()
|
|
||||||
// GetDocumentsFolder()
|
|
||||||
// GetMusicFolder()
|
|
||||||
// GetPreviewPath(std::string path)
|
|
||||||
//
|
|
||||||
// CreateFileUWP(std::string path, int accessMode, int shareMode, int openMode)
|
|
||||||
// CreateFileUWP(std::wstring path, int accessMode, int shareMode, int openMode)
|
|
||||||
// GetFileStream(std::string path, const char* mode)
|
|
||||||
// IsValidUWP(std::string path)
|
|
||||||
// IsExistsUWP(std::string path)
|
|
||||||
// IsDirectoryUWP(std::string path)
|
|
||||||
//
|
|
||||||
// GetFolderContents(std::string path, T& files)
|
|
||||||
// GetFolderContents(std::wstring path, T& files)
|
|
||||||
// GetFileInfoUWP(std::string path, T& info)
|
|
||||||
//
|
|
||||||
// GetSizeUWP(std::string path)
|
|
||||||
// DeleteUWP(std::string path)
|
|
||||||
// CreateDirectoryUWP(std::string path, bool replaceExisting)
|
|
||||||
// RenameUWP(std::string path, std::string name)
|
|
||||||
// CopyUWP(std::string path, std::string name)
|
|
||||||
// MoveUWP(std::string path, std::string name)
|
|
||||||
//
|
|
||||||
// OpenFile(std::string path)
|
|
||||||
// OpenFolder(std::string path)
|
|
||||||
// IsFirstStart()
|
|
||||||
//
|
|
||||||
// GetLogFile()
|
|
||||||
// SaveLogs()
|
|
||||||
// CleanupLogs()
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "Common/File/DirListing.h"
|
||||||
|
|
||||||
#include "StoragePath.h"
|
|
||||||
#include "StorageInfo.h"
|
|
||||||
#include "StorageAccess.h"
|
#include "StorageAccess.h"
|
||||||
#include "StoragePickers.h"
|
#include "StoragePickers.h"
|
||||||
|
|
||||||
// Locations
|
// Locations
|
||||||
std::string GetWorkingFolder(); // Where main data is, default is app data
|
std::string GetWorkingFolder(); // Where main data is, default is app data
|
||||||
void SetWorkingFolder(std::string location); // Change working location
|
|
||||||
std::string GetInstallationFolder();
|
std::string GetInstallationFolder();
|
||||||
std::string GetLocalFolder();
|
std::string GetLocalFolder();
|
||||||
std::string GetTempFolder();
|
std::string GetTempFolder();
|
||||||
|
@ -66,32 +28,13 @@ std::string GetPreviewPath(std::string path);
|
||||||
bool isLocalState(std::string path);
|
bool isLocalState(std::string path);
|
||||||
|
|
||||||
// Management
|
// Management
|
||||||
HANDLE CreateFileUWP(std::string path, int accessMode = GENERIC_READ, int shareMode = FILE_SHARE_READ, int openMode = OPEN_EXISTING);
|
|
||||||
HANDLE CreateFileUWP(std::wstring path, int accessMode = GENERIC_READ, int shareMode = FILE_SHARE_READ, int openMode = OPEN_EXISTING);
|
|
||||||
FILE* GetFileStream(std::string path, const char* mode);
|
|
||||||
// `GetFileStreamFromApp` Will use Windows UWP API, use it instead of fopen..etc
|
// `GetFileStreamFromApp` Will use Windows UWP API, use it instead of fopen..etc
|
||||||
FILE* GetFileStreamFromApp(std::string path, const char* mode);
|
FILE* GetFileStreamFromApp(std::string path, const char* mode);
|
||||||
bool IsValidUWP(std::string path);
|
|
||||||
bool IsExistsUWP(std::string path);
|
|
||||||
bool IsDirectoryUWP(std::string path);
|
|
||||||
|
|
||||||
std::list<ItemInfoUWP> GetFolderContents(std::string path, bool deepScan = false);
|
// 'driveName' like C:
|
||||||
std::list<ItemInfoUWP> GetFolderContents(std::wstring path, bool deepScan = false);
|
bool CheckDriveAccess(std::string driveName);
|
||||||
ItemInfoUWP GetItemInfoUWP(std::string path);
|
bool GetFakeFolders(Path path, std::vector<File::FileInfo>* files, const char* filter, std::set<std::string> filters);
|
||||||
bool IsContainsAccessibleItems(std::string path);
|
|
||||||
bool IsRootForAccessibleItems(std::string path);
|
bool IsRootForAccessibleItems(std::string path);
|
||||||
// 'checkIfContainsFutureAccessItems' for listing purposes not real access, 'driveName' like C:
|
|
||||||
bool CheckDriveAccess(std::string driveName, bool checkIfContainsFutureAccessItems);
|
|
||||||
|
|
||||||
// Basics
|
|
||||||
int64_t GetSizeUWP(std::string path);
|
|
||||||
bool DeleteUWP(std::string path);
|
|
||||||
bool CreateDirectoryUWP(std::string path, bool replaceExisting = true);
|
|
||||||
bool RenameUWP(std::string path, std::string name);
|
|
||||||
// Add file name to destination path
|
|
||||||
bool CopyUWP(std::string path, std::string dest);
|
|
||||||
// Add file name to destination path
|
|
||||||
bool MoveUWP(std::string path, std::string dest);
|
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
bool OpenFile(std::string path);
|
bool OpenFile(std::string path);
|
||||||
|
@ -101,6 +44,3 @@ std::string ResolvePathUWP(std::string path);
|
||||||
|
|
||||||
// Log helpers
|
// Log helpers
|
||||||
std::string GetLogFile();
|
std::string GetLogFile();
|
||||||
bool SaveLogs(); // With picker
|
|
||||||
void CleanupLogs();
|
|
||||||
|
|
||||||
|
|
|
@ -1,272 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Based on 'Path' from PPSSPP
|
|
||||||
// For updates check: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cctype>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "StoragePath.h"
|
|
||||||
#include "StorageLog.h"
|
|
||||||
#include "StorageExtensions.h"
|
|
||||||
|
|
||||||
PathUWP::PathUWP(const std::string &str) {
|
|
||||||
Init(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathUWP::PathUWP(const std::wstring &str) {
|
|
||||||
type_ = PathTypeUWP::NATIVE;
|
|
||||||
Init(convert(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PathUWP::Init(const std::string &str) {
|
|
||||||
if (str.empty()) {
|
|
||||||
type_ = PathTypeUWP::UNDEFINED;
|
|
||||||
path_.clear();
|
|
||||||
} else if (starts_with(str, "http://") || starts_with(str, "https://")) {
|
|
||||||
type_ = PathTypeUWP::HTTP;
|
|
||||||
path_ = str;
|
|
||||||
} else {
|
|
||||||
type_ = PathTypeUWP::NATIVE;
|
|
||||||
path_ = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flip all the slashes around. We flip them back on ToWString().
|
|
||||||
for (size_t i = 0; i < path_.size(); i++) {
|
|
||||||
if (path_[i] == '\\') {
|
|
||||||
path_[i] = '/';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't pop_back if it's just "/".
|
|
||||||
if (type_ == PathTypeUWP::NATIVE && path_.size() > 1 && path_.back() == '/') {
|
|
||||||
path_.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We always use forward slashes internally, we convert to backslash only when
|
|
||||||
// converted to a wstring.
|
|
||||||
PathUWP PathUWP::operator /(const std::string &subdir) const {
|
|
||||||
// Direct string manipulation.
|
|
||||||
|
|
||||||
if (subdir.empty()) {
|
|
||||||
return PathUWP(path_);
|
|
||||||
}
|
|
||||||
std::string fullPath = path_;
|
|
||||||
if (subdir.front() != '/' && (fullPath.empty() || fullPath.back() != '/')) {
|
|
||||||
fullPath += "/";
|
|
||||||
}
|
|
||||||
fullPath += subdir;
|
|
||||||
// Prevent adding extra slashes.
|
|
||||||
if (fullPath.back() == '/') {
|
|
||||||
fullPath.pop_back();
|
|
||||||
}
|
|
||||||
return PathUWP(fullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PathUWP::operator /=(const std::string &subdir) {
|
|
||||||
*this = *this / subdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
PathUWP PathUWP::WithExtraExtension(const std::string &ext) const {
|
|
||||||
return PathUWP(path_ + ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathUWP PathUWP::WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const {
|
|
||||||
if (ends_with(path_, oldExtension)) {
|
|
||||||
std::string newPath = path_.substr(0, path_.size() - oldExtension.size());
|
|
||||||
return PathUWP(newPath + newExtension);
|
|
||||||
} else {
|
|
||||||
return PathUWP(*this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PathUWP PathUWP::WithReplacedExtension(const std::string &newExtension) const {
|
|
||||||
if (path_.empty()) {
|
|
||||||
return PathUWP(*this);
|
|
||||||
}
|
|
||||||
std::string extension = GetFileExtension();
|
|
||||||
std::string newPath = path_.substr(0, path_.size() - extension.size()) + newExtension;
|
|
||||||
return PathUWP(newPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PathUWP::GetFilename() const {
|
|
||||||
size_t pos = path_.rfind('/');
|
|
||||||
if (pos != std::string::npos) {
|
|
||||||
return path_.substr(pos + 1);
|
|
||||||
}
|
|
||||||
return path_;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string GetExtFromString(const std::string &str) {
|
|
||||||
size_t pos = str.rfind(".");
|
|
||||||
if (pos == std::string::npos) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
size_t slash_pos = str.rfind("/");
|
|
||||||
if (slash_pos != std::string::npos && slash_pos > pos) {
|
|
||||||
// Don't want to detect "df/file" from "/as.df/file"
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
std::string ext = str.substr(pos);
|
|
||||||
for (size_t i = 0; i < ext.size(); i++) {
|
|
||||||
ext[i] = tolower(ext[i]);
|
|
||||||
}
|
|
||||||
return ext;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PathUWP::GetFileExtension() const {
|
|
||||||
return GetExtFromString(path_);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PathUWP::GetDirectory() const {
|
|
||||||
size_t pos = path_.rfind('/');
|
|
||||||
if (type_ == PathTypeUWP::HTTP) {
|
|
||||||
// Things are a bit different for HTTP, because we probably ended with /.
|
|
||||||
if (pos + 1 == path_.size()) {
|
|
||||||
pos = path_.rfind('/', pos - 1);
|
|
||||||
if (pos != path_.npos && pos > 8) {
|
|
||||||
return path_.substr(0, pos + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos != std::string::npos) {
|
|
||||||
if (pos == 0) {
|
|
||||||
return "/"; // We're at the root.
|
|
||||||
}
|
|
||||||
return path_.substr(0, pos);
|
|
||||||
} else if (path_.size() == 2 && path_[1] == ':') {
|
|
||||||
// Windows fake-root.
|
|
||||||
return "/";
|
|
||||||
} else {
|
|
||||||
// There could be a ':', too. Unlike the slash, let's include that
|
|
||||||
// in the returned directory.
|
|
||||||
size_t c_pos = path_.rfind(':');
|
|
||||||
if (c_pos != std::string::npos) {
|
|
||||||
return path_.substr(0, c_pos + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// No directory components, we're a relative path.
|
|
||||||
return path_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PathUWP::FilePathContainsNoCase(const std::string &needle) const {
|
|
||||||
std::string haystack;
|
|
||||||
|
|
||||||
haystack = path_;
|
|
||||||
auto pred = [](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); };
|
|
||||||
auto found = std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), pred);
|
|
||||||
return found != haystack.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PathUWP::StartsWith(const PathUWP &other) const {
|
|
||||||
if (type_ != other.type_) {
|
|
||||||
// Bad
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return starts_with(path_, other.path_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &PathUWP::ToString() const {
|
|
||||||
return path_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring PathUWP::ToWString() const {
|
|
||||||
std::wstring w = convertToWString(path_);
|
|
||||||
for (size_t i = 0; i < w.size(); i++) {
|
|
||||||
if (w[i] == '/') {
|
|
||||||
w[i] = '\\';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PathUWP::ToVisualString() const {
|
|
||||||
if (type_ == PathTypeUWP::NATIVE) {
|
|
||||||
return replace2(path_, "/", "\\");
|
|
||||||
} else {
|
|
||||||
return path_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PathUWP::CanNavigateUp() const {
|
|
||||||
if (path_ == "/" || path_.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (type_ == PathTypeUWP::HTTP) {
|
|
||||||
size_t rootSlash = path_.find_first_of('/', strlen("https://"));
|
|
||||||
if (rootSlash == path_.npos || path_.size() < rootSlash + 1) {
|
|
||||||
// This means, "http://server" or "http://server/". Can't go up.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PathUWP PathUWP::NavigateUp() const {
|
|
||||||
std::string dir = GetDirectory();
|
|
||||||
return PathUWP(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
PathUWP PathUWP::GetRootVolume() const {
|
|
||||||
if (!IsAbsolute()) {
|
|
||||||
// Can't do anything
|
|
||||||
return PathUWP(path_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path_[1] == ':') {
|
|
||||||
// Windows path with drive letter
|
|
||||||
std::string path = path_.substr(0, 2);
|
|
||||||
return PathUWP(path);
|
|
||||||
}
|
|
||||||
// Support UNC and device paths.
|
|
||||||
if (path_[0] == '/' && path_[1] == '/') {
|
|
||||||
size_t next = 2;
|
|
||||||
if ((path_[2] == '.' || path_[2] == '?') && path_[3] == '/') {
|
|
||||||
// Device path, or "\\.\UNC" path, skip the dot and consider the device the root.
|
|
||||||
next = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t len = path_.find_first_of('/', next);
|
|
||||||
return PathUWP(path_.substr(0, len));
|
|
||||||
}
|
|
||||||
return PathUWP("/");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PathUWP::IsAbsolute() const {
|
|
||||||
if (path_.empty())
|
|
||||||
return true;
|
|
||||||
else if (path_.front() == '/')
|
|
||||||
return true;
|
|
||||||
else if (path_.size() > 3 && path_[1] == ':')
|
|
||||||
return true; // Windows path with drive letter
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PathUWP::ComputePathTo(const PathUWP &other, std::string &path) const {
|
|
||||||
if (other == *this) {
|
|
||||||
path.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!other.StartsWith(*this)) {
|
|
||||||
// Can't do this. Should return an error.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*this == other) {
|
|
||||||
// Equal, the path is empty.
|
|
||||||
path.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path_ == "/") {
|
|
||||||
path = other.path_.substr(1);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
path = other.path_.substr(path_.size() + 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Based on 'Path' from PPSSPP
|
|
||||||
// For updates check: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define HOST_IS_CASE_SENSITIVE 0
|
|
||||||
|
|
||||||
enum class PathTypeUWP {
|
|
||||||
UNDEFINED = 0,
|
|
||||||
NATIVE = 1, // Can be relative.
|
|
||||||
CONTENT_URI = 2, // Android only. Can only be absolute!
|
|
||||||
HTTP = 3, // http://, https://
|
|
||||||
};
|
|
||||||
|
|
||||||
// Windows paths are always stored with '/' slashes in a Path.
|
|
||||||
// On .ToWString(), they are flipped back to '\'.
|
|
||||||
|
|
||||||
class PathUWP {
|
|
||||||
private:
|
|
||||||
void Init(const std::string &str);
|
|
||||||
|
|
||||||
public:
|
|
||||||
PathUWP() : type_(PathTypeUWP::UNDEFINED) {}
|
|
||||||
explicit PathUWP(const std::string &str);
|
|
||||||
|
|
||||||
explicit PathUWP(const std::wstring &str);
|
|
||||||
|
|
||||||
PathTypeUWP Type() const {
|
|
||||||
return type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Valid() const { return !path_.empty(); }
|
|
||||||
bool IsRoot() const { return path_ == "/"; } // Special value - only path that can end in a slash.
|
|
||||||
|
|
||||||
// Some std::string emulation for simplicity.
|
|
||||||
bool empty() const { return !Valid(); }
|
|
||||||
void clear() {
|
|
||||||
type_ = PathTypeUWP::UNDEFINED;
|
|
||||||
path_.clear();
|
|
||||||
}
|
|
||||||
size_t size() const {
|
|
||||||
return path_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// WARNING: Potentially unsafe usage, if it's not NATIVE.
|
|
||||||
const char *c_str() const {
|
|
||||||
return path_.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsAbsolute() const;
|
|
||||||
|
|
||||||
// Returns a path extended with a subdirectory.
|
|
||||||
PathUWP operator /(const std::string &subdir) const;
|
|
||||||
|
|
||||||
// Navigates down into a subdir.
|
|
||||||
void operator /=(const std::string &subdir);
|
|
||||||
|
|
||||||
// File extension manipulation.
|
|
||||||
PathUWP WithExtraExtension(const std::string &ext) const;
|
|
||||||
PathUWP WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const;
|
|
||||||
PathUWP WithReplacedExtension(const std::string &newExtension) const;
|
|
||||||
|
|
||||||
// Removes the last component.
|
|
||||||
std::string GetFilename() const; // Really, GetLastComponent. Could be a file or directory. Includes the extension.
|
|
||||||
std::string GetFileExtension() const; // Always lowercase return. Includes the dot.
|
|
||||||
std::string GetDirectory() const;
|
|
||||||
|
|
||||||
const std::string &ToString() const;
|
|
||||||
|
|
||||||
std::wstring ToWString() const;
|
|
||||||
|
|
||||||
std::string ToVisualString() const;
|
|
||||||
|
|
||||||
bool CanNavigateUp() const;
|
|
||||||
PathUWP NavigateUp() const;
|
|
||||||
|
|
||||||
// Navigates as far up as possible from this path. If not possible to navigate upwards, returns the same path.
|
|
||||||
// Not actually always the root of the volume, especially on systems like Mac and Linux where things are often mounted.
|
|
||||||
// For Android directory trees, navigates to the root of the tree.
|
|
||||||
PathUWP GetRootVolume() const;
|
|
||||||
|
|
||||||
bool ComputePathTo(const PathUWP&other, std::string &path) const;
|
|
||||||
|
|
||||||
bool operator ==(const PathUWP&other) const {
|
|
||||||
return path_ == other.path_ && type_ == other.type_;
|
|
||||||
}
|
|
||||||
bool operator !=(const PathUWP&other) const {
|
|
||||||
return path_ != other.path_ || type_ != other.type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FilePathContainsNoCase(const std::string &needle) const;
|
|
||||||
|
|
||||||
bool StartsWith(const PathUWP&other) const;
|
|
||||||
|
|
||||||
bool operator <(const PathUWP&other) const {
|
|
||||||
return path_ < other.path_;
|
|
||||||
}
|
|
||||||
bool operator >(const PathUWP&other) const {
|
|
||||||
return path_ > other.path_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// The internal representation is currently always the plain string.
|
|
||||||
// For CPU efficiency we could keep an AndroidStorageContentURI too,
|
|
||||||
// but I don't think the encode/decode cost is significant. We simply create
|
|
||||||
// those for processing instead.
|
|
||||||
std::string path_;
|
|
||||||
|
|
||||||
PathTypeUWP type_;
|
|
||||||
};
|
|
|
@ -3,14 +3,8 @@
|
||||||
// Email: bashar@astifan.online
|
// Email: bashar@astifan.online
|
||||||
// Telegram: @basharastifan
|
// Telegram: @basharastifan
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// ChooseFolder()
|
|
||||||
// ChooseFile(std::vector<std::string> exts)
|
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
#include "StorageLog.h"
|
|
||||||
#include "StorageExtensions.h"
|
|
||||||
#include "StorageAsync.h"
|
#include "StorageAsync.h"
|
||||||
#include "StorageAccess.h"
|
#include "StorageAccess.h"
|
||||||
|
|
||||||
|
@ -47,7 +41,7 @@ concurrency::task<Platform::String^> PickSingleFile(std::vector<std::string> ext
|
||||||
|
|
||||||
if (exts.size() > 0) {
|
if (exts.size() > 0) {
|
||||||
for each (auto ext in exts) {
|
for each (auto ext in exts) {
|
||||||
filePicker->FileTypeFilter->Append(convert(ext));
|
filePicker->FileTypeFilter->Append(ToPlatformString(ext));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -68,13 +62,13 @@ concurrency::task<Platform::String^> PickSingleFile(std::vector<std::string> ext
|
||||||
|
|
||||||
concurrency::task<std::string> ChooseFile(std::vector<std::string> exts) {
|
concurrency::task<std::string> ChooseFile(std::vector<std::string> exts) {
|
||||||
return PickSingleFile(exts).then([](Platform::String^ filePath) {
|
return PickSingleFile(exts).then([](Platform::String^ filePath) {
|
||||||
return convert(filePath);
|
return FromPlatformString(filePath);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
concurrency::task<std::string> ChooseFolder() {
|
concurrency::task<std::string> ChooseFolder() {
|
||||||
return PickSingleFolder().then([](Platform::String^ folderPath) {
|
return PickSingleFolder().then([](Platform::String^ folderPath) {
|
||||||
return convert(folderPath);
|
return FromPlatformString(folderPath);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,6 @@
|
||||||
// Email: bashar@astifan.online
|
// Email: bashar@astifan.online
|
||||||
// Telegram: @basharastifan
|
// Telegram: @basharastifan
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// ChooseFolder()
|
|
||||||
// ChooseFile(std::vector<std::string> exts)
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ppl.h>
|
#include <ppl.h>
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
// This is small bridge to invoke UWP Storage manager
|
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// CreateFileUWP(const char* path, int accessMode, int shareMode, int openMode)
|
|
||||||
// GetFileAttributesUWP(const void* name, void* lpFileInformation)
|
|
||||||
// DeleteFileUWP(const void* name)
|
|
||||||
|
|
||||||
#include "UWP2C.h"
|
|
||||||
#include "StorageManager.h"
|
|
||||||
#include "StorageExtensions.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
void* CreateFileUWP(const char* path, int accessMode, int shareMode, int openMode) {
|
|
||||||
std::string fn = convert(path);
|
|
||||||
|
|
||||||
return (void*)CreateFileUWP(fn, accessMode, shareMode, openMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetFileAttributesUWP(const void* name, void* lpFileInformation) {
|
|
||||||
size_t size = sizeof(WIN32_FILE_ATTRIBUTE_DATA);
|
|
||||||
WIN32_FILE_ATTRIBUTE_DATA* file_attributes = (WIN32_FILE_ATTRIBUTE_DATA*)(malloc(size));
|
|
||||||
|
|
||||||
std::string fn = convert((const char*)name);
|
|
||||||
HANDLE handle = CreateFileUWP(fn);
|
|
||||||
|
|
||||||
FILETIME createTime{};
|
|
||||||
FILETIME changeTime{};
|
|
||||||
|
|
||||||
DWORD fileSizeHigh = 0;
|
|
||||||
DWORD fileSizeLow = 0;
|
|
||||||
DWORD fileAttributes = 32;
|
|
||||||
|
|
||||||
if (handle != INVALID_HANDLE_VALUE) {
|
|
||||||
size_t size = sizeof(FILE_BASIC_INFO);
|
|
||||||
FILE_BASIC_INFO* information = (FILE_BASIC_INFO*)(malloc(size));
|
|
||||||
if (information) {
|
|
||||||
if (FALSE != GetFileInformationByHandleEx(handle, FileBasicInfo, information, (DWORD)size)) {
|
|
||||||
createTime.dwHighDateTime = information->CreationTime.HighPart;
|
|
||||||
createTime.dwLowDateTime = information->CreationTime.LowPart;
|
|
||||||
changeTime.dwHighDateTime = information->ChangeTime.HighPart;
|
|
||||||
changeTime.dwLowDateTime = information->ChangeTime.LowPart;
|
|
||||||
fileAttributes = information->FileAttributes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LARGE_INTEGER fsize{ 0 };
|
|
||||||
if (FALSE == GetFileSizeEx(handle, &fsize)) {
|
|
||||||
LARGE_INTEGER end_offset;
|
|
||||||
const LARGE_INTEGER zero{};
|
|
||||||
if (SetFilePointerEx(handle, zero, &end_offset, FILE_END) == 0) {
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fileSizeHigh = (DWORD)end_offset.HighPart;
|
|
||||||
fileSizeLow = (DWORD)end_offset.LowPart;
|
|
||||||
SetFilePointerEx(handle, zero, nullptr, FILE_BEGIN);
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fileSizeHigh = (DWORD)fsize.HighPart;
|
|
||||||
fileSizeLow = (DWORD)fsize.LowPart;
|
|
||||||
|
|
||||||
CloseHandle(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->ftCreationTime = createTime;
|
|
||||||
((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->ftLastAccessTime = changeTime;
|
|
||||||
((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->ftLastWriteTime = changeTime;
|
|
||||||
((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->nFileSizeHigh = fileSizeHigh;
|
|
||||||
((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->nFileSizeLow = fileSizeLow;
|
|
||||||
((WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation)->dwFileAttributes = fileAttributes;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DeleteFileUWP(const void* name) {
|
|
||||||
std::string fn = convert((const char*)name);
|
|
||||||
bool state = DeleteUWP(fn);
|
|
||||||
|
|
||||||
return state ? 1 : 0;
|
|
||||||
}
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,26 +0,0 @@
|
||||||
// UWP STORAGE MANAGER
|
|
||||||
// Copyright (c) 2023 Bashar Astifan.
|
|
||||||
// Email: bashar@astifan.online
|
|
||||||
// Telegram: @basharastifan
|
|
||||||
// GitHub: https://github.com/basharast/UWP2Win32
|
|
||||||
|
|
||||||
// This is small bridge to invoke UWP Storage manager
|
|
||||||
|
|
||||||
// Functions:
|
|
||||||
// CreateFileUWP(const char* path, int accessMode, int shareMode, int openMode)
|
|
||||||
// GetFileAttributesUWP(const void* name, void* lpFileInformation)
|
|
||||||
// DeleteFileUWP(const void* name)
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void* CreateFileUWP(const char* path, int accessMode, int shareMode, int openMode);
|
|
||||||
int GetFileAttributesUWP(const void* name, void* lpFileInformation);
|
|
||||||
int DeleteFileUWP(const void* name);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -32,9 +32,6 @@
|
||||||
*/
|
*/
|
||||||
#ifdef MS_UWP
|
#ifdef MS_UWP
|
||||||
#include <fileapifromapp.h>
|
#include <fileapifromapp.h>
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
#include "UWP/UWPHelpers/UWP2C.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "zip_source_file_win32.h"
|
#include "zip_source_file_win32.h"
|
||||||
|
@ -47,18 +44,11 @@ static char *utf16_strdup(const char *string);
|
||||||
#ifdef MS_UWP && !defined(__LIBRETRO__)
|
#ifdef MS_UWP && !defined(__LIBRETRO__)
|
||||||
static BOOL __stdcall GetFileAttr(const void* name, GET_FILEEX_INFO_LEVELS info_level, void* lpFileInformation) {
|
static BOOL __stdcall GetFileAttr(const void* name, GET_FILEEX_INFO_LEVELS info_level, void* lpFileInformation) {
|
||||||
BOOL state = GetFileAttributesExFromAppW(name, info_level, lpFileInformation);
|
BOOL state = GetFileAttributesExFromAppW(name, info_level, lpFileInformation);
|
||||||
if (state == FALSE) {
|
|
||||||
// Ignore `info_level` not in use for now
|
|
||||||
state = GetFileAttributesUWP(name, lpFileInformation);
|
|
||||||
}
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL __stdcall DelFile(const void* name) {
|
static BOOL __stdcall DelFile(const void* name) {
|
||||||
BOOL state = DeleteFileFromAppW(name);
|
BOOL state = DeleteFileFromAppW(name);
|
||||||
if (state == FALSE) {
|
|
||||||
state = DeleteFileUWP(name);
|
|
||||||
}
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,11 +120,6 @@ utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_AT
|
||||||
return CreateFile2((const wchar_t *)name, access, share_mode, creation_disposition, &extParams);
|
return CreateFile2((const wchar_t *)name, access, share_mode, creation_disposition, &extParams);
|
||||||
#else
|
#else
|
||||||
HANDLE h = CreateFile2FromAppW((const wchar_t *)name, access, share_mode, creation_disposition, NULL);
|
HANDLE h = CreateFile2FromAppW((const wchar_t *)name, access, share_mode, creation_disposition, NULL);
|
||||||
#if !defined(__LIBRETRO__)
|
|
||||||
if (h == INVALID_HANDLE_VALUE) {
|
|
||||||
h = CreateFileUWP(name, (int)access, (int)share_mode, (int)creation_disposition);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return h;
|
return h;
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue