• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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