//
// 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
