mirror of
				https://github.com/RetroDECK/Duckstation.git
				synced 2025-04-10 19:15:14 +00:00 
			
		
		
		
	Common: Add UWP support for helper classes
This commit is contained in:
		
							parent
							
								
									281f7c5789
								
							
						
					
					
						commit
						03ab18909a
					
				|  | @ -20,10 +20,12 @@ | |||
| #endif | ||||
| 
 | ||||
| // require vista+
 | ||||
| #ifndef WINAPI_FAMILY | ||||
| #ifdef _WIN32_WINNT | ||||
| #undef _WIN32_WINNT | ||||
| #endif | ||||
| #define _WIN32_WINNT _WIN32_WINNT_VISTA | ||||
| #endif | ||||
| 
 | ||||
| #include <windows.h> | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| #include <cstdlib> | ||||
| #include <mutex> | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #if defined(_WIN32) && !defined(_UWP) | ||||
| #include "windows_headers.h" | ||||
| #include <intrin.h> | ||||
| #include <tlhelp32.h> | ||||
|  | @ -13,7 +13,7 @@ static std::mutex s_AssertFailedMutex; | |||
| 
 | ||||
| static inline void FreezeThreads(void** ppHandle) | ||||
| { | ||||
| #ifdef _WIN32 | ||||
| #if defined(_WIN32) && !defined(_UWP) | ||||
|   HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); | ||||
|   if (hSnapshot != INVALID_HANDLE_VALUE) | ||||
|   { | ||||
|  | @ -43,7 +43,7 @@ static inline void FreezeThreads(void** ppHandle) | |||
| 
 | ||||
| static inline void ResumeThreads(void* pHandle) | ||||
| { | ||||
| #ifdef _WIN32 | ||||
| #if defined(_WIN32) && !defined(_UWP) | ||||
|   HANDLE hSnapshot = (HANDLE)pHandle; | ||||
|   if (pHandle != INVALID_HANDLE_VALUE) | ||||
|   { | ||||
|  | @ -79,7 +79,7 @@ void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char* | |||
|   char szMsg[512]; | ||||
|   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); | ||||
|   WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), szMsg, static_cast<DWORD>(std::strlen(szMsg)), NULL, NULL); | ||||
|   OutputDebugStringA(szMsg); | ||||
|  | @ -114,7 +114,7 @@ void Y_OnPanicReached(const char* szMessage, const char* szFunction, const char* | |||
|   char szMsg[512]; | ||||
|   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); | ||||
|   WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), szMsg, static_cast<DWORD>(std::strlen(szMsg)), NULL, NULL); | ||||
|   OutputDebugStringA(szMsg); | ||||
|  |  | |||
|  | @ -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 opening with write but not create, the path must exist.
 | ||||
|     if (GetFileAttributes(fileName) == INVALID_FILE_ATTRIBUTES) | ||||
|     if (!FileSystem::FileExists(fileName)) | ||||
|       return nullptr; | ||||
|   } | ||||
| 
 | ||||
