Common: Add UWP support for helper classes

This commit is contained in:
Connor McLaughlin 2021-07-04 19:09:11 +10:00
parent 281f7c5789
commit 03ab18909a
13 changed files with 317 additions and 41 deletions

View file

@ -20,10 +20,12 @@
#endif #endif
// require vista+ // require vista+
#ifndef WINAPI_FAMILY
#ifdef _WIN32_WINNT #ifdef _WIN32_WINNT
#undef _WIN32_WINNT #undef _WIN32_WINNT
#endif #endif
#define _WIN32_WINNT _WIN32_WINNT_VISTA #define _WIN32_WINNT _WIN32_WINNT_VISTA
#endif
#include <windows.h> #include <windows.h>

View file

@ -3,7 +3,7 @@
#include <cstdlib> #include <cstdlib>
#include <mutex> #include <mutex>
#ifdef _WIN32 #if defined(_WIN32) && !defined(_UWP)
#include "windows_headers.h" #include "windows_headers.h"
#include <intrin.h> #include <intrin.h>
#include <tlhelp32.h> #include <tlhelp32.h>
@ -13,7 +13,7 @@ static std::mutex s_AssertFailedMutex;
static inline void FreezeThreads(void** ppHandle) static inline void FreezeThreads(void** ppHandle)
{ {
#ifdef _WIN32 #if defined(_WIN32) && !defined(_UWP)
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hSnapshot != INVALID_HANDLE_VALUE) if (hSnapshot != INVALID_HANDLE_VALUE)
{ {
@ -43,7 +43,7 @@ static inline void FreezeThreads(void** ppHandle)
static inline void ResumeThreads(void* pHandle) static inline void ResumeThreads(void* pHandle)
{ {
#ifdef _WIN32 #if defined(_WIN32) && !defined(_UWP)
HANDLE hSnapshot = (HANDLE)pHandle; HANDLE hSnapshot = (HANDLE)pHandle;
if (pHandle != INVALID_HANDLE_VALUE) if (pHandle != INVALID_HANDLE_VALUE)
{ {
@ -79,7 +79,7 @@ void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char*
char szMsg[512]; char szMsg[512];
std::snprintf(szMsg, sizeof(szMsg), "%s in function %s (%s:%u)", szMessage, szFunction, szFile, uLine); std::snprintf(szMsg, sizeof(szMsg), "%s in function %s (%s:%u)", szMessage, szFunction, szFile, uLine);
#ifdef _WIN32 #if defined(_WIN32) && !defined(_UWP)
SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), szMsg, static_cast<DWORD>(std::strlen(szMsg)), NULL, NULL); WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), szMsg, static_cast<DWORD>(std::strlen(szMsg)), NULL, NULL);
OutputDebugStringA(szMsg); OutputDebugStringA(szMsg);
@ -114,7 +114,7 @@ void Y_OnPanicReached(const char* szMessage, const char* szFunction, const char*
char szMsg[512]; char szMsg[512];
std::snprintf(szMsg, sizeof(szMsg), "%s in function %s (%s:%u)", szMessage, szFunction, szFile, uLine); std::snprintf(szMsg, sizeof(szMsg), "%s in function %s (%s:%u)", szMessage, szFunction, szFile, uLine);
#ifdef _WIN32 #if defined(_WIN32) && !defined(_UWP)
SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), szMsg, static_cast<DWORD>(std::strlen(szMsg)), NULL, NULL); WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), szMsg, static_cast<DWORD>(std::strlen(szMsg)), NULL, NULL);
OutputDebugStringA(szMsg); OutputDebugStringA(szMsg);

View file

