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
GetPath(HMODULE module)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
GetDirectory(HMODULE module)30 std::string GetDirectory(HMODULE module)
31 {
32 std::string executablePath = GetPath(module);
33 return StripFilenameFromPath(executablePath);
34 }
35
36 } // anonymous namespace
37
GetExecutablePath()38 std::string GetExecutablePath()
39 {
40 return GetPath(nullptr);
41 }
42
GetExecutableDirectory()43 std::string GetExecutableDirectory()
44 {
45 return GetDirectory(nullptr);
46 }
47
GetSharedLibraryExtension()48 const char *GetSharedLibraryExtension()
49 {
50 return "dll";
51 }
52
GetCWD()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
SetCWD(const char * dirName)64 bool SetCWD(const char *dirName)
65 {
66 return (SetCurrentDirectoryW(Widen(dirName).c_str()) == TRUE);
67 }
68
GetPathSeparatorForEnvironmentVar()69 const char *GetPathSeparatorForEnvironmentVar()
70 {
71 return ";";
72 }
73
GetCurrentSystemTime()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
GetCurrentProcessCpuTime()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
IsDirectory(const char * filename)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
IsDebuggerAttached()131 bool IsDebuggerAttached()
132 {
133 return !!::IsDebuggerPresent();
134 }
135
BreakDebugger()136 void BreakDebugger()
137 {
138 __debugbreak();
139 }
140
GetExecutableExtension()141 const char *GetExecutableExtension()
142 {
143 return ".exe";
144 }
145
GetPathSeparator()146 char GetPathSeparator()
147 {
148 return '\\';
149 }
150
GetModuleDirectory()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
GetRootDirectory()167 std::string GetRootDirectory()
168 {
169 return "C:\\";
170 }
171
GetTempDirectory()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
CreateTemporaryFileInDirectory(const std::string & directory)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
GetLibraryPath(void * libraryHandle)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
GetLibrarySymbol(void * libraryHandle,const char * symbolName)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
CloseSystemLibrary(void * libraryHandle)229 void CloseSystemLibrary(void *libraryHandle)
230 {
231 if (libraryHandle)
232 {
233 FreeLibrary(reinterpret_cast<HMODULE>(libraryHandle));
234 }
235 }
Narrow(const std::wstring_view & utf16)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
Widen(const std::string_view & utf8)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
265