|  | @ -895,7 +895,7 @@ std::unique_ptr<ByteStream> ByteStream_OpenFileStream(const char* fileName, u32 | |||
|   { | ||||
|     // 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+
 | ||||
|     if ((openMode & BYTESTREAM_OPEN_TRUNCATE) || GetFileAttributes(fileName) == INVALID_FILE_ATTRIBUTES) | ||||
|     if (!FileSystem::FileExists(fileName)) | ||||
|     { | ||||
|       modeString[modeStringLength++] = 'w'; | ||||
|       if (openMode & BYTESTREAM_OPEN_READ) | ||||
|  | @ -1013,8 +1013,15 @@ std::unique_ptr<ByteStream> ByteStream_OpenFileStream(const char* fileName, u32 | |||
|     DWORD desiredAccess = GENERIC_WRITE; | ||||
|     if (openMode & BYTESTREAM_OPEN_READ) | ||||
|       desiredAccess |= GENERIC_READ; | ||||
| 
 | ||||
| #ifndef _UWP | ||||
|     HANDLE hFile = | ||||
|       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) | ||||
|       return nullptr; | ||||
| 
 | ||||
|  | @ -1175,8 +1182,8 @@ std::unique_ptr<ByteStream> ByteStream_OpenFileStream(const char* fileName, u32 | |||
|           } | ||||
|           else // if (errno == ENOTDIR)
 | ||||
|           { | ||||
|             // well.. someone's trying to open a fucking weird path that is comprised of both directories and files...
 | ||||
|             // I aint sticking around here to find out what disaster awaits... let fopen deal with it
 | ||||
|             // well.. someone's trying to open a fucking weird path that is comprised of both directories and
 | ||||
|             // files... I aint sticking around here to find out what disaster awaits... let fopen deal with it
 | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| #include <cinttypes> | ||||
| #include <cstdio> | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #if defined(_WIN32) && !defined(_UWP) | ||||
| #include "windows_headers.h" | ||||
| 
 | ||||
| #include "thirdparty/StackWalker.h" | ||||
|  |  | |||
|  | @ -21,6 +21,20 @@ | |||
| 
 | ||||
| #if defined(_WIN32) | ||||
| #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 | ||||
| #include <dirent.h> | ||||
| #include <errno.h> | ||||
|  | @ -713,7 +727,7 @@ std::vector<std::string> GetRootDirectoryList() | |||
| { | ||||
|   std::vector<std::string> results; | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #if defined(_WIN32) && !defined(_UWP) | ||||
|   char buf[256]; | ||||
|   if (GetLogicalDriveStringsA(sizeof(buf), buf) != 0) | ||||
|   { | ||||
|  | @ -725,6 +739,28 @@ std::vector<std::string> GetRootDirectoryList() | |||
|       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 | ||||
|   const char* home_path = std::getenv("HOME"); | ||||
|   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); }); | ||||
| } | ||||
| 
 | ||||
| #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) | ||||
| { | ||||
| #ifdef _WIN32 | ||||
|  | @ -789,9 +925,16 @@ std::FILE* OpenCFile(const char* filename, const char* mode) | |||
|     { | ||||
|       wfilename[wlen] = 0; | ||||
|       wmode[wmodelen] = 0; | ||||
| 
 | ||||
|       std::FILE* fp; | ||||
|       if (_wfopen_s(&fp, wfilename, wmode) != 0) | ||||
|       { | ||||
| #ifdef _UWP | ||||
|         return OpenCFileUWP(wfilename, wmode); | ||||
| #else | ||||
|         return nullptr; | ||||
| #endif | ||||
|       } | ||||
| 
 | ||||
|       return fp; | ||||
|     } | ||||
|  | @ -1052,6 +1195,19 @@ static u32 TranslateWin32Attributes(u32 Win32Attributes) | |||
|   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 | | ||||
|                                                         FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | | ||||
|                                                         FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION; | ||||
|  | @ -1064,7 +1220,7 @@ public: | |||
|       m_directoryChangeQueued(false) | ||||
|   { | ||||
|     m_bufferSize = 16384; | ||||
|     m_pBuffer = new byte[m_bufferSize]; | ||||
|     m_pBuffer = new u8[m_bufferSize]; | ||||
|   } | ||||
| 
 | ||||
|   virtual ~ChangeNotifierWin32() | ||||
|  | @ -1103,7 +1259,7 @@ public: | |||
|     // has any bytes?
 | ||||
|     if (bytesRead > 0) | ||||
|     { | ||||
|       const byte* pCurrentPointer = m_pBuffer; | ||||
|       const u8* pCurrentPointer = m_pBuffer; | ||||
|       PathString fileName; | ||||
|       for (;;) | ||||
|       { | ||||
|  | @ -1176,15 +1332,26 @@ private: | |||
|   HANDLE m_hDirectory; | ||||
|   OVERLAPPED m_overlapped; | ||||
|   bool m_directoryChangeQueued; | ||||
|   byte* m_pBuffer; | ||||
|   u8* m_pBuffer; | ||||
|   u32 m_bufferSize; | ||||
| }; | ||||
| 
 | ||||
| std::unique_ptr<ChangeNotifier> CreateChangeNotifier(const char* path, bool recursiveWatch) | ||||
| { | ||||
|   // open the directory up
 | ||||
|   HANDLE hDirectory = CreateFileA(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||||
|                                   nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr); | ||||
|   std::wstring path_wstr(StringUtil::UTF8StringToWideString(path)); | ||||
| #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) | ||||
|     return nullptr; | ||||
| 
 | ||||
|  | @ -1212,8 +1379,18 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co | |||
|     tempStr = StringUtil::StdStringFromFormat("%s\\*", OriginPath); | ||||
|   } | ||||
| 
 | ||||
|   // holder for utf-8 conversion
 | ||||
|   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); | ||||
| #else | ||||
|   HANDLE hFind = FindFirstFileExFromAppW(StringUtil::UTF8StringToWideString(tempStr).c_str(), FindExInfoBasic, &wfd, | ||||
|                                          FindExSearchNameMatch, nullptr, 0); | ||||
| #endif | ||||
| 
 | ||||
|   if (hFind == INVALID_HANDLE_VALUE) | ||||
|     return 0; | ||||
| 
 | ||||
|  | @ -1227,10 +1404,6 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co | |||
|     wildCardMatchAll = !(std::strcmp(Pattern, "*")); | ||||
|   } | ||||
| 
 | ||||
|   // holder for utf-8 conversion
 | ||||
|   std::string utf8_filename; | ||||
|   utf8_filename.reserve(countof(wfd.cFileName) * 2); | ||||
| 
 | ||||
|   // iterate results
 | ||||
|   do | ||||
|   { | ||||
|  | @ -1360,6 +1533,7 @@ bool FileSystem::StatFile(const char* path, FILESYSTEM_STAT_DATA* pStatData) | |||
| 
 | ||||
|   wpath[wlen] = 0; | ||||
| 
 | ||||
| #ifndef _UWP | ||||
|   // determine attributes for the path. if it's a directory, things have to be handled differently..
 | ||||
|   DWORD fileAttributes = GetFileAttributesW(wpath); | ||||
|   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->Size = ((u64)bhfi.nFileSizeHigh) << 32 | (u64)bhfi.nFileSizeLow; | ||||
|   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) | ||||
|  | @ -1447,7 +1631,7 @@ bool FileSystem::FileExists(const char* path) | |||
|   wpath[wlen] = 0; | ||||
| 
 | ||||
|   // 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) | ||||
|     return false; | ||||
| 
 | ||||
|  | @ -1477,7 +1661,7 @@ bool FileSystem::DirectoryExists(const char* path) | |||
|   wpath[wlen] = 0; | ||||
| 
 | ||||
|   // 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) | ||||
|     return false; | ||||
| 
 | ||||
|  | @ -1495,16 +1679,21 @@ bool FileSystem::CreateDirectory(const char* Path, bool Recursive) | |||
|   if (wpath[0] == L'\0') | ||||
|     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)) | ||||
|     return true; | ||||
| #else | ||||
|   if (CreateDirectoryFromAppW(wpath.c_str(), nullptr)) | ||||
|     return true; | ||||
| #endif | ||||
| 
 | ||||