@ -884,7 +884,7 @@ std::unique_ptr<ByteStream> ByteStream_OpenFileStream(const char* fileName, u32
if ((openMode & (BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_WRITE)) == BYTESTREAM_OPEN_WRITE) if ((openMode & (BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_WRITE)) == BYTESTREAM_OPEN_WRITE)
{ {
// if opening with write but not create, the path must exist. // if opening with write but not create, the path must exist.
if (GetFileAttributes(fileName) == INVALID_FILE_ATTRIBUTES) if (!FileSystem::FileExists(fileName))
return nullptr; return nullptr;
} }
@ -895,7 +895,7 @@ std::unique_ptr<ByteStream> ByteStream_OpenFileStream(const char* fileName, u32
{ {
// if the file exists, use r+, otherwise w+ // if the file exists, use r+, otherwise w+
// HACK: if we're not truncating, and the file exists (we want to only update it), we still have to use r+ // HACK: if we're not truncating, and the file exists (we want to only update it), we still have to use r+
if ((openMode & BYTESTREAM_OPEN_TRUNCATE) || GetFileAttributes(fileName) == INVALID_FILE_ATTRIBUTES) if (!FileSystem::FileExists(fileName))
{ {
modeString[modeStringLength++] = 'w'; modeString[modeStringLength++] = 'w';
if (openMode & BYTESTREAM_OPEN_READ) if (openMode & BYTESTREAM_OPEN_READ)
@ -1013,8 +1013,15 @@ std::unique_ptr<ByteStream> ByteStream_OpenFileStream(const char* fileName, u32
DWORD desiredAccess = GENERIC_WRITE; DWORD desiredAccess = GENERIC_WRITE;
if (openMode & BYTESTREAM_OPEN_READ) if (openMode & BYTESTREAM_OPEN_READ)
desiredAccess |= GENERIC_READ; desiredAccess |= GENERIC_READ;
#ifndef _UWP
HANDLE hFile = HANDLE hFile =
CreateFileW(wideTemporaryFileName.c_str(), desiredAccess, FILE_SHARE_DELETE, NULL, CREATE_NEW, 0, NULL); CreateFileW(wideTemporaryFileName.c_str(), desiredAccess, FILE_SHARE_DELETE, NULL, CREATE_NEW, 0, NULL);
#else
HANDLE hFile =
CreateFile2FromAppW(wideTemporaryFileName.c_str(), desiredAccess, FILE_SHARE_DELETE, CREATE_NEW, nullptr);
#endif
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
return nullptr; return nullptr;
@ -1175,8 +1182,8 @@ std::unique_ptr<ByteStream> ByteStream_OpenFileStream(const char* fileName, u32
} }
else // if (errno == ENOTDIR) else // if (errno == ENOTDIR)
{ {
// well.. someone's trying to open a fucking weird path that is comprised of both directories and files... // well.. someone's trying to open a fucking weird path that is comprised of both directories and
// I aint sticking around here to find out what disaster awaits... let fopen deal with it // files... I aint sticking around here to find out what disaster awaits... let fopen deal with it
break; break;
} }
} }

View file

@ -4,7 +4,7 @@
#include <cinttypes> #include <cinttypes>
#include <cstdio> #include <cstdio>
#ifdef _WIN32 #if defined(_WIN32) && !defined(_UWP)
#include "windows_headers.h" #include "windows_headers.h"
#include "thirdparty/StackWalker.h" #include "thirdparty/StackWalker.h"

View file

@ -21,6 +21,20 @@
#if defined(_WIN32) #if defined(_WIN32)
#include <shlobj.h> #include <shlobj.h>
#if defined(_UWP)
#include <fcntl.h>
#include <io.h>
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.Devices.Enumeration.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Storage.FileProperties.h>
#include <winrt/Windows.Storage.Search.h>
#include <winrt/Windows.Storage.h>
#endif
#else #else
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
@ -713,7 +727,7 @@ std::vector<std::string> GetRootDirectoryList()
{ {
std::vector<std::string> results; std::vector<std::string> results;
#ifdef _WIN32 #if defined(_WIN32) && !defined(_UWP)
char buf[256]; char buf[256];
if (GetLogicalDriveStringsA(sizeof(buf), buf) != 0) if (GetLogicalDriveStringsA(sizeof(buf), buf) != 0)
{ {
@ -725,6 +739,28 @@ std::vector<std::string> GetRootDirectoryList()
ptr += len + 1u; ptr += len + 1u;
} }
} }
#elif defined(_UWP)
if (const auto install_location = winrt::Windows::ApplicationModel::Package::Current().InstalledLocation();
install_location)
{
if (const auto path = install_location.Path(); !path.empty())
results.push_back(StringUtil::WideStringToUTF8String(path));
}
if (const auto local_location = winrt::Windows::Storage::ApplicationData::Current().LocalFolder(); local_location)
{
if (const auto path = local_location.Path(); !path.empty())
results.push_back(StringUtil::WideStringToUTF8String(path));
}
const auto devices = winrt::Windows::Storage::KnownFolders::RemovableDevices();
const auto folders_task(devices.GetFoldersAsync());
for (const auto& storage_folder : folders_task.get())
{
const auto path = storage_folder.Path();
if (!path.empty())
results.push_back(StringUtil::WideStringToUTF8String(path));
}
#else #else
const char* home_path = std::getenv("HOME"); const char* home_path = std::getenv("HOME");
if (home_path) if (home_path)
@ -772,6 +808,106 @@ FileSystem::ManagedCFilePtr OpenManagedCFile(const char* filename, const char* m
return ManagedCFilePtr(OpenCFile(filename, mode), [](std::FILE* fp) { std::fclose(fp); }); return ManagedCFilePtr(OpenCFile(filename, mode), [](std::FILE* fp) { std::fclose(fp); });
} }
#ifdef _UWP
std::FILE* OpenCFileUWP(const wchar_t* wfilename, const wchar_t* mode)
{
DWORD access = 0;
DWORD share = 0;
DWORD disposition = 0;
int flags = 0;
const wchar_t* tmode = mode;
while (*tmode)
{
if (*tmode == L'r' && *(tmode + 1) == L'+')
{
access = GENERIC_READ | GENERIC_WRITE;
share = 0;
disposition = OPEN_EXISTING;
flags |= _O_RDWR;
tmode += 2;
}
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;
}
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;
}
else if (*tmode == L'r')
{
access = GENERIC_READ;
share = 0;
disposition = OPEN_EXISTING;
flags |= _O_RDONLY;
tmode++;
}
else if (*tmode == L'w')
{
access = GENERIC_WRITE;
share = 0;
disposition = CREATE_ALWAYS;
flags |= _O_WRONLY | _O_CREAT | _O_TRUNC;
tmode++;
}
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++;
}
else if (*tmode == L'b')
{
flags |= _O_BINARY;
tmode++;
}
else
{
Log_ErrorPrintf("Unknown mode flags: '%s'", StringUtil::WideStringToUTF8String(mode).c_str());
return nullptr;
}
}
HANDLE hFile = CreateFileFromAppW(wfilename, access, share, nullptr, disposition, 0, nullptr);
if (hFile == INVALID_HANDLE_VALUE)
return nullptr;
if (flags & _O_APPEND && !SetFilePointerEx(hFile, LARGE_INTEGER{}, nullptr, FILE_END))
{
Log_ErrorPrintf("SetFilePointerEx() failed: %08X", GetLastError());
CloseHandle(hFile);
return nullptr;
}
int fd = _open_osfhandle(reinterpret_cast<intptr_t>(hFile), flags);
if (fd < 0)
{
CloseHandle(hFile);
return nullptr;
}
std::FILE* fp = _wfdopen(fd, mode);
if (!fp)
{
_close(fd);
return nullptr;
}
return fp;
}
#endif // _UWP
std::FILE* OpenCFile(const char* filename, const char* mode) std::FILE* OpenCFile(const char* filename, const char* mode)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -789,9 +925,16 @@ std::FILE* OpenCFile(const char* filename, const char* mode)
{ {
wfilename[wlen] = 0; wfilename[wlen] = 0;
wmode[wmodelen] = 0; wmode[wmodelen] = 0;
std::FILE* fp; std::FILE* fp;
if (_wfopen_s(&fp, wfilename, wmode) != 0) if (_wfopen_s(&fp, wfilename, wmode) != 0)
{
#ifdef _UWP
return OpenCFileUWP(wfilename, wmode);
#else
return nullptr; return nullptr;
#endif
}
return fp; return fp;
} }
@ -1052,6 +1195,19 @@ static u32 TranslateWin32Attributes(u32 Win32Attributes)
return r; return r;
} }
static DWORD WrapGetFileAttributes(const wchar_t* path)
{
#ifndef _UWP
return GetFileAttributesW(path);
#else
WIN32_FILE_ATTRIBUTE_DATA fad;
if (!GetFileAttributesExFromAppW(path, GetFileExInfoStandard, &fad))
return INVALID_FILE_ATTRIBUTES;
return fad.dwFileAttributes;
#endif
}
static const u32 READ_DIRECTORY_CHANGES_NOTIFY_FILTER = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | static const u32 READ_DIRECTORY_CHANGES_NOTIFY_FILTER = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE |
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION; FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION;
@ -1064,7 +1220,7 @@ public:
m_directoryChangeQueued(false) m_directoryChangeQueued(false)
{ {
m_bufferSize = 16384; m_bufferSize = 16384;
m_pBuffer = new byte[m_bufferSize]; m_pBuffer = new u8[m_bufferSize];
} }
virtual ~ChangeNotifierWin32() virtual ~ChangeNotifierWin32()
@ -1103,7 +1259,7 @@ public:
// has any bytes? // has any bytes?
if (bytesRead > 0) if (bytesRead > 0)
{ {
const byte* pCurrentPointer = m_pBuffer; const u8* pCurrentPointer = m_pBuffer;
PathString fileName; PathString fileName;
for (;;) for (;;)
{ {
@ -1176,15 +1332,26 @@ private:
HANDLE m_hDirectory; HANDLE m_hDirectory;
OVERLAPPED m_overlapped; OVERLAPPED m_overlapped;
bool m_directoryChangeQueued; bool m_directoryChangeQueued;
byte* m_pBuffer; u8* m_pBuffer;
u32 m_bufferSize; u32 m_bufferSize;
}; };
std::unique_ptr<ChangeNotifier> CreateChangeNotifier(const char* path, bool recursiveWatch) std::unique_ptr<ChangeNotifier> CreateChangeNotifier(const char* path, bool recursiveWatch)
{ {
// open the directory up // open the directory up
HANDLE hDirectory = CreateFileA(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, std::wstring path_wstr(StringUtil::UTF8StringToWideString(path));
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr); #ifndef _UWP
HANDLE hDirectory =
CreateFileW(path_wstr.c_str(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr);
#else
CREATEFILE2_EXTENDED_PARAMETERS ep = {};
ep.dwSize = sizeof(ep);
ep.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
ep.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
HANDLE hDirectory = CreateFile2FromAppW(path_wstr.c_str(), FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, OPEN_EXISTING, &ep);
#endif
if (hDirectory == nullptr) if (hDirectory == nullptr)
return nullptr; return nullptr;
@ -1212,8 +1379,18 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co
tempStr = StringUtil::StdStringFromFormat("%s\\*", OriginPath); tempStr = StringUtil::StdStringFromFormat("%s\\*", OriginPath);
} }
// holder for utf-8 conversion
WIN32_FIND_DATAW wfd; WIN32_FIND_DATAW wfd;
std::string utf8_filename;
utf8_filename.reserve(countof(wfd.cFileName) * 2);
#ifndef _UWP
HANDLE hFind = FindFirstFileW(StringUtil::UTF8StringToWideString(tempStr).c_str(), &wfd); HANDLE hFind = FindFirstFileW(StringUtil::UTF8StringToWideString(tempStr).c_str(), &wfd);
#else
HANDLE hFind = FindFirstFileExFromAppW(StringUtil::UTF8StringToWideString(tempStr).c_str(), FindExInfoBasic, &wfd,
FindExSearchNameMatch, nullptr, 0);
#endif
if (hFind == INVALID_HANDLE_VALUE) if (hFind == INVALID_HANDLE_VALUE)
return 0; return 0;
@ -1227,10 +1404,6 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co
wildCardMatchAll = !(std::strcmp(Pattern, "*")); wildCardMatchAll = !(std::strcmp(Pattern, "*"));
} }
// holder for utf-8 conversion
std::string utf8_filename;
utf8_filename.reserve(countof(wfd.cFileName) * 2);
// iterate results // iterate results
do do
{ {
@ -1360,6 +1533,7 @@ bool FileSystem::StatFile(const char* path, FILESYSTEM_STAT_DATA* pStatData)
wpath[wlen] = 0; wpath[wlen] = 0;
#ifndef _UWP
// determine attributes for the path. if it's a directory, things have to be handled differently.. // determine attributes for the path. if it's a directory, things have to be handled differently..
DWORD fileAttributes = GetFileAttributesW(wpath); DWORD fileAttributes = GetFileAttributesW(wpath);
if (fileAttributes == INVALID_FILE_ATTRIBUTES) if (fileAttributes == INVALID_FILE_ATTRIBUTES)
@ -1398,6 +1572,16 @@ bool FileSystem::StatFile(const char* path, FILESYSTEM_STAT_DATA* pStatData)
pStatData->ModificationTime.SetWindowsFileTime(&bhfi.ftLastWriteTime); pStatData->ModificationTime.SetWindowsFileTime(&bhfi.ftLastWriteTime);
pStatData->Size = ((u64)bhfi.nFileSizeHigh) << 32 | (u64)bhfi.nFileSizeLow; pStatData->Size = ((u64)bhfi.nFileSizeHigh) << 32 | (u64)bhfi.nFileSizeLow;
return true; return true;
#else
WIN32_FILE_ATTRIBUTE_DATA fad;
if (!GetFileAttributesExFromAppW(wpath, GetFileExInfoStandard, &fad))
return false;
pStatData->Attributes = TranslateWin32Attributes(fad.dwFileAttributes);
pStatData->ModificationTime.SetWindowsFileTime(&fad.ftLastWriteTime);
pStatData->Size = ((u64)fad.nFileSizeHigh) << 32 | (u64)fad.nFileSizeLow;
return true;
#endif
} }
bool FileSystem::StatFile(std::FILE* fp, FILESYSTEM_STAT_DATA* pStatData) bool FileSystem::StatFile(std::FILE* fp, FILESYSTEM_STAT_DATA* pStatData)
@ -1447,7 +1631,7 @@ bool FileSystem::FileExists(const char* path)
wpath[wlen] = 0; wpath[wlen] = 0;
// determine attributes for the path. if it's a directory, things have to be handled differently.. // determine attributes for the path. if it's a directory, things have to be handled differently..
DWORD fileAttributes = GetFileAttributesW(wpath); DWORD fileAttributes = WrapGetFileAttributes(wpath);
if (fileAttributes == INVALID_FILE_ATTRIBUTES) if (fileAttributes == INVALID_FILE_ATTRIBUTES)
return false; return false;
@ -1477,7 +1661,7 @@ bool FileSystem::DirectoryExists(const char* path)
wpath[wlen] = 0; wpath[wlen] = 0;
// determine attributes for the path. if it's a directory, things have to be handled differently.. // determine attributes for the path. if it's a directory, things have to be handled differently..
DWORD fileAttributes = GetFileAttributesW(wpath); DWORD fileAttributes = WrapGetFileAttributes(wpath);
if (fileAttributes == INVALID_FILE_ATTRIBUTES) if (fileAttributes == INVALID_FILE_ATTRIBUTES)
return false; return false;
@ -1496,15 +1680,20 @@ bool FileSystem::CreateDirectory(const char* Path, bool Recursive)
return false; return false;
// try just flat-out, might work if there's no other segments that have to be made // try just flat-out, might work if there's no other segments that have to be made
#ifndef _UWP
if (CreateDirectoryW(wpath.c_str(), nullptr)) if (CreateDirectoryW(wpath.c_str(), nullptr))
return true; return true;
#else
if (CreateDirectoryFromAppW(wpath.c_str(), nullptr))
return true;
#endif
// check error // check error
DWORD lastError = GetLastError(); DWORD lastError = GetLastError();
if (lastError == ERROR_ALREADY_EXISTS) if (lastError == ERROR_ALREADY_EXISTS)
{ {
// check the attributes // check the attributes
u32 Attributes = GetFileAttributesW(wpath.c_str()); u32 Attributes = WrapGetFileAttributes(wpath.c_str());
if (Attributes != INVALID_FILE_ATTRIBUTES && Attributes & FILE_ATTRIBUTE_DIRECTORY) if (Attributes != INVALID_FILE_ATTRIBUTES && Attributes & FILE_ATTRIBUTE_DIRECTORY)
return true; return true;
else else
@ -1523,7 +1712,13 @@ bool FileSystem::CreateDirectory(const char* Path, bool Recursive)
if (wpath[i] == L'\\' || wpath[i] == L'/') if (wpath[i] == L'\\' || wpath[i] == L'/')
{ {
tempStr[i] = L'\0'; tempStr[i] = L'\0';
if (!CreateDirectoryW(tempStr, nullptr))
#ifndef _UWP
const BOOL result = CreateDirectoryW(tempStr, nullptr);
#else
const BOOL result = CreateDirectoryFromAppW(tempStr, nullptr);
#endif
if (!result)
{ {
lastError = GetLastError(); lastError = GetLastError();
if (lastError != ERROR_ALREADY_EXISTS) // fine, continue to next path segment if (lastError != ERROR_ALREADY_EXISTS) // fine, continue to next path segment
@ -1537,7 +1732,12 @@ bool FileSystem::CreateDirectory(const char* Path, bool Recursive)
// re-create the end if it's not a separator, check / as well because windows can interpret them // re-create the end if it's not a separator, check / as well because windows can interpret them
if (wpath[pathLength - 1] != L'\\' && wpath[pathLength - 1] != L'/') if (wpath[pathLength - 1] != L'\\' && wpath[pathLength - 1] != L'/')
{ {
if (!CreateDirectoryW(wpath.c_str(), nullptr)) #ifndef _UWP
const BOOL result = CreateDirectoryW(wpath.c_str(), nullptr);
#else
const BOOL result = CreateDirectoryFromAppW(wpath.c_str(), nullptr);
#endif
if (!result)
{ {
lastError = GetLastError(); lastError = GetLastError();
if (lastError != ERROR_ALREADY_EXISTS) if (lastError != ERROR_ALREADY_EXISTS)
@ -1561,14 +1761,15 @@ bool FileSystem::DeleteFile(const char* Path)
return false; return false;
const std::wstring wpath(StringUtil::UTF8StringToWideString(Path)); const std::wstring wpath(StringUtil::UTF8StringToWideString(Path));
DWORD fileAttributes = GetFileAttributesW(wpath.c_str()); const DWORD fileAttributes = WrapGetFileAttributes(wpath.c_str());
if (fileAttributes == INVALID_FILE_ATTRIBUTES) if (fileAttributes == INVALID_FILE_ATTRIBUTES || fileAttributes & FILE_ATTRIBUTE_DIRECTORY)
return false; return false;
if (!(fileAttributes & FILE_ATTRIBUTE_DIRECTORY)) #ifndef _UWP
return (DeleteFileW(wpath.c_str()) == TRUE); return (DeleteFileW(wpath.c_str()) == TRUE);
else #else
return false; return (DeleteFileFromAppW(wpath.c_str()) == TRUE);
#endif
} }
bool FileSystem::RenamePath(const char* OldPath, const char* NewPath) bool FileSystem::RenamePath(const char* OldPath, const char* NewPath)
@ -1576,11 +1777,19 @@ bool FileSystem::RenamePath(const char* OldPath, const char* NewPath)
const std::wstring old_wpath(StringUtil::UTF8StringToWideString(OldPath)); const std::wstring old_wpath(StringUtil::UTF8StringToWideString(OldPath));
const std::wstring new_wpath(StringUtil::UTF8StringToWideString(NewPath)); const std::wstring new_wpath(StringUtil::UTF8StringToWideString(NewPath));
#ifndef _UWP
if (!MoveFileExW(old_wpath.c_str(), new_wpath.c_str(), MOVEFILE_REPLACE_EXISTING)) if (!MoveFileExW(old_wpath.c_str(), new_wpath.c_str(), MOVEFILE_REPLACE_EXISTING))
{ {
Log_ErrorPrintf("MoveFileEx('%s', '%s') failed: %08X", OldPath, NewPath, GetLastError()); Log_ErrorPrintf("MoveFileEx('%s', '%s') failed: %08X", OldPath, NewPath, GetLastError());
return false; return false;
} }
#else
if (!ReplaceFileFromAppW(old_wpath.c_str(), new_wpath.c_str(), nullptr, 0, nullptr, nullptr))
{
Log_ErrorPrintf("MoveFileFromAppW('%s', '%s') failed: %08X", OldPath, NewPath, GetLastError());
return false;
}
#endif
return true; return true;
} }
@ -1588,13 +1797,19 @@ bool FileSystem::RenamePath(const char* OldPath, const char* NewPath)
static bool RecursiveDeleteDirectory(const std::wstring& wpath, bool Recursive) static bool RecursiveDeleteDirectory(const std::wstring& wpath, bool Recursive)
{ {
// ensure it exists // ensure it exists
DWORD fileAttributes = GetFileAttributesW(wpath.c_str()); const DWORD fileAttributes = WrapGetFileAttributes(wpath.c_str());
if (fileAttributes == INVALID_FILE_ATTRIBUTES || !(fileAttributes & FILE_ATTRIBUTE_DIRECTORY)) if (fileAttributes == INVALID_FILE_ATTRIBUTES || fileAttributes & FILE_ATTRIBUTE_DIRECTORY)
return false; return false;
// non-recursive case just try removing the directory // non-recursive case just try removing the directory
if (!Recursive) if (!Recursive)
{
#ifndef _UWP
return (RemoveDirectoryW(wpath.c_str()) == TRUE); return (RemoveDirectoryW(wpath.c_str()) == TRUE);
#else
return (RemoveDirectoryFromAppW(wpath.c_str()) == TRUE);
#endif
}
// doing a recursive delete // doing a recursive delete
std::wstring fileName = wpath; std::wstring fileName = wpath;
@ -1602,7 +1817,12 @@ static bool RecursiveDeleteDirectory(const std::wstring& wpath, bool Recursive)
// is there any files? // is there any files?
WIN32_FIND_DATAW findData; WIN32_FIND_DATAW findData;
#ifndef _UWP
HANDLE hFind = FindFirstFileW(fileName.c_str(), &findData); HANDLE hFind = FindFirstFileW(fileName.c_str(), &findData);
#else
HANDLE hFind =
FindFirstFileExFromAppW(fileName.c_str(), FindExInfoBasic, &findData, FindExSearchNameMatch, nullptr, 0);
#endif
if (hFind == INVALID_HANDLE_VALUE) if (hFind == INVALID_HANDLE_VALUE)
return false; return false;
@ -1634,7 +1854,12 @@ static bool RecursiveDeleteDirectory(const std::wstring& wpath, bool Recursive)
else else
{ {
// found a file, so delete it // found a file, so delete it
if (!DeleteFileW(fileName.c_str())) #ifndef _UWP
const BOOL result = DeleteFileW(fileName.c_str());
#else
const BOOL result = DeleteFileFromAppW(fileName.c_str());
#endif
if (!result)
{ {
FindClose(hFind); FindClose(hFind);
return false; return false;
@ -1644,7 +1869,12 @@ static bool RecursiveDeleteDirectory(const std::wstring& wpath, bool Recursive)
FindClose(hFind); FindClose(hFind);
// nuke the directory itself // nuke the directory itself
if (!RemoveDirectoryW(wpath.c_str())) #ifndef _UWP
const BOOL result = RemoveDirectoryW(wpath.c_str());
#else
const BOOL result = RemoveDirectoryFromAppW(wpath.c_str());
#endif
if (!result)
return false; return false;
// done // done
@ -1664,8 +1894,10 @@ std::string GetProgramPath()
// Fall back to the main module if this fails. // Fall back to the main module if this fails.
HMODULE module = nullptr; HMODULE module = nullptr;
#ifndef _UWP
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCWSTR>(&GetProgramPath), &module); reinterpret_cast<LPCWSTR>(&GetProgramPath), &module);
#endif
for (;;) for (;;)
{ {

View file

@ -44,7 +44,21 @@ bool JitCodeBuffer::Allocate(u32 size /* = 64 * 1024 * 1024 */, u32 far_code_siz
m_total_size = size + far_code_size; m_total_size = size + far_code_size;
#if defined(_WIN32) #if defined(_WIN32)
#if !defined(_UWP)
m_code_ptr = static_cast<u8*>(VirtualAlloc(nullptr, m_total_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE)); m_code_ptr = static_cast<u8*>(VirtualAlloc(nullptr, m_total_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE));
#else
m_code_ptr = static_cast<u8*>(
VirtualAlloc2FromApp(GetCurrentProcess(), nullptr, m_total_size, MEM_COMMIT, PAGE_READWRITE, nullptr, 0));
if (m_code_ptr)
{
ULONG old_protection;
if (!VirtualProtectFromApp(m_code_ptr, m_total_size, PAGE_EXECUTE_READWRITE, &old_protection))
{
VirtualFree(m_code_ptr, m_total_size, MEM_RELEASE);
return false;
}
}
#endif
if (!m_code_ptr) if (!m_code_ptr)
{ {
Log_ErrorPrintf("VirtualAlloc(RWX, %u) for internal buffer failed: %u", m_total_size, GetLastError()); Log_ErrorPrintf("VirtualAlloc(RWX, %u) for internal buffer failed: %u", m_total_size, GetLastError());

View file

@ -9,6 +9,8 @@ public:
JitCodeBuffer(void* buffer, u32 size, u32 far_code_size, u32 guard_size); JitCodeBuffer(void* buffer, u32 size, u32 far_code_size, u32 guard_size);
~JitCodeBuffer(); ~JitCodeBuffer();
bool IsValid() const { return (m_code_ptr != nullptr); }
bool Allocate(u32 size = 64 * 1024 * 1024, u32 far_code_size = 0); bool Allocate(u32 size = 64 * 1024 * 1024, u32 far_code_size = 0);
bool Initialize(void* buffer, u32 size, u32 far_code_size = 0, u32 guard_size = 0); bool Initialize(void* buffer, u32 size, u32 far_code_size = 0, u32 guard_size = 0);
void Destroy(); void Destroy();

View file

@ -135,8 +135,13 @@ bool MemoryArena::Create(size_t size, bool writable, bool executable)
#if defined(_WIN32) #if defined(_WIN32)
const DWORD protect = (writable ? (executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE) : PAGE_READONLY); const DWORD protect = (writable ? (executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE) : PAGE_READONLY);
#ifndef _UWP
m_file_handle = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, protect, Truncate32(size >> 32), Truncate32(size), m_file_handle = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, protect, Truncate32(size >> 32), Truncate32(size),
file_mapping_name.c_str()); file_mapping_name.c_str());
#else
m_file_handle = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, nullptr, protect, size,
StringUtil::UTF8StringToWideString(file_mapping_name).c_str());
#endif
if (!m_file_handle) if (!m_file_handle)
{ {
Log_ErrorPrintf("CreateFileMapping failed: %u", GetLastError()); Log_ErrorPrintf("CreateFileMapping failed: %u", GetLastError());
@ -257,8 +262,16 @@ void* MemoryArena::CreateViewPtr(size_t offset, size_t size, bool writable, bool
void* base_pointer; void* base_pointer;
#if defined(_WIN32) #if defined(_WIN32)
const DWORD desired_access = FILE_MAP_READ | (writable ? FILE_MAP_WRITE : 0) | (executable ? FILE_MAP_EXECUTE : 0); const DWORD desired_access = FILE_MAP_READ | (writable ? FILE_MAP_WRITE : 0) | (executable ? FILE_MAP_EXECUTE : 0);
#ifndef _UWP
base_pointer = base_pointer =
MapViewOfFileEx(m_file_handle, desired_access, Truncate32(offset >> 32), Truncate32(offset), size, fixed_address); MapViewOfFileEx(m_file_handle, desired_access, Truncate32(offset >> 32), Truncate32(offset), size, fixed_address);
#else
// UWP does not support fixed mappings.
if (!fixed_address)
base_pointer = MapViewOfFileFromApp(m_file_handle, desired_access, offset, size);
else
base_pointer = nullptr;
#endif
if (!base_pointer) if (!base_pointer)
return nullptr; return nullptr;
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)

View file

@ -78,7 +78,7 @@ static bool IsStoreInstruction(const void* ptr)
} }
#endif #endif
#if defined(_WIN32) && (defined(CPU_X64) || defined(CPU_AARCH64)) #if defined(_WIN32) && !defined(_UWP) && (defined(CPU_X64) || defined(CPU_AARCH64))
static PVOID s_veh_handle; static PVOID s_veh_handle;
static LONG ExceptionHandler(PEXCEPTION_POINTERS exi) static LONG ExceptionHandler(PEXCEPTION_POINTERS exi)
@ -110,6 +110,7 @@ static LONG ExceptionHandler(PEXCEPTION_POINTERS exi)
} }
s_in_handler = false; s_in_handler = false;
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
@ -222,7 +223,7 @@ bool InstallHandler(void* owner, Callback callback)
if (was_empty) if (was_empty)
{ {
#if defined(_WIN32) && (defined(CPU_X64) || defined(CPU_AARCH64)) #if defined(_WIN32) && !defined(_UWP) && (defined(CPU_X64) || defined(CPU_AARCH64))
s_veh_handle = AddVectoredExceptionHandler(1, ExceptionHandler); s_veh_handle = AddVectoredExceptionHandler(1, ExceptionHandler);
if (!s_veh_handle) if (!s_veh_handle)
{ {
@ -279,7 +280,7 @@ bool RemoveHandler(void* owner)
if (m_handlers.empty()) if (m_handlers.empty())
{ {
#if defined(_WIN32) && (defined(CPU_X64) || defined(CPU_AARCH64)) #if defined(_WIN32) && !defined(_UWP) && (defined(CPU_X64) || defined(CPU_AARCH64))
RemoveVectoredExceptionHandler(s_veh_handle); RemoveVectoredExceptionHandler(s_veh_handle);
s_veh_handle = nullptr; s_veh_handle = nullptr;
#elif defined(USE_SIGSEGV) #elif defined(USE_SIGSEGV)

View file

@ -93,6 +93,7 @@ void Timer::SleepUntil(Value value, bool exact)
if (diff <= 0) if (diff <= 0)
return; return;
#ifndef _UWP
HANDLE timer = GetSleepTimer(); HANDLE timer = GetSleepTimer();
if (timer) if (timer)
{ {
@ -110,6 +111,7 @@ void Timer::SleepUntil(Value value, bool exact)
return; return;
} }
} }
#endif
// falling back to sleep... bad. // falling back to sleep... bad.
Sleep(static_cast<DWORD>(static_cast<std::uint64_t>(diff) / 1000000)); Sleep(static_cast<DWORD>(static_cast<std::uint64_t>(diff) / 1000000));

View file

@ -2,7 +2,7 @@
#include "common/log.h" #include "common/log.h"
Log_SetChannel(WindowInfo); Log_SetChannel(WindowInfo);
#if defined(_WIN32) #if defined(_WIN32) && !defined(_UWP)
#include "common/windows_headers.h" #include "common/windows_headers.h"
#include <dwmapi.h> #include <dwmapi.h>

View file

@ -8,6 +8,7 @@ struct WindowInfo
{ {
Surfaceless, Surfaceless,
Win32, Win32,
WinRT,
X11, X11,
Wayland, Wayland,
MacOS, MacOS,

View file

@ -7,11 +7,13 @@
#define NOMINMAX 1 #define NOMINMAX 1
#endif #endif
// require vista+ // require vista+, but don't set it when compiling for UWP
#ifndef WINAPI_FAMILY
#ifdef _WIN32_WINNT #ifdef _WIN32_WINNT
#undef _WIN32_WINNT #undef _WIN32_WINNT
#endif #endif
#define _WIN32_WINNT _WIN32_WINNT_VISTA #define _WIN32_WINNT _WIN32_WINNT_VISTA
#endif
#include <windows.h> #include <windows.h>