system_utils_win.cpp (6743B)
1 // 2 // Copyright 2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // system_utils_win.cpp: Implementation of OS-specific functions for Windows 8 9 #include "system_utils.h" 10 11 #include <stdarg.h> 12 #include <windows.h> 13 #include <array> 14 #include <vector> 15 16 namespace angle 17 { 18 19 namespace 20 { 21 22 std::string GetPath(HMODULE module) 23 { 24 std::array<wchar_t, MAX_PATH> executableFileBuf; 25 DWORD executablePathLen = GetModuleFileNameW(module, executableFileBuf.data(), 26 static_cast<DWORD>(executableFileBuf.size())); 27 return Narrow(executablePathLen > 0 ? executableFileBuf.data() : L""); 28 } 29 30 std::string GetDirectory(HMODULE module) 31 { 32 std::string executablePath = GetPath(module); 33 return StripFilenameFromPath(executablePath); 34 } 35 36 } // anonymous namespace 37 38 std::string GetExecutablePath() 39 { 40 return GetPath(nullptr); 41 } 42 43 std::string GetExecutableDirectory() 44 { 45 return GetDirectory(nullptr); 46 } 47 48 const char *GetSharedLibraryExtension() 49 { 50 return "dll"; 51 } 52 53 Optional<std::string> GetCWD() 54 { 55 std::array<wchar_t, MAX_PATH> pathBuf; 56 DWORD result = GetCurrentDirectoryW(static_cast<DWORD>(pathBuf.size()), pathBuf.data()); 57 if (result == 0) 58 { 59 return Optional<std::string>::Invalid(); 60 } 61 return Narrow(pathBuf.data()); 62 } 63 64 bool SetCWD(const char *dirName) 65 { 66 return (SetCurrentDirectoryW(Widen(dirName).c_str()) == TRUE); 67 } 68 69 const char *GetPathSeparatorForEnvironmentVar() 70 { 71 return ";"; 72 } 73 74 double GetCurrentSystemTime() 75 { 76 LARGE_INTEGER frequency = {}; 77 QueryPerformanceFrequency(&frequency); 78 79 LARGE_INTEGER curTime; 80 QueryPerformanceCounter(&curTime); 81 82 return static_cast<double>(curTime.QuadPart) / frequency.QuadPart; 83 } 84 85 double GetCurrentProcessCpuTime() 86 { 87 FILETIME creationTime = {}; 88 FILETIME exitTime = {}; 89 FILETIME kernelTime = {}; 90 FILETIME userTime = {}; 91 92 // Note this will not give accurate results if the current thread is 93 // scheduled for less than the tick rate, which is often 15 ms. In that 94 // case, GetProcessTimes will not return different values, making it 95 // possible to end up with 0 ms for a process that takes 93% of a core 96 // (14/15 ms)! An alternative is QueryProcessCycleTime but there is no 97 // simple way to convert cycles back to seconds, and on top of that, it's 98 // not supported pre-Windows Vista. 99 100 // Returns 100-ns intervals, so we want to divide by 1e7 to get seconds 101 GetProcessTimes(GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime); 102 103 ULARGE_INTEGER kernelInt64; 104 kernelInt64.LowPart = kernelTime.dwLowDateTime; 105 kernelInt64.HighPart = kernelTime.dwHighDateTime; 106 double systemTimeSeconds = static_cast<double>(kernelInt64.QuadPart) * 1e-7; 107 108 ULARGE_INTEGER userInt64; 109 userInt64.LowPart = userTime.dwLowDateTime; 110 userInt64.HighPart = userTime.dwHighDateTime; 111 double userTimeSeconds = static_cast<double>(userInt64.QuadPart) * 1e-7; 112 113 return systemTimeSeconds + userTimeSeconds; 114 } 115 116 bool IsDirectory(const char *filename) 117 { 118 WIN32_FILE_ATTRIBUTE_DATA fileInformation; 119 120 BOOL result = 121 GetFileAttributesExW(Widen(filename).c_str(), GetFileExInfoStandard, &fileInformation); 122 if (result) 123 { 124 DWORD attribs = fileInformation.dwFileAttributes; 125 return (attribs != INVALID_FILE_ATTRIBUTES) && ((attribs & FILE_ATTRIBUTE_DIRECTORY) > 0); 126 } 127 128 return false; 129 } 130 131 bool IsDebuggerAttached() 132 { 133 return !!::IsDebuggerPresent(); 134 } 135 136 void BreakDebugger() 137 { 138 __debugbreak(); 139 } 140 141 const char *GetExecutableExtension() 142 { 143 return ".exe"; 144 } 145 146 char GetPathSeparator() 147 { 148 return '\\'; 149 } 150 151 std::string GetModuleDirectory() 152 { 153 // GetModuleHandleEx is unavailable on UWP 154 #if !defined(ANGLE_IS_WINUWP) 155 static int placeholderSymbol = 0; 156 HMODULE module = nullptr; 157 if (GetModuleHandleExW( 158 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 159 reinterpret_cast<LPCWSTR>(&placeholderSymbol), &module)) 160 { 161 return GetDirectory(module); 162 } 163 #endif 164 return GetDirectory(nullptr); 165 } 166 167 std::string GetRootDirectory() 168 { 169 return "C:\\"; 170 } 171 172 Optional<std::string> GetTempDirectory() 173 { 174 char tempDirOut[MAX_PATH + 1]; 175 GetTempPathA(MAX_PATH + 1, tempDirOut); 176 std::string tempDir = std::string(tempDirOut); 177 178 if (tempDir.length() < 0 || tempDir.length() > MAX_PATH) 179 { 180 return Optional<std::string>::Invalid(); 181 } 182 183 if (tempDir.length() > 0 && tempDir.back() == '\\') 184 { 185 tempDir.pop_back(); 186 } 187 188 return tempDir; 189 } 190 191 Optional<std::string> CreateTemporaryFileInDirectory(const std::string &directory) 192 { 193 char fileName[MAX_PATH + 1]; 194 if (GetTempFileNameA(directory.c_str(), "ANGLE", 0, fileName) == 0) 195 return Optional<std::string>::Invalid(); 196 197 return std::string(fileName); 198 } 199 200 std::string GetLibraryPath(void *libraryHandle) 201 { 202 if (!libraryHandle) 203 { 204 return ""; 205 } 206 207 std::array<wchar_t, MAX_PATH> buffer; 208 if (GetModuleFileNameW(reinterpret_cast<HMODULE>(libraryHandle), buffer.data(), 209 buffer.size()) == 0) 210 { 211 return ""; 212 } 213 214 return Narrow(buffer.data()); 215 } 216 217 void *GetLibrarySymbol(void *libraryHandle, const char *symbolName) 218 { 219 if (!libraryHandle) 220 { 221 fprintf(stderr, "Module was not loaded\n"); 222 return nullptr; 223 } 224 225 return reinterpret_cast<void *>( 226 GetProcAddress(reinterpret_cast<HMODULE>(libraryHandle), symbolName)); 227 } 228 229 void CloseSystemLibrary(void *libraryHandle) 230 { 231 if (libraryHandle) 232 { 233 FreeLibrary(reinterpret_cast<HMODULE>(libraryHandle)); 234 } 235 } 236 std::string Narrow(const std::wstring_view &utf16) 237 { 238 if (utf16.empty()) 239 { 240 return {}; 241 } 242 int requiredSize = WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.size()), 243 nullptr, 0, nullptr, nullptr); 244 std::string utf8(requiredSize, '\0'); 245 WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.size()), &utf8[0], 246 requiredSize, nullptr, nullptr); 247 return utf8; 248 } 249 250 std::wstring Widen(const std::string_view &utf8) 251 { 252 if (utf8.empty()) 253 { 254 return {}; 255 } 256 int requiredSize = 257 MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), nullptr, 0); 258 std::wstring utf16(requiredSize, L'\0'); 259 MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), &utf16[0], 260 requiredSize); 261 return utf16; 262 } 263 264 } // namespace angle