diff options
Diffstat (limited to 'gfx/angle/checkout/src/common/system_utils_win32.cpp')
-rw-r--r-- | gfx/angle/checkout/src/common/system_utils_win32.cpp | 235 |
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 |