|   // check error
 | ||||
|   DWORD lastError = GetLastError(); | ||||
|   if (lastError == ERROR_ALREADY_EXISTS) | ||||
|   { | ||||
|     // check the attributes
 | ||||
|     u32 Attributes = GetFileAttributesW(wpath.c_str()); | ||||
|     u32 Attributes = WrapGetFileAttributes(wpath.c_str()); | ||||
|     if (Attributes != INVALID_FILE_ATTRIBUTES && Attributes & FILE_ATTRIBUTE_DIRECTORY) | ||||
|       return true; | ||||
|     else | ||||
|  | @ -1523,7 +1712,13 @@ bool FileSystem::CreateDirectory(const char* Path, bool Recursive) | |||
|       if (wpath[i] == L'\\' || wpath[i] == L'/') | ||||
|       { | ||||
|         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(); | ||||
|           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
 | ||||
|     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(); | ||||
|         if (lastError != ERROR_ALREADY_EXISTS) | ||||
|  | @ -1561,14 +1761,15 @@ bool FileSystem::DeleteFile(const char* Path) | |||
|     return false; | ||||
| 
 | ||||
|   const std::wstring wpath(StringUtil::UTF8StringToWideString(Path)); | ||||
|   DWORD fileAttributes = GetFileAttributesW(wpath.c_str()); | ||||
|   if (fileAttributes == INVALID_FILE_ATTRIBUTES) | ||||
|   const DWORD fileAttributes = WrapGetFileAttributes(wpath.c_str()); | ||||
|   if (fileAttributes == INVALID_FILE_ATTRIBUTES || fileAttributes & FILE_ATTRIBUTE_DIRECTORY) | ||||
|     return false; | ||||
| 
 | ||||
|   if (!(fileAttributes & FILE_ATTRIBUTE_DIRECTORY)) | ||||
|     return (DeleteFileW(wpath.c_str()) == TRUE); | ||||
|   else | ||||
|     return false; | ||||
| #ifndef _UWP | ||||
|   return (DeleteFileW(wpath.c_str()) == TRUE); | ||||
| #else | ||||
|   return (DeleteFileFromAppW(wpath.c_str()) == TRUE); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 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 new_wpath(StringUtil::UTF8StringToWideString(NewPath)); | ||||
| 
 | ||||
| #ifndef _UWP | ||||
|   if (!MoveFileExW(old_wpath.c_str(), new_wpath.c_str(), MOVEFILE_REPLACE_EXISTING)) | ||||
|   { | ||||
|     Log_ErrorPrintf("MoveFileEx('%s', '%s') failed: %08X", OldPath, NewPath, GetLastError()); | ||||
|     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; | ||||
| } | ||||
|  | @ -1588,13 +1797,19 @@ bool FileSystem::RenamePath(const char* OldPath, const char* NewPath) | |||
| static bool RecursiveDeleteDirectory(const std::wstring& wpath, bool Recursive) | ||||
| { | ||||
|   // ensure it exists
 | ||||
|   DWORD fileAttributes = GetFileAttributesW(wpath.c_str()); | ||||
|   if (fileAttributes == INVALID_FILE_ATTRIBUTES || !(fileAttributes & FILE_ATTRIBUTE_DIRECTORY)) | ||||
|   const DWORD fileAttributes = WrapGetFileAttributes(wpath.c_str()); | ||||
|   if (fileAttributes == INVALID_FILE_ATTRIBUTES || fileAttributes & FILE_ATTRIBUTE_DIRECTORY) | ||||
|     return false; | ||||
| 
 | ||||
|   // non-recursive case just try removing the directory
 | ||||
|   if (!Recursive) | ||||
|   { | ||||
| #ifndef _UWP | ||||
|     return (RemoveDirectoryW(wpath.c_str()) == TRUE); | ||||
| #else | ||||
|     return (RemoveDirectoryFromAppW(wpath.c_str()) == TRUE); | ||||
| #endif | ||||
|   } | ||||
| 
 | ||||
|   // doing a recursive delete
 | ||||
|   std::wstring fileName = wpath; | ||||
|  | @ -1602,7 +1817,12 @@ static bool RecursiveDeleteDirectory(const std::wstring& wpath, bool Recursive) | |||
| 
 | ||||
|   // is there any files?
 | ||||
|   WIN32_FIND_DATAW findData; | ||||
| #ifndef _UWP | ||||
|   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) | ||||
|     return false; | ||||
| 
 | ||||
|  | @ -1634,7 +1854,12 @@ static bool RecursiveDeleteDirectory(const std::wstring& wpath, bool Recursive) | |||
|     else | ||||
|     { | ||||
|       // 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); | ||||
|         return false; | ||||
|  | @ -1644,7 +1869,12 @@ static bool RecursiveDeleteDirectory(const std::wstring& wpath, bool Recursive) | |||
|   FindClose(hFind); | ||||
| 
 | ||||
|   // 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; | ||||
| 
 | ||||
|   // done
 | ||||
|  | @ -1664,8 +1894,10 @@ std::string GetProgramPath() | |||
| 
 | ||||
|   // Fall back to the main module if this fails.
 | ||||
|   HMODULE module = nullptr; | ||||
| #ifndef _UWP | ||||
|   GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, | ||||
|                      reinterpret_cast<LPCWSTR>(&GetProgramPath), &module); | ||||
| #endif | ||||
| 
 | ||||
|   for (;;) | ||||
|   { | ||||
|  |  | |||
|  | @ -44,7 +44,21 @@ bool JitCodeBuffer::Allocate(u32 size /* = 64 * 1024 * 1024 */, u32 far_code_siz | |||
|   m_total_size = size + far_code_size; | ||||
| 
 | ||||
| #if defined(_WIN32) | ||||
| #if !defined(_UWP) | ||||
|   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) | ||||
|   { | ||||
|     Log_ErrorPrintf("VirtualAlloc(RWX, %u) for internal buffer failed: %u", m_total_size, GetLastError()); | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ public: | |||
|   JitCodeBuffer(void* buffer, u32 size, u32 far_code_size, u32 guard_size); | ||||
|   ~JitCodeBuffer(); | ||||
| 
 | ||||
|   bool IsValid() const { return (m_code_ptr != nullptr); } | ||||
| 
 | ||||
|   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); | ||||
|   void Destroy(); | ||||
|  |  | |||
|  | @ -135,8 +135,13 @@ bool MemoryArena::Create(size_t size, bool writable, bool executable) | |||
| 
 | ||||
| #if defined(_WIN32) | ||||
|   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), | ||||
|                                      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) | ||||
|   { | ||||
|     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; | ||||
| #if defined(_WIN32) | ||||
|   const DWORD desired_access = FILE_MAP_READ | (writable ? FILE_MAP_WRITE : 0) | (executable ? FILE_MAP_EXECUTE : 0); | ||||
| #ifndef _UWP | ||||
|   base_pointer = | ||||
|     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) | ||||
|     return nullptr; | ||||
| #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) | ||||
|  |  | |||
|  | @ -78,7 +78,7 @@ static bool IsStoreInstruction(const void* ptr) | |||
| } | ||||
| #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 LONG ExceptionHandler(PEXCEPTION_POINTERS exi) | ||||
|  | @ -110,6 +110,7 @@ static LONG ExceptionHandler(PEXCEPTION_POINTERS exi) | |||
|   } | ||||
| 
 | ||||
