| // | |
| // Copyright 2014 The ANGLE Project Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // | |
| // system_utils_win.cpp: Implementation of OS-specific functions for Windows | |
| #include "system_utils.h" | |
| #include <stdarg.h> | |
| #include <windows.h> | |
| #include <array> | |
| #include <vector> | |
| namespace angle | |
| { | |
| namespace | |
| { | |
| std::string GetPath(HMODULE module) | |
| { | |
| std::array<wchar_t, MAX_PATH> executableFileBuf; | |
| DWORD executablePathLen = GetModuleFileNameW(module, executableFileBuf.data(), | |
| static_cast<DWORD>(executableFileBuf.size())); | |
| return Narrow(executablePathLen > 0 ? executableFileBuf.data() : L""); | |
| } | |
| std::string GetDirectory(HMODULE module) | |
| { | |
| std::string executablePath = GetPath(module); | |
| return StripFilenameFromPath(executablePath); | |
| } | |
| } // anonymous namespace | |
| std::string GetExecutablePath() | |
| { | |
| return GetPath(nullptr); | |
| } | |
| std::string GetExecutableDirectory() | |
| { | |
| return GetDirectory(nullptr); | |
| } | |
| const char *GetSharedLibraryExtension() | |
| { | |
| return "dll"; | |
| } | |
| Optional<std::string> GetCWD() | |
| { | |
| std::array<wchar_t, MAX_PATH> pathBuf; | |
| DWORD result = GetCurrentDirectoryW(static_cast<DWORD>(pathBuf.size()), pathBuf.data()); | |
| if (result == 0) | |
| { | |
| return Optional<std::string>::Invalid(); | |
| } | |
| return Narrow(pathBuf.data()); | |
| } | |
| bool SetCWD(const char *dirName) | |
| { | |
| return (SetCurrentDirectoryW(Widen(dirName).c_str()) == TRUE); | |
| } | |
| const char *GetPathSeparatorForEnvironmentVar() | |
| { | |
| return ";"; | |
| } | |
| double GetCurrentSystemTime() | |
| { | |
| LARGE_INTEGER frequency = {}; | |
| QueryPerformanceFrequency(&frequency); | |
| LARGE_INTEGER curTime; | |
| QueryPerformanceCounter(&curTime); | |
| return static_cast<double>(curTime.QuadPart) / frequency.QuadPart; | |
| } | |
| double GetCurrentProcessCpuTime() | |
| { | |
| FILETIME creationTime = {}; | |
| FILETIME exitTime = {}; | |
| FILETIME kernelTime = {}; | |
| FILETIME userTime = {}; | |
| // Note this will not give accurate results if the current thread is | |
| // scheduled for less than the tick rate, which is often 15 ms. In that | |
| // case, GetProcessTimes will not return different values, making it | |
| // possible to end up with 0 ms for a process that takes 93% of a core | |
| // (14/15 ms)! An alternative is QueryProcessCycleTime but there is no | |
| // simple way to convert cycles back to seconds, and on top of that, it's | |
| // not supported pre-Windows Vista. | |
| // Returns 100-ns intervals, so we want to divide by 1e7 to get seconds | |
| GetProcessTimes(GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime); | |
| ULARGE_INTEGER kernelInt64; | |
| kernelInt64.LowPart = kernelTime.dwLowDateTime; | |
| kernelInt64.HighPart = kernelTime.dwHighDateTime; | |
| double systemTimeSeconds = static_cast<double>(kernelInt64.QuadPart) * 1e-7; | |
| ULARGE_INTEGER userInt64; | |
| userInt64.LowPart = userTime.dwLowDateTime; | |
| userInt64.HighPart = userTime.dwHighDateTime; | |
| double userTimeSeconds = static_cast<double>(userInt64.QuadPart) * 1e-7; | |
| return systemTimeSeconds + userTimeSeconds; | |
| } | |
| bool IsDirectory(const char *filename) | |
| { | |
| WIN32_FILE_ATTRIBUTE_DATA fileInformation; | |
| BOOL result = | |
| GetFileAttributesExW(Widen(filename).c_str(), GetFileExInfoStandard, &fileInformation); | |
| if (result) | |
| { | |
| DWORD attribs = fileInformation.dwFileAttributes; | |
| return (attribs != INVALID_FILE_ATTRIBUTES) && ((attribs & FILE_ATTRIBUTE_DIRECTORY) > 0); | |
| } | |
| return false; | |
| } | |
| bool IsDebuggerAttached() | |
| { | |
| return !!::IsDebuggerPresent(); | |
| } | |
| void BreakDebugger() | |
| { | |
| __debugbreak(); | |
| } | |
| const char *GetExecutableExtension() | |
| { | |
| return ".exe"; | |
| } | |
| char GetPathSeparator() | |
| { | |
| return '\\'; | |
| } | |
| std::string GetModuleDirectory() | |
| { | |
| // GetModuleHandleEx is unavailable on UWP | |
| #if !defined(ANGLE_IS_WINUWP) | |
| static int placeholderSymbol = 0; | |
| HMODULE module = nullptr; | |
| if (GetModuleHandleExW( | |
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, | |
| reinterpret_cast<LPCWSTR>(&placeholderSymbol), &module)) | |
| { | |
| return GetDirectory(module); | |
| } | |
| #endif | |
| return GetDirectory(nullptr); | |
| } | |
| std::string GetRootDirectory() | |
| { | |
| return "C:\\"; | |
| } | |
| Optional<std::string> GetTempDirectory() | |
| { | |
| char tempDirOut[MAX_PATH + 1]; | |
| GetTempPathA(MAX_PATH + 1, tempDirOut); | |
| std::string tempDir = std::string(tempDirOut); | |
| if (tempDir.length() < 0 || tempDir.length() > MAX_PATH) | |
| { | |
| return Optional<std::string>::Invalid(); | |
| } | |
| if (tempDir.length() > 0 && tempDir.back() == '\\') | |
| { | |
| tempDir.pop_back(); | |
| } | |
| return tempDir; | |
| } | |
| Optional<std::string> CreateTemporaryFileInDirectory(const std::string &directory) | |
| { | |
| char fileName[MAX_PATH + 1]; | |
| if (GetTempFileNameA(directory.c_str(), "ANGLE", 0, fileName) == 0) | |
| return Optional<std::string>::Invalid(); | |
| return std::string(fileName); | |
| } | |
| std::string GetLibraryPath(void *libraryHandle) | |
| { | |
| if (!libraryHandle) | |
| { | |
| return ""; | |
| } | |
| std::array<wchar_t, MAX_PATH> buffer; | |
| if (GetModuleFileNameW(reinterpret_cast<HMODULE>(libraryHandle), buffer.data(), | |
| buffer.size()) == 0) | |
| { | |
| return ""; | |
| } | |
| return Narrow(buffer.data()); | |
| } | |
| void *GetLibrarySymbol(void *libraryHandle, const char *symbolName) | |
| { | |
| if (!libraryHandle) | |
| { | |
| fprintf(stderr, "Module was not loaded\n"); | |
| return nullptr; | |
| } | |
| return reinterpret_cast<void *>( | |
| GetProcAddress(reinterpret_cast<HMODULE>(libraryHandle), symbolName)); | |
| } | |
| void CloseSystemLibrary(void *libraryHandle) | |
| { | |
| if (libraryHandle) | |
| { | |
| FreeLibrary(reinterpret_cast<HMODULE>(libraryHandle)); | |
| } | |
| } | |
| std::string Narrow(const std::wstring_view &utf16) | |
| { | |
| if (utf16.empty()) | |
| { | |
| return {}; | |
| } | |
| int requiredSize = WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.size()), | |
| nullptr, 0, nullptr, nullptr); | |
| std::string utf8(requiredSize, '\0'); | |
| WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.size()), &utf8[0], | |
| requiredSize, nullptr, nullptr); | |
| return utf8; | |
| } | |
| std::wstring Widen(const std::string_view &utf8) | |
| { | |
| if (utf8.empty()) | |
| { | |
| return {}; | |
| } | |
| int requiredSize = | |
| MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), nullptr, 0); | |
| std::wstring utf16(requiredSize, L'\0'); | |
| MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), &utf16[0], | |
| requiredSize); | |
| return utf16; | |
| } | |
| } // namespace angle |