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>
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
#include <fileapifromapp.h>
|
||||
#if !defined(__LIBRETRO__)
|
||||
#include "UWP/UWPHelpers/StorageManager.h"
|
||||
#include "UWP/UWPHelpers/PPSSPPTypesHelpers.h"
|
||||
#endif
|
||||
#include <UWP/UWPHelpers/StorageManager.h>
|
||||
#endif
|
||||
#else
|
||||
#include <strings.h>
|
||||
|
@ -71,11 +68,6 @@ bool GetFileInfo(const Path &path, FileInfo * fileInfo) {
|
|||
WIN32_FILE_ATTRIBUTE_DATA attrs;
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (!GetFileAttributesExFromAppW(path.ToWString().c_str(), GetFileExInfoStandard, &attrs)) {
|
||||
#if !defined(__LIBRETRO__)
|
||||
if (GetFileInfoUWP(path.ToString(), fileInfo)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if (!GetFileAttributesExW(path.ToWString().c_str(), GetFileExInfoStandard, &attrs)) {
|
||||
#endif
|
||||
|
@ -230,11 +222,9 @@ bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const ch
|
|||
#endif
|
||||
if (hFind == INVALID_HANDLE_VALUE) {
|
||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
||||
// Getting folder contents need extra work
|
||||
// request must be done within StorageManager
|
||||
auto contents = GetFolderContents(directory.ToString());
|
||||
if (ItemsInfoUWPToFilesInfo(contents, files, filter, filters)) {
|
||||
std::sort(files->begin(), files->end());
|
||||
// This step just to avoid empty results by adding fake folders
|
||||
// It will help also to navigate back between selected folder
|
||||
if(GetFakeFolders(directory, files, filter, filters)){
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -337,13 +327,7 @@ std::vector<std::string> GetWindowsDrives()
|
|||
{
|
||||
CHAR driveName[] = { (CHAR)(TEXT('A') + i), TEXT(':'), TEXT('\\'), TEXT('\0') };
|
||||
std::string str(driveName);
|
||||
#if !defined(__LIBRETRO__)
|
||||
if (CheckDriveAccess(driveName, true)) {
|
||||
drives.push_back(driveName);
|
||||
}
|
||||
#else
|
||||
drives.push_back(driveName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return drives;
|
||||
|
|
|
@ -53,10 +53,8 @@
|
|||
#include <direct.h> // getcwd
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
#include <fileapifromapp.h>
|
||||
#if !defined(__LIBRETRO__)
|
||||
#include "UWP/UWPHelpers/StorageManager.h"
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -161,13 +159,13 @@ FILE *OpenCFile(const Path &path, const char *mode) {
|
|||
|
||||
#if defined(_WIN32) && defined(UNICODE)
|
||||
#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);
|
||||
|
||||
if (!file) {
|
||||
// Call UWP storage helper
|
||||
file = GetFileStream(path.ToString(), mode);
|
||||
}
|
||||
return file;
|
||||
#else
|
||||
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 PPSSPP_PLATFORM(UWP)
|
||||
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
|
||||
HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
#endif
|
||||
|
@ -391,11 +385,6 @@ bool Exists(const Path &path) {
|
|||
WIN32_FILE_ATTRIBUTE_DATA data{};
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
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;
|
||||
}
|
||||
#else
|
||||
|
@ -434,11 +423,6 @@ bool IsDirectory(const Path &filename) {
|
|||
WIN32_FILE_ATTRIBUTE_DATA data{};
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (!GetFileAttributesExFromAppW(filename.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
|
||||
#if !defined(__LIBRETRO__)
|
||||
if (IsDirectoryUWP(filename.ToString())) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if (!GetFileAttributesEx(filename.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
|
||||
#endif
|
||||
|
@ -492,11 +476,6 @@ bool Delete(const Path &filename) {
|
|||
#ifdef _WIN32
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
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());
|
||||
return false;
|
||||
}
|
||||
|
@ -551,19 +530,8 @@ bool CreateDir(const Path &path) {
|
|||
DEBUG_LOG(COMMON, "CreateDir('%s')", path.c_str());
|
||||
#ifdef _WIN32
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (CreateDirectoryFromAppW(path.ToWString().c_str(), NULL)) {
|
||||
if (CreateDirectoryFromAppW(path.ToWString().c_str(), NULL))
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
#if !defined(__LIBRETRO__)
|
||||
if (File::Exists(path)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
CreateDirectoryUWP(path.ToString());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if (::CreateDirectory(path.ToWString().c_str(), NULL))
|
||||
return true;
|
||||
|
@ -657,16 +625,8 @@ bool DeleteDir(const Path &path) {
|
|||
|
||||
#ifdef _WIN32
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (RemoveDirectoryFromAppW(path.ToWString().c_str())) {
|
||||
if (RemoveDirectoryFromAppW(path.ToWString().c_str()))
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
#if !defined(__LIBRETRO__)
|
||||
if (DeleteUWP(path.ToString())) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if (::RemoveDirectory(path.ToWString().c_str()))
|
||||
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());
|
||||
|
||||
#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 destw = destFilename.ToWString();
|
||||
if (_wrename(srcw.c_str(), destw.c_str()) == 0)
|
||||
return true;
|
||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
||||
else {
|
||||
if (RenameUWP(srcFilename.ToString(), destFilename.ToString())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
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 (CopyFileFromAppW(srcFilename.ToWString().c_str(), destFilename.ToWString().c_str(), FALSE))
|
||||
return true;
|
||||
#if !defined(__LIBRETRO__)
|
||||
else {
|
||||
if (CopyUWP(srcFilename.ToString(), destFilename.ToString())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if (CopyFile(srcFilename.ToWString().c_str(), destFilename.ToWString().c_str(), FALSE))
|
||||
return true;
|
||||
|
@ -846,11 +797,6 @@ bool Move(const Path &srcFilename, const Path &destFilename) {
|
|||
} else if (Copy(srcFilename, destFilename)) {
|
||||
return Delete(srcFilename);
|
||||
} else {
|
||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
||||
if (MoveUWP(srcFilename.ToString(), destFilename.ToString())) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -900,9 +846,6 @@ uint64_t GetFileSize(const Path &filename) {
|
|||
WIN32_FILE_ATTRIBUTE_DATA attr;
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
if (!GetFileAttributesExFromAppW(filename.ToWString().c_str(), GetFileExInfoStandard, &attr)) {
|
||||
#if !defined(__LIBRETRO__)
|
||||
return (uint64_t)GetSizeUWP(filename.ToString());
|
||||
#endif
|
||||
#else
|
||||
if (!GetFileAttributesEx(filename.ToWString().c_str(), GetFileExInfoStandard, &attr)){
|
||||
#endif
|
||||
|
@ -1020,9 +963,7 @@ bool OpenFileInEditor(const Path &fileName) {
|
|||
|
||||
#if PPSSPP_PLATFORM(WINDOWS)
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
#if !defined(__LIBRETRO__)
|
||||
OpenFile(fileName.ToString());
|
||||
#endif
|
||||
#else
|
||||
ShellExecuteW(nullptr, L"open", fileName.ToWString().c_str(), nullptr, nullptr, SW_SHOW);
|
||||
#endif
|
||||
|
|
|
@ -33,9 +33,6 @@
|
|||
#include "Common/CommonWindows.h"
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
#include <fileapifromapp.h>
|
||||
#if !defined(__LIBRETRO__)
|
||||
#include "UWP/UWPHelpers/StorageManager.h"
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
|
@ -111,15 +108,7 @@ LocalFileLoader::LocalFileLoader(const Path &filename)
|
|||
handle_ = CreateFile(filename.ToWString().c_str(), access, share, nullptr, mode, flags, nullptr);
|
||||
#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) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
LARGE_INTEGER end_offset;
|
||||
const LARGE_INTEGER zero{};
|
||||
|
@ -170,11 +159,7 @@ bool LocalFileLoader::Exists() {
|
|||
if (File::GetFileInfo(filename_, &info)) {
|
||||
return info.exists;
|
||||
} else {
|
||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
||||
return IsExistsUWP(filename_.ToString());
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,11 +168,7 @@ bool LocalFileLoader::IsDirectory() {
|
|||
if (File::GetFileInfo(filename_, &info)) {
|
||||
return info.exists && info.isDirectory;
|
||||
}
|
||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
||||
return IsDirectoryUWP(filename_.ToString());
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
s64 LocalFileLoader::FileSize() {
|
||||
|
|
|
@ -52,10 +52,6 @@
|
|||
#include <sys/stat.h>
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
#include <fileapifromapp.h>
|
||||
#if !defined(__LIBRETRO__)
|
||||
#include "UWP/UWPHelpers/StorageManager.h"
|
||||
#include "UWP/UWPHelpers/PPSSPPTypesHelpers.h"
|
||||
#endif
|
||||
#endif
|
||||
#undef FILE_OPEN
|
||||
#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);
|
||||
#endif
|
||||
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) {
|
||||
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);
|
||||
#endif
|
||||
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) {
|
||||
w32err = GetLastError();
|
||||
}
|
||||
|
|
|
@ -41,10 +41,6 @@
|
|||
#include <sys/stat.h>
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
#include <fileapifromapp.h>
|
||||
#if !defined(__LIBRETRO__)
|
||||
#include "UWP/UWPHelpers/StorageManager.h"
|
||||
#include "UWP/UWPHelpers/PPSSPPTypesHelpers.h"
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#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);
|
||||
#endif
|
||||
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)
|
||||
*exists = false;
|
||||
return myVector; //the empty list
|
||||
|
|
|
@ -48,10 +48,6 @@
|
|||
#include "Core/Util/GameManager.h"
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
|
||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
||||
#include "UWP/UWPHelpers/StorageManager.h"
|
||||
#endif
|
||||
|
||||
GameManager g_GameManager;
|
||||
|
||||
static struct zip *ZipOpenPath(Path fileName) {
|
||||
|
@ -79,12 +75,6 @@ GameManager::GameManager() {
|
|||
|
||||
Path GameManager::GetTempFilename() const {
|
||||
#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];
|
||||
GetTempPath(MAX_PATH, tempPath);
|
||||
wchar_t buffer[MAX_PATH];
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
#include "UI/ControlMappingScreen.h"
|
||||
#include "UI/GameSettingsScreen.h"
|
||||
|
||||
#if PPSSPP_PLATFORM(UWP) && !defined(__LIBRETRO__)
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
#include "UWP/UWPHelpers/StorageManager.h"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -522,7 +522,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
|||
else {
|
||||
INFO_LOG(SYSTEM, "No memstick directory file found (tried to open '%s')", pathResolved.c_str());
|
||||
}
|
||||
SetWorkingFolder(g_Config.memStickDirectory.ToString());
|
||||
#elif PPSSPP_PLATFORM(IOS)
|
||||
g_Config.defaultCurrentDirectory = g_Config.internalDataDirectory;
|
||||
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!");
|
||||
g_screenManager = new ScreenManager();
|
||||
#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
|
||||
if (g_Config.memStickDirectory.empty()) {
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include <ppltasks.h>
|
||||
|
||||
#include <UWPHelpers/StorageExtensions.h>
|
||||
#include <UWPHelpers/LaunchItem.h>
|
||||
#include <regex>
|
||||
|
||||
|
|
|
@ -134,8 +134,6 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptr<DX::DeviceResourc
|
|||
|
||||
// Set log file location
|
||||
if (g_Config.bEnableLogging) {
|
||||
// Do cleanup first
|
||||
CleanupLogs();
|
||||
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();
|
||||
dataPackage->RequestedOperation = DataPackageOperation::Copy;
|
||||
dataPackage->SetText(convert(param1));
|
||||
dataPackage->SetText(ToPlatformString(param1));
|
||||
Clipboard::SetContent(dataPackage);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,53 +1,53 @@
|
|||
<?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">
|
||||
<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" />
|
||||
<Properties>
|
||||
<DisplayName>PPSSPP - PSP emulator</DisplayName>
|
||||
<PublisherDisplayName>Henrik Rydgård</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="PPSSPP.App">
|
||||
<uap:VisualElements DisplayName="PPSSPP" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="PPSSPP - PSP emulator" BackgroundColor="transparent">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
<uap:InitialRotationPreference>
|
||||
<uap:Rotation Preference="landscape" />
|
||||
</uap:InitialRotationPreference>
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<uap:Extension Category="windows.fileTypeAssociation">
|
||||
<uap:FileTypeAssociation Name="psprom">
|
||||
<uap:SupportedFileTypes>
|
||||
<uap:FileType>.cso</uap:FileType>
|
||||
<uap:FileType>.bin</uap:FileType>
|
||||
<uap:FileType>.iso</uap:FileType>
|
||||
<uap:FileType>.elf</uap:FileType>
|
||||
</uap:SupportedFileTypes>
|
||||
</uap:FileTypeAssociation>
|
||||
</uap:Extension>
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="ppsspp"/>
|
||||
</uap:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="codeGeneration" />
|
||||
<Capability Name="internetClient" />
|
||||
<uap:Capability Name="removableStorage" />
|
||||
<rescap:Capability Name="runFullTrust"/>
|
||||
<rescap:Capability Name="broadFileSystemAccess" />
|
||||
<rescap:Capability Name="expandedResources" />
|
||||
<Capability Name="internetClientServer"/>
|
||||
<Capability Name="privateNetworkClientServer"/> <!-- For features like remote disk streaming -->
|
||||
</Capabilities>
|
||||
<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" />
|
||||
<Properties>
|
||||
<DisplayName>PPSSPP - PSP emulator</DisplayName>
|
||||
<PublisherDisplayName>Henrik Rydgård</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="PPSSPP.App">
|
||||
<uap:VisualElements DisplayName="PPSSPP" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="PPSSPP - PSP emulator" BackgroundColor="transparent">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
<uap:InitialRotationPreference>
|
||||
<uap:Rotation Preference="landscape" />
|
||||
</uap:InitialRotationPreference>
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<uap:Extension Category="windows.fileTypeAssociation">
|
||||
<uap:FileTypeAssociation Name="psprom">
|
||||
<uap:SupportedFileTypes>
|
||||
<uap:FileType>.cso</uap:FileType>
|
||||
<uap:FileType>.bin</uap:FileType>
|
||||
<uap:FileType>.iso</uap:FileType>
|
||||
<uap:FileType>.elf</uap:FileType>
|
||||
</uap:SupportedFileTypes>
|
||||
</uap:FileTypeAssociation>
|
||||
</uap:Extension>
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="ppsspp"/>
|
||||
</uap:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="codeGeneration" />
|
||||
<Capability Name="internetClient" />
|
||||
<uap:Capability Name="removableStorage" />
|
||||
<rescap:Capability Name="runFullTrust"/>
|
||||
<rescap:Capability Name="broadFileSystemAccess" />
|
||||
<rescap:Capability Name="expandedResources" />
|
||||
<Capability Name="internetClientServer"/>
|
||||
<Capability Name="privateNetworkClientServer"/><!-- For features like remote disc streaming -->
|
||||
</Capabilities>
|
||||
</Package>
|
||||
|
|
|
@ -1,57 +1,57 @@
|
|||
<?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">
|
||||
<Identity Name="32617401-c880-44d1-ba5a-c0b46feba525" Publisher="CN=Henrik" Version="1.14.4.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="32617401-c880-44d1-ba5a-c0b46feba525" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>PPSSPP Gold - PSP emulator</DisplayName>
|
||||
<PublisherDisplayName>Henrik Rydgård</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="PPSSPPGold.App">
|
||||
<uap:VisualElements DisplayName="PPSSPP Gold" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="PPSSPP Gold - PSP emulator" BackgroundColor="transparent">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">
|
||||
<uap:ShowNameOnTiles>
|
||||
<uap:ShowOn Tile="square150x150Logo" />
|
||||
<uap:ShowOn Tile="wide310x150Logo" />
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
<uap:InitialRotationPreference>
|
||||
<uap:Rotation Preference="landscape" />
|
||||
</uap:InitialRotationPreference>
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<uap:Extension Category="windows.fileTypeAssociation">
|
||||
<uap:FileTypeAssociation Name="psprom">
|
||||
<uap:SupportedFileTypes>
|
||||
<uap:FileType>.cso</uap:FileType>
|
||||
<uap:FileType>.bin</uap:FileType>
|
||||
<uap:FileType>.iso</uap:FileType>
|
||||
<uap:FileType>.elf</uap:FileType>
|
||||
</uap:SupportedFileTypes>
|
||||
</uap:FileTypeAssociation>
|
||||
</uap:Extension>
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="ppsspp"/>
|
||||
</uap:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="codeGeneration" />
|
||||
<Capability Name="internetClient" />
|
||||
<uap:Capability Name="removableStorage" />
|
||||
<rescap:Capability Name="runFullTrust"/>
|
||||
<rescap:Capability Name="broadFileSystemAccess" />
|
||||
<rescap:Capability Name="expandedResources" />
|
||||
<Capability Name="internetClientServer"/>
|
||||
<Capability Name="privateNetworkClientServer"/> <!-- For features like remote disk streaming -->
|
||||
</Capabilities>
|
||||
<Identity Name="32617401-c880-44d1-ba5a-c0b46feba525" Publisher="CN=Henrik" Version="1.14.4.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="32617401-c880-44d1-ba5a-c0b46feba525" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>PPSSPP Gold - PSP emulator</DisplayName>
|
||||
<PublisherDisplayName>Henrik Rydgård</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="PPSSPPGold.App">
|
||||
<uap:VisualElements DisplayName="PPSSPP Gold" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="PPSSPP Gold - PSP emulator" BackgroundColor="transparent">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">
|
||||
<uap:ShowNameOnTiles>
|
||||
<uap:ShowOn Tile="square150x150Logo" />
|
||||
<uap:ShowOn Tile="wide310x150Logo" />
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
<uap:InitialRotationPreference>
|
||||
<uap:Rotation Preference="landscape" />
|
||||
</uap:InitialRotationPreference>
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<uap:Extension Category="windows.fileTypeAssociation">
|
||||
<uap:FileTypeAssociation Name="psprom">
|
||||
<uap:SupportedFileTypes>
|
||||
<uap:FileType>.cso</uap:FileType>
|
||||
<uap:FileType>.bin</uap:FileType>
|
||||
<uap:FileType>.iso</uap:FileType>
|
||||
<uap:FileType>.elf</uap:FileType>
|
||||
</uap:SupportedFileTypes>
|
||||
</uap:FileTypeAssociation>
|
||||
</uap:Extension>
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="ppsspp"/>
|
||||
</uap:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="codeGeneration" />
|
||||
<Capability Name="internetClient" />
|
||||
<uap:Capability Name="removableStorage" />
|
||||
<rescap:Capability Name="runFullTrust"/>
|
||||
<rescap:Capability Name="broadFileSystemAccess" />
|
||||
<rescap:Capability Name="expandedResources" />
|
||||
<Capability Name="internetClientServer"/>
|
||||
<Capability Name="privateNetworkClientServer"/><!-- For features like remote disc streaming -->
|
||||
</Capabilities>
|
||||
</Package>
|
||||
|
|
|
@ -1,53 +1,53 @@
|
|||
<?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">
|
||||
<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" />
|
||||
<Properties>
|
||||
<DisplayName>PPSSPP - PSP emulator</DisplayName>
|
||||
<PublisherDisplayName>Henrik Rydgård</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="PPSSPP.App">
|
||||
<uap:VisualElements DisplayName="PPSSPP" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="PPSSPP - PSP emulator" BackgroundColor="transparent">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
<uap:InitialRotationPreference>
|
||||
<uap:Rotation Preference="landscape" />
|
||||
</uap:InitialRotationPreference>
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<uap:Extension Category="windows.fileTypeAssociation">
|
||||
<uap:FileTypeAssociation Name="psprom">
|
||||
<uap:SupportedFileTypes>
|
||||
<uap:FileType>.cso</uap:FileType>
|
||||
<uap:FileType>.bin</uap:FileType>
|
||||
<uap:FileType>.iso</uap:FileType>
|
||||
<uap:FileType>.elf</uap:FileType>
|
||||
</uap:SupportedFileTypes>
|
||||
</uap:FileTypeAssociation>
|
||||
</uap:Extension>
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="ppsspp"/>
|
||||
</uap:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="codeGeneration" />
|
||||
<Capability Name="internetClient" />
|
||||
<uap:Capability Name="removableStorage" />
|
||||
<rescap:Capability Name="runFullTrust"/>
|
||||
<rescap:Capability Name="broadFileSystemAccess" />
|
||||
<rescap:Capability Name="expandedResources" />
|
||||
<Capability Name="internetClientServer"/>
|
||||
<Capability Name="privateNetworkClientServer"/> <!-- For features like remote disk streaming -->
|
||||
</Capabilities>
|
||||
<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" />
|
||||
<Properties>
|
||||
<DisplayName>PPSSPP - PSP emulator</DisplayName>
|
||||
<PublisherDisplayName>Henrik Rydgård</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="PPSSPP.App">
|
||||
<uap:VisualElements DisplayName="PPSSPP" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="PPSSPP - PSP emulator" BackgroundColor="transparent">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
<uap:InitialRotationPreference>
|
||||
<uap:Rotation Preference="landscape" />
|
||||
</uap:InitialRotationPreference>
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<uap:Extension Category="windows.fileTypeAssociation">
|
||||
<uap:FileTypeAssociation Name="psprom">
|
||||
<uap:SupportedFileTypes>
|
||||
<uap:FileType>.cso</uap:FileType>
|
||||
<uap:FileType>.bin</uap:FileType>
|
||||
<uap:FileType>.iso</uap:FileType>
|
||||
<uap:FileType>.elf</uap:FileType>
|
||||
</uap:SupportedFileTypes>
|
||||
</uap:FileTypeAssociation>
|
||||
</uap:Extension>
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="ppsspp"/>
|
||||
</uap:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="codeGeneration" />
|
||||
<Capability Name="internetClient" />
|
||||
<uap:Capability Name="removableStorage" />
|
||||
<rescap:Capability Name="runFullTrust"/>
|
||||
<rescap:Capability Name="broadFileSystemAccess" />
|
||||
<rescap:Capability Name="expandedResources" />
|
||||
<Capability Name="internetClientServer"/>
|
||||
<Capability Name="privateNetworkClientServer"/><!-- For features like remote disc streaming -->
|
||||
</Capabilities>
|
||||
</Package>
|
||||
|
|
|
@ -89,12 +89,14 @@
|
|||
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
|
||||
<AppxSymbolPackageEnabled>False</AppxSymbolPackageEnabled>
|
||||
<AppxBundle>Never</AppxBundle>
|
||||
<PackageCertificateThumbprint>C8DEB388B9BC89D1DC61324E4E9D9FE6A796B7AA</PackageCertificateThumbprint>
|
||||
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||
<AppInstallerUpdateFrequency>1</AppInstallerUpdateFrequency>
|
||||
<AppInstallerUpdateFrequency>0</AppInstallerUpdateFrequency>
|
||||
<AppInstallerCheckForUpdateFrequency>OnApplicationRun</AppInstallerCheckForUpdateFrequency>
|
||||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
||||
<PackageCertificateKeyFile>PPSSPP_UWP_TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
|
||||
<GenerateTestArtifacts>True</GenerateTestArtifacts>
|
||||
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<Link>
|
||||
|
@ -458,21 +460,10 @@
|
|||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="UWPUtil.h" />
|
||||
<ClInclude Include="XAudioSoundStream.h" />
|
||||
<ClInclude Include="UWPHelpers\PPSSPPTypesHelpers.h" />
|
||||
<ClInclude Include="UWPHelpers\StorageAccess.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\StoragePath.h" />
|
||||
<ClInclude Include="UWPHelpers\StoragePickers.h" />
|
||||
<ClInclude Include="UWPHelpers\UWP2C.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\git-version.cpp">
|
||||
|
@ -485,15 +476,10 @@
|
|||
<ClCompile Include="NKCodeFromWindowsSystem.cpp" />
|
||||
<ClCompile Include="PPSSPP_UWPMain.cpp" />
|
||||
<ClCompile Include="UWPHelpers\LaunchItem.h" />
|
||||
<ClCompile Include="UWPHelpers\PPSSPPTypesHelpers.cpp" />
|
||||
<ClCompile Include="UWPHelpers\StorageAccess.cpp" />
|
||||
<ClCompile Include="UWPHelpers\StorageAsync.cpp" />
|
||||
<ClCompile Include="UWPHelpers\StorageExtensions.cpp" />
|
||||
<ClCompile Include="UWPHelpers\StorageHandler.cpp" />
|
||||
<ClCompile Include="UWPHelpers\StorageManager.cpp" />
|
||||
<ClCompile Include="UWPHelpers\StoragePath.cpp" />
|
||||
<ClCompile Include="UWPHelpers\StoragePickers.cpp" />
|
||||
<ClCompile Include="UWPHelpers\UWP2C.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
|
|
|
@ -17,78 +17,30 @@
|
|||
<UniqueIdentifier>a5564d79-b131-4b27-9f5f-d80671731d94</UniqueIdentifier>
|
||||
<Extensions>bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png</Extensions>
|
||||
</Filter>
|
||||
<ClInclude Include="UWPHelpers\PPSSPPTypesHelpers.h">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UWPHelpers\StorageAccess.h">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UWPHelpers\StorageAsync.h">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</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">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UWPHelpers\StoragePath.h">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UWPHelpers\StoragePickers.h">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UWPHelpers\UWP2C.h">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="UWPHelpers\PPSSPPTypesHelpers.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UWPHelpers\StorageAccess.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UWPHelpers\StorageAsync.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UWPHelpers\StorageExtensions.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UWPHelpers\StorageHandler.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UWPHelpers\StorageManager.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UWPHelpers\StoragePath.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UWPHelpers\StoragePickers.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UWPHelpers\UWP2C.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="Common\DirectXHelper.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <fcntl.h>
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "StorageExtensions.h"
|
||||
#include "UWPUtil.h"
|
||||
#include <regex>
|
||||
|
||||
|
||||
|
@ -41,7 +41,7 @@ public:
|
|||
|
||||
if (arg->Name == "cmd")
|
||||
{
|
||||
auto command = convert(arg->Value);
|
||||
auto command = FromPlatformString(arg->Value);
|
||||
DEBUG_LOG(FILESYS, "Launch command %s", command.c_str());
|
||||
|
||||
std::regex rgx("\"(.+\[^\/]+)\"");
|
||||
|
@ -59,7 +59,7 @@ public:
|
|||
}
|
||||
}
|
||||
else if (arg->Name == "launchOnExit") {
|
||||
launchOnExit = convert(arg->Value);
|
||||
launchOnExit = FromPlatformString(arg->Value);
|
||||
DEBUG_LOG(FILESYS, "On exit URI %s", launchOnExit.c_str());
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ public:
|
|||
std::string GetFilePath() {
|
||||
std::string path = launchPath;
|
||||
if (storageFile != nullptr) {
|
||||
path = convert(storageFile->Path);
|
||||
path = FromPlatformString(storageFile->Path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ public:
|
|||
|
||||
if (!launchOnExit.empty()) {
|
||||
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);
|
||||
}
|
||||
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
|
||||
// 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 "StorageAccess.h"
|
||||
#include "StorageItemW.h"
|
||||
#include "UWPUtil.h"
|
||||
#include <Common/File/Path.h>
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::Storage;
|
||||
|
@ -36,8 +16,12 @@ using namespace Windows::Foundation::Collections;
|
|||
using namespace Windows::Storage::AccessCache;
|
||||
using namespace Windows::ApplicationModel;
|
||||
|
||||
// Main lookup list
|
||||
std::list<StorageItemW> FutureAccessItems;
|
||||
std::list<std::string> alist;
|
||||
void AppendToAccessList(Platform::String^ path)
|
||||
{
|
||||
Path p(FromPlatformString(path));
|
||||
alist.push_back(p.ToString());
|
||||
}
|
||||
|
||||
// Get value from app local settings
|
||||
Platform::String^ GetDataFromLocalSettings(Platform::String^ key) {
|
||||
|
@ -54,7 +38,7 @@ Platform::String^ GetDataFromLocalSettings(Platform::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
|
||||
|
@ -77,31 +61,15 @@ bool AddDataToLocalSettings(Platform::String^ key, Platform::String^ data, bool
|
|||
}
|
||||
|
||||
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)
|
||||
void AddItemToFutureList(IStorageItem^ item) {
|
||||
try {
|
||||
if (item != nullptr) {
|
||||
Platform::String^ folderToken = AccessCache::StorageApplicationPermissions::FutureAccessList->Add(item);
|
||||
AddToAccessibleItems(item);
|
||||
AppendToAccessList(item->Path);
|
||||
}
|
||||
}
|
||||
catch (Platform::COMException^ e) {
|
||||
|
@ -120,104 +88,30 @@ IStorageItem^ GetItemByKey(Platform::String^ key) {
|
|||
return item;
|
||||
}
|
||||
|
||||
// Append folder by token to (FutureAccessFolders)
|
||||
void AppendItemByToken(Platform::String^ token) {
|
||||
try {
|
||||
if (token != nullptr && AccessCache::StorageApplicationPermissions::FutureAccessList->ContainsItem(token)) {
|
||||
IStorageItem^ storageItem;
|
||||
ExecuteTask(storageItem, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(token));
|
||||
AddToAccessibleItems(storageItem);
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
std::list<std::string> GetFutureAccessList() {
|
||||
if (alist.empty()) {
|
||||
auto AccessList = AccessCache::StorageApplicationPermissions::FutureAccessList->Entries;
|
||||
for (auto it = 0; it != AccessList->Size; ++it){
|
||||
auto item = AccessList->GetAt(it);
|
||||
try {
|
||||
if (corewindow) {
|
||||
corewindow->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
|
||||
}
|
||||
else {
|
||||
corewindow = CoreWindow::GetForCurrentThread();
|
||||
auto token = item.Token;
|
||||
if (token != nullptr && AccessCache::StorageApplicationPermissions::FutureAccessList->ContainsItem(token)) {
|
||||
IStorageItem^ storageItem;
|
||||
ExecuteTask(storageItem, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(token));
|
||||
if (storageItem != nullptr) {
|
||||
AppendToAccessList(storageItem->Path);
|
||||
}
|
||||
else {
|
||||
AccessCache::StorageApplicationPermissions::FutureAccessList->Remove(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
|
||||
catch (Platform::COMException^ e) {
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
AppendToAccessList(ApplicationData::Current->LocalFolder->Path);
|
||||
AppendToAccessList(ApplicationData::Current->TemporaryFolder->Path);
|
||||
}
|
||||
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) {
|
||||
// Access denied or file moved/deleted
|
||||
AccessCache::StorageApplicationPermissions::FutureAccessList->Remove(listItem.Token);
|
||||
}
|
||||
}
|
||||
|
||||
// Get files/folders selected by the user
|
||||
UpdateItemsByFutureList();
|
||||
|
||||
// Append known folders
|
||||
#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;
|
||||
return alist;
|
||||
}
|
||||
|
|
|
@ -4,19 +4,12 @@
|
|||
// Telegram: @basharastifan
|
||||
// GitHub: https://github.com/basharast/UWP2Win32
|
||||
|
||||
// Functions:
|
||||
// GetDataFromLocalSettings(std::string key)
|
||||
// AddDataToLocalSettings(std::string key, std::string data, bool replace)
|
||||
//
|
||||
// FillLookupList()
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
// Local settings
|
||||
std::string GetDataFromLocalSettings(std::string key);
|
||||
bool AddDataToLocalSettings(std::string key, std::string data, bool replace);
|
||||
|
||||
// Lookup list
|
||||
void FillLookupList();
|
||||
std::list<std::string> GetFutureAccessList();
|
||||
|
|
|
@ -7,20 +7,20 @@
|
|||
// Thanks to RetroArch/Libretro team for this 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"
|
||||
|
||||
bool ActionPass(Windows::Foundation::IAsyncAction^ action)
|
||||
{
|
||||
return TaskHandler<bool>([&]() {
|
||||
return concurrency::create_task(action).then([]() {
|
||||
return true;
|
||||
});
|
||||
}, false);
|
||||
try {
|
||||
return TaskHandler<bool>([&]() {
|
||||
return concurrency::create_task(action).then([]() {
|
||||
return true;
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Async action such as 'Delete' file
|
||||
|
|
|
@ -7,11 +7,6 @@
|
|||
// Thanks to RetroArch/Libretro team for this 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
|
||||
|
||||
#include "pch.h"
|
||||
|
@ -20,8 +15,8 @@
|
|||
#include <wrl.h>
|
||||
#include <wrl/implements.h>
|
||||
|
||||
#include "StorageLog.h"
|
||||
#include "StorageExtensions.h"
|
||||
#include "Common/Log.h"
|
||||
#include "UWPUtil.h"
|
||||
|
||||
using namespace Windows::UI::Core;
|
||||
|
||||
|
@ -38,11 +33,11 @@ T TaskHandler(std::function<concurrency::task<T>()> wtask, T def)
|
|||
wtask().then([&](concurrency::task<T> t) {
|
||||
try
|
||||
{
|
||||
result = t.get();
|
||||
result = t.get();
|
||||
}
|
||||
catch (Platform::Exception^ exception_)
|
||||
{
|
||||
UWP_ERROR_LOG(UWPSMT, convertToChar(exception_->Message));
|
||||
ERROR_LOG(FILESYS, FromPlatformString(exception_->Message).c_str());
|
||||
}
|
||||
done = true;
|
||||
});
|
||||
|
@ -86,7 +81,12 @@ bool ActionPass(Windows::Foundation::IAsyncAction^ action);
|
|||
template<typename T>
|
||||
void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation<T>^ task)
|
||||
{
|
||||
out = TaskPass<T>(task, T());
|
||||
try {
|
||||
out = TaskPass<T>(task, T());
|
||||
}
|
||||
catch (...) {
|
||||
out = T();
|
||||
}
|
||||
};
|
||||
|
||||
// For specific return default value
|
||||
|
@ -96,7 +96,12 @@ void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation<T>^ task)
|
|||
template<typename T>
|
||||
void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation<T>^ task, T def)
|
||||
{
|
||||
out = TaskPass<T>(task, def);
|
||||
try{
|
||||
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
|
||||
// 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 <io.h>
|
||||
#include <fcntl.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 "StorageExtensions.h"
|
||||
#include "StorageHandler.h"
|
||||
#include "StorageAsync.h"
|
||||
#include "StorageAccess.h"
|
||||
#include "StorageItemW.h"
|
||||
#include "StorageLog.h"
|
||||
|
||||
|
||||
using namespace Platform;
|
||||
|
@ -61,37 +25,33 @@ using namespace Windows::Storage;
|
|||
using namespace Windows::Foundation;
|
||||
using namespace Windows::ApplicationModel;
|
||||
|
||||
extern std::list<StorageItemW> FutureAccessItems;
|
||||
|
||||
#pragma region Locations
|
||||
std::string GetWorkingFolder() {
|
||||
if (AppWorkingFolder.empty()) {
|
||||
if (g_Config.memStickDirectory.empty()) {
|
||||
return GetLocalFolder();
|
||||
}
|
||||
else {
|
||||
return AppWorkingFolder;
|
||||
return g_Config.memStickDirectory.ToString();
|
||||
}
|
||||
}
|
||||
void SetWorkingFolder(std::string location) {
|
||||
AppWorkingFolder = location;
|
||||
}
|
||||
std::string GetInstallationFolder() {
|
||||
return convert(Package::Current->InstalledLocation->Path);
|
||||
return FromPlatformString(Package::Current->InstalledLocation->Path);
|
||||
}
|
||||
StorageFolder^ GetLocalStorageFolder() {
|
||||
return ApplicationData::Current->LocalFolder;
|
||||
}
|
||||
std::string GetLocalFolder() {
|
||||
return convert(GetLocalStorageFolder()->Path);
|
||||
return FromPlatformString(GetLocalStorageFolder()->Path);
|
||||
}
|
||||
std::string GetTempFolder() {
|
||||
return convert(ApplicationData::Current->TemporaryFolder->Path);
|
||||
return FromPlatformString(ApplicationData::Current->TemporaryFolder->Path);
|
||||
}
|
||||
std::string GetTempFile(std::string name) {
|
||||
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) {
|
||||
return convert(tmpFile->Path);
|
||||
return FromPlatformString(tmpFile->Path);
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
|
@ -99,231 +59,56 @@ std::string GetTempFile(std::string name) {
|
|||
}
|
||||
std::string GetPicturesFolder() {
|
||||
// Requires 'picturesLibrary' capability
|
||||
return convert(KnownFolders::PicturesLibrary->Path);
|
||||
return FromPlatformString(KnownFolders::PicturesLibrary->Path);
|
||||
}
|
||||
std::string GetVideosFolder() {
|
||||
// Requires 'videosLibrary' capability
|
||||
return convert(KnownFolders::VideosLibrary->Path);
|
||||
return FromPlatformString(KnownFolders::VideosLibrary->Path);
|
||||
}
|
||||
std::string GetDocumentsFolder() {
|
||||
// Requires 'documentsLibrary' capability
|
||||
return convert(KnownFolders::DocumentsLibrary->Path);
|
||||
return FromPlatformString(KnownFolders::DocumentsLibrary->Path);
|
||||
}
|
||||
std::string GetMusicFolder() {
|
||||
// Requires 'musicLibrary' capability
|
||||
return convert(KnownFolders::MusicLibrary->Path);
|
||||
return FromPlatformString(KnownFolders::MusicLibrary->Path);
|
||||
}
|
||||
std::string GetPreviewPath(std::string path) {
|
||||
std::string pathView = path;
|
||||
windowsPath(pathView);
|
||||
replace(pathView, GetLocalFolder(), "LocalState");
|
||||
replace(pathView, GetTempFolder(), "TempState");
|
||||
replace(pathView, GetInstallationFolder(), "Installation folder");
|
||||
|
||||
pathView = ReplaceAll(pathView, "/", "\\");
|
||||
pathView = ReplaceAll(pathView, GetLocalFolder(), "LocalState");
|
||||
pathView = ReplaceAll(pathView, GetTempFolder(), "TempState");
|
||||
pathView = ReplaceAll(pathView, GetInstallationFolder(), "Installation folder");
|
||||
return pathView;
|
||||
}
|
||||
bool isLocalState(std::string path) {
|
||||
return iequals(GetPreviewPath(path), "LocalState");
|
||||
return !_stricmp(GetPreviewPath(path).c_str(), "LocalState");
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Internal
|
||||
PathUWP PathResolver(PathUWP path) {
|
||||
Path PathResolver(Path path) {
|
||||
auto root = path.GetDirectory();
|
||||
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
|
||||
replace(newPath, "/", (GetLocalFolder() + (path.size() > 1 ? "/": "")));
|
||||
newPath = ReplaceAll(newPath, "/", (GetLocalFolder() + (path.size() > 1 ? "/" : "")));
|
||||
}
|
||||
path = PathUWP(newPath);
|
||||
return path;
|
||||
return Path(newPath);
|
||||
}
|
||||
PathUWP PathResolver(std::string path) {
|
||||
return PathResolver(PathUWP(path));
|
||||
Path PathResolver(std::string path) {
|
||||
return PathResolver(Path(path));
|
||||
}
|
||||
|
||||
std::string ResolvePathUWP(std::string path) {
|
||||
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 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;
|
||||
bool CheckDriveAccess(std::string driveName, bool checkIfContainsFutureAccessItems) {
|
||||
bool CheckDriveAccess(std::string driveName) {
|
||||
bool state = false;
|
||||
|
||||
HANDLE searchResults;
|
||||
|
@ -334,140 +119,41 @@ bool CheckDriveAccess(std::string driveName, bool checkIfContainsFutureAccessIte
|
|||
}
|
||||
else {
|
||||
try {
|
||||
wchar_t* filteredPath = _wcsdup(convert(driveName)->Data());
|
||||
wchar_t* filteredPath = _wcsdup(ConvertUTF8ToWString(driveName).c_str());
|
||||
wcscat_s(filteredPath, sizeof(L"\\*.*"), L"\\*.*");
|
||||
#if !defined(_M_ARM)
|
||||
|
||||
searchResults = FindFirstFileExFromAppW(
|
||||
filteredPath, FindExInfoBasic, &findDataResult,
|
||||
FindExSearchNameMatch, NULL, 0);
|
||||
#else
|
||||
searchResults = FindFirstFileEx(
|
||||
filteredPath, FindExInfoBasic, &findDataResult,
|
||||
FindExSearchNameMatch, NULL, 0);
|
||||
#endif
|
||||
|
||||
state = searchResults != NULL && searchResults != INVALID_HANDLE_VALUE;
|
||||
if (state) {
|
||||
FindClose(searchResults);
|
||||
}
|
||||
// Cache the state
|
||||
accessState.insert(std::make_pair(driveName, state));
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!state && checkIfContainsFutureAccessItems) {
|
||||
// Consider the drive accessible in case it contain files/folder selected before to avoid empty results
|
||||
state = IsRootForAccessibleItems(driveName) || IsContainsAccessibleItems(driveName);
|
||||
if (!state) {
|
||||
state = IsRootForAccessibleItems(driveName);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
bool IsValidUWP(std::string path) {
|
||||
auto p = PathResolver(path);
|
||||
|
||||
//Check valid path
|
||||
if (p.Type() == PathTypeUWP::UNDEFINED || !p.IsAbsolute()) {
|
||||
// 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 isWriteMode(const char* mode) {
|
||||
return (!strcmp(mode, "w") || !strcmp(mode, "wb") || !strcmp(mode, "wt") || !strcmp(mode, "at") || !strcmp(mode, "a"));
|
||||
}
|
||||
|
||||
bool IsExistsUWP(std::string path) {
|
||||
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;
|
||||
bool isAppendMode(const char* mode) {
|
||||
return (!strcmp(mode, "at") || !strcmp(mode, "a"));
|
||||
}
|
||||
|
||||
FILE* GetFileStreamFromApp(std::string path, const char* mode) {
|
||||
|
||||
FILE* file{};
|
||||
|
||||
auto pathResolved = PathUWP(ResolvePathUWP(path));
|
||||
auto pathResolved = Path(ResolvePathUWP(path));
|
||||
HANDLE handle;
|
||||
auto access = GENERIC_READ;
|
||||
auto share = FILE_SHARE_READ;
|
||||
|
@ -480,11 +166,8 @@ FILE* GetFileStreamFromApp(std::string path, const char* mode) {
|
|||
share = FILE_SHARE_WRITE;
|
||||
creation = isAppend ? OPEN_ALWAYS : CREATE_ALWAYS;
|
||||
}
|
||||
#if !defined(_M_ARM)
|
||||
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) {
|
||||
int flags = _O_RDONLY;
|
||||
if (isWrite) {
|
||||
|
@ -496,262 +179,121 @@ FILE* GetFileStreamFromApp(std::string path, const char* mode) {
|
|||
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
|
||||
|
||||
std::list<ItemInfoUWP> GetFolderContents(std::string path, bool deepScan) {
|
||||
std::list<ItemInfoUWP> contents;
|
||||
#pragma region FakeFolders
|
||||
// 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)) {
|
||||
auto storageItem = GetStorageItem(path);
|
||||
if (storageItem.IsValid()) {
|
||||
return parent + "/" + subRoot;
|
||||
}
|
||||
|
||||
// Files
|
||||
// deepScan is slow, try to avoid it
|
||||
auto rfiles = deepScan ? storageItem.GetAllFiles() : storageItem.GetFiles();
|
||||
for each (auto file in rfiles) {
|
||||
contents.push_back(file.GetFileInfo());
|
||||
bool isChild(std::string parent, std::string 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) {
|
||||
parent.append("/" + childName);
|
||||
return parent == child;
|
||||
}
|
||||
|
||||
bool IsRootForAccessibleItems(Path path, std::list<std::string>& subRoot, bool breakOnFirstMatch = false) {
|
||||
path = PathResolver(path);
|
||||
auto FutureAccessItems = GetFutureAccessList();
|
||||
for (auto& fItem : FutureAccessItems) {
|
||||
if (isChild(path.ToString(), fItem)) {
|
||||
if (breakOnFirstMatch) {
|
||||
// Just checking, we don't need to loop for each item
|
||||
return true;
|
||||
}
|
||||
auto sub = getSubRoot(path.ToString(), fItem);
|
||||
|
||||
// Folders
|
||||
// deepScan is slow, try to avoid it
|
||||
auto rfolders = deepScan ? storageItem.GetAllFolders() : storageItem.GetFolders();
|
||||
for each (auto folder in rfolders) {
|
||||
contents.push_back(folder.GetFolderInfo());
|
||||
}
|
||||
}
|
||||
else {
|
||||
DEBUG_LOG(FILESYS, "Cannot get contents!, checking for other options.. (%s)", path.c_str());
|
||||
}
|
||||
; }
|
||||
|
||||
if (contents.size() == 0) {
|
||||
// Folder maybe not accessible or not exists
|
||||
// if not accessible, maybe some items inside it were selected before
|
||||
// and they already in our accessible list
|
||||
if (IsContainsAccessibleItems(path)) {
|
||||
DEBUG_LOG(FILESYS, "Folder contains accessible items (%s)", path.c_str());
|
||||
|
||||
// Check contents
|
||||
auto cItems = GetStorageItemsByParent(path);
|
||||
if (!cItems.empty()) {
|
||||
for each (auto item in cItems) {
|
||||
VERBOSE_LOG(FILESYS, "Appending accessible item (%s)", item.GetPath().c_str());
|
||||
contents.push_back(item.GetItemInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if this folder is root for accessible item
|
||||
// then add fake folder as sub root to avoid empty results
|
||||
std::list<std::string> subRoot;
|
||||
if (IsRootForAccessibleItems(path, subRoot)) {
|
||||
DEBUG_LOG(FILESYS, "Folder is root for accessible items (%s)", path.c_str());
|
||||
|
||||
if (!subRoot.empty()) {
|
||||
for each (auto sItem in subRoot) {
|
||||
VERBOSE_LOG(FILESYS, "Appending fake folder (%s)", sItem.c_str());
|
||||
contents.push_back(GetFakeFolderInfo(sItem));
|
||||
// This check can be better, but that's how I can do it in C++
|
||||
if (!endsWith(sub, ":")) {
|
||||
bool alreadyAdded = false;
|
||||
for each (auto sItem in subRoot) {
|
||||
if (!strcmp(sItem.c_str(), sub.c_str())) {
|
||||
alreadyAdded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
VERBOSE_LOG(FILESYS, "Cannot get any content!.. (%s)", path.c_str());
|
||||
if (!alreadyAdded) {
|
||||
subRoot.push_back(sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return contents;
|
||||
return !subRoot.empty();
|
||||
}
|
||||
std::list<ItemInfoUWP> GetFolderContents(std::wstring path, bool deepScan) {
|
||||
return GetFolderContents(convert(path), deepScan);
|
||||
bool IsRootForAccessibleItems(std::string path)
|
||||
{
|
||||
std::list<std::string> tmp;
|
||||
return IsRootForAccessibleItems(Path(path), tmp, true);
|
||||
}
|
||||
|
||||
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());
|
||||
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;
|
||||
if (IsRootForAccessibleItems(path, subRoot)) {
|
||||
if (!subRoot.empty()) {
|
||||
for each (auto sItem in subRoot) {
|
||||
auto folderPath = Path(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 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
files->push_back(info);
|
||||
state = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return info;
|
||||
return state;
|
||||
}
|
||||
|
||||
#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
|
||||
bool OpenFile(std::string path) {
|
||||
bool state = false;
|
||||
path = ReplaceAll(path, "/", "\\");
|
||||
|
||||
auto storageItem = GetStorageItem(path);
|
||||
if (storageItem.IsValid()) {
|
||||
if (!storageItem.IsDirectory()) {
|
||||
ExecuteTask(state, Windows::System::Launcher::LaunchFileAsync(storageItem.GetStorageFile()), false);
|
||||
}
|
||||
StorageFile^ storageItem;
|
||||
ExecuteTask(storageItem, StorageFile::GetFileFromPathAsync(ToPlatformString(path)));
|
||||
if (storageItem != nullptr) {
|
||||
ExecuteTask(state, Windows::System::Launcher::LaunchFileAsync(storageItem), false);
|
||||
}
|
||||
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);
|
||||
}
|
||||
return state;
|
||||
|
@ -759,16 +301,12 @@ bool OpenFile(std::string path) {
|
|||
|
||||
bool OpenFolder(std::string path) {
|
||||
bool state = false;
|
||||
auto uri = ref new Windows::Foundation::Uri(convert(path));
|
||||
path = ReplaceAll(path, "/", "\\");
|
||||
|
||||
auto storageItem = GetStorageItem(path);
|
||||
if (storageItem.IsValid()) {
|
||||
if (storageItem.IsDirectory()) {
|
||||
ExecuteTask(state, Windows::System::Launcher::LaunchFolderAsync(storageItem.GetStorageFolder()), false);
|
||||
}
|
||||
else {
|
||||
OpenFile(storageItem.GetPath());
|
||||
}
|
||||
StorageFolder^ storageItem;
|
||||
ExecuteTask(storageItem, StorageFolder::GetFolderFromPathAsync(ToPlatformString(path)));
|
||||
if (storageItem != nullptr) {
|
||||
ExecuteTask(state, Windows::System::Launcher::LaunchFolderAsync(storageItem), false);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -781,89 +319,13 @@ bool IsFirstStart() {
|
|||
#pragma endregion
|
||||
|
||||
#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 logFilePath = "";
|
||||
|
||||
// Ensure 'LOGS' folder is created
|
||||
StorageFolder^ logsFolder = GetLogsStorageFolder();
|
||||
|
||||
if (logsFolder != nullptr) {
|
||||
auto logFileName = convert(getLogFileName());
|
||||
StorageFile^ logFile;
|
||||
ExecuteTask(logFile, logsFolder->CreateFileAsync(logFileName, CreationCollisionOption::OpenIfExists));
|
||||
|
||||
if (logFile != nullptr) {
|
||||
logFilePath = convert(logFile->Path);
|
||||
}
|
||||
Path logFilePath = Path(GetWorkingFolder() + "\\PSP\\ppsspp.txt");
|
||||
HANDLE h = CreateFile2FromAppW(logFilePath.ToWString().c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, CREATE_ALWAYS, nullptr);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return logFilePath;
|
||||
return logFilePath.ToString();
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
|
@ -4,56 +4,18 @@
|
|||
// Telegram: @basharastifan
|
||||
// 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
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#include "Common/File/DirListing.h"
|
||||
|
||||
#include "StoragePath.h"
|
||||
#include "StorageInfo.h"
|
||||
#include "StorageAccess.h"
|
||||
#include "StoragePickers.h"
|
||||
|
||||
// Locations
|
||||
std::string GetWorkingFolder(); // Where main data is, default is app data
|
||||
void SetWorkingFolder(std::string location); // Change working location
|
||||
std::string GetInstallationFolder();
|
||||
std::string GetLocalFolder();
|
||||
std::string GetTempFolder();
|
||||
|
@ -66,32 +28,13 @@ std::string GetPreviewPath(std::string path);
|
|||
bool isLocalState(std::string path);
|
||||
|
||||
// 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
|
||||
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);
|
||||
std::list<ItemInfoUWP> GetFolderContents(std::wstring path, bool deepScan = false);
|
||||
ItemInfoUWP GetItemInfoUWP(std::string path);
|
||||
bool IsContainsAccessibleItems(std::string path);
|
||||
// 'driveName' like C:
|
||||
bool CheckDriveAccess(std::string driveName);
|
||||
bool GetFakeFolders(Path path, std::vector<File::FileInfo>* files, const char* filter, std::set<std::string> filters);
|
||||
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
|
||||
bool OpenFile(std::string path);
|
||||
|
@ -101,6 +44,3 @@ std::string ResolvePathUWP(std::string path);
|
|||
|
||||
// Log helpers
|
||||
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
|
||||
// Telegram: @basharastifan
|
||||
|
||||
// Functions:
|
||||
// ChooseFolder()
|
||||
// ChooseFile(std::vector<std::string> exts)
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "StorageLog.h"
|
||||
#include "StorageExtensions.h"
|
||||
#include "StorageAsync.h"
|
||||
#include "StorageAccess.h"
|
||||
|
||||
|
@ -47,7 +41,7 @@ concurrency::task<Platform::String^> PickSingleFile(std::vector<std::string> ext
|
|||
|
||||
if (exts.size() > 0) {
|
||||
for each (auto ext in exts) {
|
||||
filePicker->FileTypeFilter->Append(convert(ext));
|
||||
filePicker->FileTypeFilter->Append(ToPlatformString(ext));
|
||||
}
|
||||
}
|
||||
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) {
|
||||
return PickSingleFile(exts).then([](Platform::String^ filePath) {
|
||||
return convert(filePath);
|
||||
return FromPlatformString(filePath);
|
||||
});
|
||||
}
|
||||
|
||||
concurrency::task<std::string> ChooseFolder() {
|
||||
return PickSingleFolder().then([](Platform::String^ folderPath) {
|
||||
return convert(folderPath);
|
||||
return FromPlatformString(folderPath);
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
// Email: bashar@astifan.online
|
||||
// Telegram: @basharastifan
|
||||
|
||||
// Functions:
|
||||
// ChooseFolder()
|
||||
// ChooseFile(std::vector<std::string> exts)
|
||||
|
||||
#pragma once
|
||||
|
||||
#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
|
||||
#include <fileapifromapp.h>
|
||||
#if !defined(__LIBRETRO__)
|
||||
#include "UWP/UWPHelpers/UWP2C.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "zip_source_file_win32.h"
|
||||
|
@ -47,18 +44,11 @@ static char *utf16_strdup(const char *string);
|
|||
#ifdef MS_UWP && !defined(__LIBRETRO__)
|
||||
static BOOL __stdcall GetFileAttr(const void* name, GET_FILEEX_INFO_LEVELS info_level, void* 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;
|
||||
}
|
||||
|
||||
static BOOL __stdcall DelFile(const void* name) {
|
||||
BOOL state = DeleteFileFromAppW(name);
|
||||
if (state == FALSE) {
|
||||
state = DeleteFileUWP(name);
|
||||
}
|
||||
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);
|
||||
#else
|
||||
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;
|
||||
#endif
|
||||
#else
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue