summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/common/system_utils_win32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/common/system_utils_win32.cpp')
-rw-r--r--gfx/angle/checkout/src/common/system_utils_win32.cpp235
1 files changed, 235 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/common/system_utils_win32.cpp b/gfx/angle/checkout/src/common/system_utils_win32.cpp
new file mode 100644
index 0000000000..5bcfa2347e
--- /dev/null
+++ b/gfx/angle/checkout/src/common/system_utils_win32.cpp
@@ -0,0 +1,235 @@
+//
+// Copyright 2019 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_win32.cpp: Implementation of OS-specific functions for Windows.
+
+#include "common/FastVector.h"
+#include "system_utils.h"
+
+#include <array>
+
+// Must be included in this order.
+// clang-format off
+#include <windows.h>
+#include <psapi.h>
+// clang-format on
+
+namespace angle
+{
+bool UnsetEnvironmentVar(const char *variableName)
+{
+ return (SetEnvironmentVariableW(Widen(variableName).c_str(), nullptr) == TRUE);
+}
+
+bool SetEnvironmentVar(const char *variableName, const char *value)
+{
+ return (SetEnvironmentVariableW(Widen(variableName).c_str(), Widen(value).c_str()) == TRUE);
+}
+
+std::string GetEnvironmentVar(const char *variableName)
+{
+ std::wstring variableNameUtf16 = Widen(variableName);
+ FastVector<wchar_t, MAX_PATH> value;
+
+ DWORD result;
+
+ // First get the length of the variable, including the null terminator
+ result = GetEnvironmentVariableW(variableNameUtf16.c_str(), nullptr, 0);
+
+ // Zero means the variable was not found, so return now.
+ if (result == 0)
+ {
+ return std::string();
+ }
+
+ // Now size the vector to fit the data, and read the environment variable.
+ value.resize(result, 0);
+ result = GetEnvironmentVariableW(variableNameUtf16.c_str(), value.data(), result);
+
+ return Narrow(value.data());
+}
+
+void *OpenSystemLibraryWithExtensionAndGetError(const char *libraryName,
+ SearchType searchType,
+ std::string *errorOut)
+{
+ char buffer[MAX_PATH];
+ int ret = snprintf(buffer, MAX_PATH, "%s.%s", libraryName, GetSharedLibraryExtension());
+ if (ret <= 0 || ret >= MAX_PATH)
+ {
+ fprintf(stderr, "Error loading shared library: 0x%x", ret);
+ return nullptr;
+ }
+
+ HMODULE libraryModule = nullptr;
+
+ switch (searchType)
+ {
+ case SearchType::ModuleDir:
+ {
+ std::string moduleRelativePath = ConcatenatePath(GetModuleDirectory(), libraryName);
+ if (errorOut)
+ {
+ *errorOut = moduleRelativePath;
+ }
+ libraryModule = LoadLibraryW(Widen(moduleRelativePath).c_str());
+ break;
+ }
+
+ case SearchType::SystemDir:
+ {
+ if (errorOut)
+ {
+ *errorOut = libraryName;
+ }
+ libraryModule =
+ LoadLibraryExW(Widen(libraryName).c_str(), nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ break;
+ }
+
+ case SearchType::AlreadyLoaded:
+ {
+ if (errorOut)
+ {
+ *errorOut = libraryName;
+ }
+ libraryModule = GetModuleHandleW(Widen(libraryName).c_str());
+ break;
+ }
+ }
+
+ return reinterpret_cast<void *>(libraryModule);
+}
+
+namespace
+{
+class Win32PageFaultHandler : public PageFaultHandler
+{
+ public:
+ Win32PageFaultHandler(PageFaultCallback callback) : PageFaultHandler(callback) {}
+ ~Win32PageFaultHandler() override {}
+
+ bool enable() override;
+ bool disable() override;
+
+ LONG handle(PEXCEPTION_POINTERS pExceptionInfo);
+
+ private:
+ void *mVectoredExceptionHandler = nullptr;
+};
+
+Win32PageFaultHandler *gWin32PageFaultHandler = nullptr;
+static LONG CALLBACK VectoredExceptionHandler(PEXCEPTION_POINTERS info)
+{
+ return gWin32PageFaultHandler->handle(info);
+}
+
+bool SetMemoryProtection(uintptr_t start, size_t size, DWORD protections)
+{
+ DWORD oldProtect;
+ BOOL res = VirtualProtect(reinterpret_cast<LPVOID>(start), size, protections, &oldProtect);
+ if (!res)
+ {
+ DWORD lastError = GetLastError();
+ fprintf(stderr, "VirtualProtect failed: 0x%lx\n", lastError);
+ return false;
+ }
+
+ return true;
+}
+
+LONG Win32PageFaultHandler::handle(PEXCEPTION_POINTERS info)
+{
+ bool found = false;
+
+ if (info->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
+ info->ExceptionRecord->NumberParameters >= 2 &&
+ info->ExceptionRecord->ExceptionInformation[0] == 1)
+ {
+ found = mCallback(static_cast<uintptr_t>(info->ExceptionRecord->ExceptionInformation[1])) ==
+ PageFaultHandlerRangeType::InRange;
+ }
+
+ if (found)
+ {
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ else
+ {
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+}
+
+bool Win32PageFaultHandler::disable()
+{
+ if (mVectoredExceptionHandler)
+ {
+ ULONG res = RemoveVectoredExceptionHandler(mVectoredExceptionHandler);
+ mVectoredExceptionHandler = nullptr;
+ if (res == 0)
+ {
+ DWORD lastError = GetLastError();
+ fprintf(stderr, "RemoveVectoredExceptionHandler failed: 0x%lx\n", lastError);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Win32PageFaultHandler::enable()
+{
+ if (mVectoredExceptionHandler)
+ {
+ return true;
+ }
+
+ PVECTORED_EXCEPTION_HANDLER handler =
+ reinterpret_cast<PVECTORED_EXCEPTION_HANDLER>(&VectoredExceptionHandler);
+
+ mVectoredExceptionHandler = AddVectoredExceptionHandler(1, handler);
+
+ if (!mVectoredExceptionHandler)
+ {
+ DWORD lastError = GetLastError();
+ fprintf(stderr, "AddVectoredExceptionHandler failed: 0x%lx\n", lastError);
+ return false;
+ }
+ return true;
+}
+} // namespace
+
+// Set write protection
+bool ProtectMemory(uintptr_t start, size_t size)
+{
+ return SetMemoryProtection(start, size, PAGE_READONLY);
+}
+
+// Allow reading and writing
+bool UnprotectMemory(uintptr_t start, size_t size)
+{
+ return SetMemoryProtection(start, size, PAGE_READWRITE);
+}
+
+size_t GetPageSize()
+{
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ return static_cast<size_t>(info.dwPageSize);
+}
+
+PageFaultHandler *CreatePageFaultHandler(PageFaultCallback callback)
+{
+ gWin32PageFaultHandler = new Win32PageFaultHandler(callback);
+ return gWin32PageFaultHandler;
+}
+
+uint64_t GetProcessMemoryUsageKB()
+{
+ PROCESS_MEMORY_COUNTERS_EX pmc;
+ ::GetProcessMemoryInfo(::GetCurrentProcess(), reinterpret_cast<PROCESS_MEMORY_COUNTERS *>(&pmc),
+ sizeof(pmc));
+ return static_cast<uint64_t>(pmc.PrivateUsage) / 1024ull;
+}
+} // namespace angle