Major update

This commit is contained in:
Bashar Astifan 2023-04-30 08:54:54 +04:00
parent cb5d18cb03
commit 05776ee6af
41 changed files with 396 additions and 3885 deletions

View file

@ -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,14 +327,8 @@ 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;
#else

View file

@ -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

View file

@ -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>
@ -110,17 +107,9 @@ LocalFileLoader::LocalFileLoader(const Path &filename)
#else
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{};
if (SetFilePointerEx(handle_, zero, &end_offset, FILE_END) == 0) {
@ -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() {

View file

@ -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();
}

View file

@ -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

View file

@ -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];

View file

@ -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

View file

@ -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

View file

@ -14,7 +14,6 @@
#include <ppltasks.h>
#include <UWPHelpers/StorageExtensions.h>
#include <UWPHelpers/LaunchItem.h>
#include <regex>

View file

@ -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;
}

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
<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" />
@ -48,6 +48,6 @@
<rescap:Capability Name="broadFileSystemAccess" />
<rescap:Capability Name="expandedResources" />
<Capability Name="internetClientServer"/>
<Capability Name="privateNetworkClientServer"/> <!-- For features like remote disk streaming -->
<Capability Name="privateNetworkClientServer"/><!-- For features like remote disc streaming -->
</Capabilities>
</Package>

View file

@ -52,6 +52,6 @@
<rescap:Capability Name="broadFileSystemAccess" />
<rescap:Capability Name="expandedResources" />
<Capability Name="internetClientServer"/>
<Capability Name="privateNetworkClientServer"/> <!-- For features like remote disk streaming -->
<Capability Name="privateNetworkClientServer"/><!-- For features like remote disc streaming -->
</Capabilities>
</Package>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
<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" />
@ -48,6 +48,6 @@
<rescap:Capability Name="broadFileSystemAccess" />
<rescap:Capability Name="expandedResources" />
<Capability Name="internetClientServer"/>
<Capability Name="privateNetworkClientServer"/> <!-- For features like remote disk streaming -->
<Capability Name="privateNetworkClientServer"/><!-- For features like remote disc streaming -->
</Capabilities>
</Package>

View file

@ -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>

View file

@ -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>

View file

@ -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();

View file

@ -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;
}

View file

@ -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);

View file

@ -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) {
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 {
auto token = item.Token;
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)
{
try {
if (corewindow) {
corewindow->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
if (storageItem != nullptr) {
AppendToAccessList(storageItem->Path);
}
else {
corewindow = CoreWindow::GetForCurrentThread();
AccessCache::StorageApplicationPermissions::FutureAccessList->Remove(token);
}
}
catch (...) {
}
}
return;
}
fillListsCalled = true;
fillListInProgress = true;
// Clean access list from any deleted/moved items
for each (auto listItem in AccessCache::StorageApplicationPermissions::FutureAccessList->Entries) {
try {
IStorageItem^ test;
ExecuteTask(test, AccessCache::StorageApplicationPermissions::FutureAccessList->GetItemAsync(listItem.Token));
if (test == nullptr) {
// Access denied or file moved/deleted
AccessCache::StorageApplicationPermissions::FutureAccessList->Remove(listItem.Token);
}
}
catch (Platform::COMException^ e) {
// 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;
AppendToAccessList(ApplicationData::Current->LocalFolder->Path);
AppendToAccessList(ApplicationData::Current->TemporaryFolder->Path);
}
return alist;
}

View file

@ -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();

View file

@ -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)
{
try {
return TaskHandler<bool>([&]() {
return concurrency::create_task(action).then([]() {
return true;
});
}, false);
}
catch (...) {
return false;
}
}
// Async action such as 'Delete' file

View 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;
@ -42,7 +37,7 @@ T TaskHandler(std::function<concurrency::task<T>()> wtask, T def)
}
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)
{
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)
{
try{
out = TaskPass<T>(task, def);
}
catch (...) {
out = def;
}
};

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}
};

View file

@ -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;
}
};

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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;
};

View file

@ -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;
};

View file

@ -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)

View file

@ -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;
}
// 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());
}
; }
// 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;
}
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());
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);
// 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());
// 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;
}
}
if (!alreadyAdded) {
subRoot.push_back(sub);
}
}
}
else
{
// Check if this folder is root for accessible item
// then add fake folder as sub root to avoid empty results
}
return !subRoot.empty();
}
bool IsRootForAccessibleItems(std::string path)
{
std::list<std::string> tmp;
return IsRootForAccessibleItems(Path(path), tmp, true);
}
bool GetFakeFolders(Path path, std::vector<File::FileInfo>* files, const char* filter, std::set<std::string> filters) {
bool state = false;
std::list<std::string> subRoot;
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));
}
}
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 {
VERBOSE_LOG(FILESYS, "Cannot get any content!.. (%s)", path.c_str());
info.access = 0666; // Read/Write
}
if (attributes & FILE_ATTRIBUTE_DIRECTORY) {
info.access |= 0111; // Execute
}
if (!info.isDirectory) {
std::string ext = info.fullName.GetFileExtension();
if (!ext.empty()) {
ext = ext.substr(1); // Remove the dot.
if (filter && filters.find(ext) == filters.end()) {
continue;
}
}
}
return contents;
}
std::list<ItemInfoUWP> GetFolderContents(std::wstring path, bool deepScan) {
return GetFolderContents(convert(path), deepScan);
files->push_back(info);
state = true;
}
}
}
return state;
}
ItemInfoUWP GetItemInfoUWP(std::string path) {
ItemInfoUWP info;
info.size = -1;
info.attributes = INVALID_FILE_ATTRIBUTES;
if (IsValidUWP(path)) {
auto storageItem = GetStorageItem(path);
if (storageItem.IsValid()) {
info = storageItem.GetItemInfo();
}
else {
ERROR_LOG(FILESYS, "Couldn't find or access (%s)", path.c_str());
}
}
return info;
}
#pragma endregion
#pragma 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

View file

@ -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();

View file

@ -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;
}
}

View file

@ -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_;
};

View file

@ -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);
});
}

View file

@ -3,10 +3,6 @@
// Email: bashar@astifan.online
// Telegram: @basharastifan
// Functions:
// ChooseFolder()
// ChooseFile(std::vector<std::string> exts)
#pragma once
#include <ppl.h>

View file

@ -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

View file

@ -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

View file

@ -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