FileSystem: Add OpenSharedCFile()

This commit is contained in:
Connor McLaughlin
2022-06-06 22:46:39 +10:00
committed by refractionpcsx2
parent 8c0120bdbb
commit afa29facc6
2 changed files with 81 additions and 10 deletions
+67 -10
View File
@@ -37,6 +37,7 @@
#if defined(_WIN32)
#include "RedtapeWindows.h"
#include <winioctl.h>
#include <share.h>
#include <shlobj.h>
#if defined(_UWP)
@@ -595,12 +596,29 @@ std::string Path::Combine(const std::string_view& base, const std::string_view&
}
#ifdef _UWP
static std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode)
static std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode, FileSystem::FileShareMode share_mode)
{
DWORD access = 0;
DWORD share = 0;
DWORD disposition = 0;
switch (share_mode)
{
case FileSystem::FileShareMode::DenyNone:
share = FILE_SHARE_READ | FILE_SHARE_WRITE;
break;
case FileSystem::FileShareMode::DenyRead:
share = FILE_SHARE_WRITE;
break;
case FileSystem::FileShareMode::DenyWrite:
share = FILE_SHARE_READ;
break;
case FileSystem::FileShareMode::DenyReadWrite:
default:
share = 0;
break;
}
int flags = 0;
const wchar_t* tmode = mode;
while (*tmode)
@@ -608,7 +626,6 @@ static std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode)
if (*tmode == L'r' && *(tmode + 1) == L'+')
{
access = GENERIC_READ | GENERIC_WRITE;
share = 0;
disposition = OPEN_EXISTING;
flags |= _O_RDWR;
tmode += 2;
@@ -616,7 +633,6 @@ static std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode)
else if (*tmode == L'w' && *(tmode + 1) == L'+')
{
access = GENERIC_READ | GENERIC_WRITE;
share = 0;
disposition = CREATE_ALWAYS;
flags |= _O_RDWR | _O_CREAT | _O_TRUNC;
tmode += 2;
@@ -624,7 +640,6 @@ static std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode)
else if (*tmode == L'a' && *(tmode + 1) == L'+')
{
access = GENERIC_READ | GENERIC_WRITE;
share = 0;
disposition = CREATE_ALWAYS;
flags |= _O_RDWR | _O_APPEND | _O_CREAT | _O_TRUNC;
tmode += 2;
@@ -632,7 +647,6 @@ static std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode)
else if (*tmode == L'r')
{
access = GENERIC_READ;
share = 0;
disposition = OPEN_EXISTING;
flags |= _O_RDONLY;
tmode++;
@@ -640,7 +654,6 @@ static std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode)
else if (*tmode == L'w')
{
access = GENERIC_WRITE;
share = 0;
disposition = CREATE_ALWAYS;
flags |= _O_WRONLY | _O_CREAT | _O_TRUNC;
tmode++;
@@ -648,7 +661,6 @@ static std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode)
else if (*tmode == L'a')
{
access = GENERIC_READ | GENERIC_WRITE;
share = 0;
disposition = CREATE_ALWAYS;
flags |= _O_WRONLY | _O_APPEND | _O_CREAT | _O_TRUNC;
tmode++;
@@ -670,7 +682,7 @@ static std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode)
}
else
{
Log_ErrorPrintf("Unknown mode flags: '%s'", StringUtil::WideStringToUTF8String(mode).c_str());
Console.Error("Unknown mode flags: '%s'", StringUtil::WideStringToUTF8String(mode).c_str());
return nullptr;
}
}
@@ -681,7 +693,7 @@ static std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode)
if (flags & _O_APPEND && !SetFilePointerEx(hFile, LARGE_INTEGER{}, nullptr, FILE_END))
{
Log_ErrorPrintf("SetFilePointerEx() failed: %08X", GetLastError());
Console.Error("SetFilePointerEx() failed: %08X", GetLastError());
CloseHandle(hFile);
return nullptr;
}
@@ -715,7 +727,7 @@ std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode)
if (_wfopen_s(&fp, wfilename.c_str(), wmode.c_str()) != 0)
{
#ifdef _UWP
return OpenCFileUWP(wfilename.c_str(), wmode.c_str());
return OpenCFileUWP(wfilename.c_str(), wmode.c_str(), FileShareMode::DenyReadWrite);
#else
return nullptr;
#endif
@@ -755,6 +767,51 @@ FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, c
return ManagedCFilePtr(OpenCFile(filename, mode), [](std::FILE* fp) { std::fclose(fp); });
}
std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode)
{
#ifdef _WIN32
const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename));
const std::wstring wmode(StringUtil::UTF8StringToWideString(mode));
if (wfilename.empty() || wmode.empty())
return nullptr;
int share_flags = 0;
switch (share_mode)
{
case FileShareMode::DenyNone:
share_flags = _SH_DENYNO;
break;
case FileShareMode::DenyRead:
share_flags = _SH_DENYRD;
break;
case FileShareMode::DenyWrite:
share_flags = _SH_DENYWR;
break;
case FileShareMode::DenyReadWrite:
default:
share_flags = _SH_DENYRW;
break;
}
std::FILE* fp = _wfsopen(wfilename.c_str(), wmode.c_str(), share_flags);
if (fp)
return fp;
#ifdef _UWP
return OpenCFileUWP(wfilename.c_str(), wmode.c_str(), share_mode);
#else
return nullptr;
#endif
#else
return std::fopen(filename, mode);
#endif
}
FileSystem::ManagedCFilePtr FileSystem::OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode)
{
return ManagedCFilePtr(OpenSharedCFile(filename, mode, share_mode), [](std::FILE* fp) { std::fclose(fp); });
}
int FileSystem::FSeek64(std::FILE* fp, s64 offset, int whence)
{
#ifdef _WIN32