|   s_in_handler = false; | ||||
| 
 | ||||
|   return EXCEPTION_CONTINUE_SEARCH; | ||||
| } | ||||
| 
 | ||||
|  | @ -222,7 +223,7 @@ bool InstallHandler(void* owner, Callback callback) | |||
| 
 | ||||
|   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); | ||||
|     if (!s_veh_handle) | ||||
|     { | ||||
|  | @ -279,7 +280,7 @@ bool RemoveHandler(void* owner) | |||
| 
 | ||||
|   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); | ||||
|     s_veh_handle = nullptr; | ||||
| #elif defined(USE_SIGSEGV) | ||||
|  |  | |||
|  | @ -93,6 +93,7 @@ void Timer::SleepUntil(Value value, bool exact) | |||
|     if (diff <= 0) | ||||
|       return; | ||||
| 
 | ||||
| #ifndef _UWP | ||||
|     HANDLE timer = GetSleepTimer(); | ||||
|     if (timer) | ||||
|     { | ||||
|  | @ -110,6 +111,7 @@ void Timer::SleepUntil(Value value, bool exact) | |||
|         return; | ||||
|       } | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     // falling back to sleep... bad.
 | ||||
|     Sleep(static_cast<DWORD>(static_cast<std::uint64_t>(diff) / 1000000)); | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| #include "common/log.h" | ||||
| Log_SetChannel(WindowInfo); | ||||
| 
 | ||||
| #if defined(_WIN32) | ||||
| #if defined(_WIN32) && !defined(_UWP) | ||||
| 
 | ||||
| #include "common/windows_headers.h" | ||||
| #include <dwmapi.h> | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ struct WindowInfo | |||
|   { | ||||
|     Surfaceless, | ||||
|     Win32, | ||||
|     WinRT, | ||||
|     X11, | ||||
|     Wayland, | ||||
|     MacOS, | ||||
|  |  | |||
|  | @ -7,11 +7,13 @@ | |||
| #define NOMINMAX 1 | ||||
| #endif | ||||
| 
 | ||||
| // require vista+
 | ||||
| // require vista+, but don't set it when compiling for UWP
 | ||||
| #ifndef WINAPI_FAMILY | ||||
| #ifdef _WIN32_WINNT | ||||
| #undef _WIN32_WINNT | ||||
| #endif | ||||
| #define _WIN32_WINNT _WIN32_WINNT_VISTA | ||||
| #endif | ||||
| 
 | ||||
| #include <windows.h> | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Connor McLaughlin
						Connor McLaughlin