//
// Copyright 2014 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.
//

// test_utils_win.cpp: Implementation of OS-specific functions for Windows

#include "util/test_utils.h"

#include <aclapi.h>
#include <stdarg.h>
#include <versionhelpers.h>
#include <windows.h>
#include <array>
#include <iostream>
#include <vector>

#include "anglebase/no_destructor.h"
#include "common/angleutils.h"

namespace angle
{
namespace
{
struct ScopedPipe
{
    ~ScopedPipe()
    {
        closeReadHandle();
        closeWriteHandle();
    }
    bool closeReadHandle()
    {
        if (readHandle)
        {
            if (::CloseHandle(readHandle) == FALSE)
            {
                std::cerr << "Error closing write handle: " << GetLastError();
                return false;
            }
            readHandle = nullptr;
        }

        return true;
    }
    bool closeWriteHandle()
    {
        if (writeHandle)
        {
            if (::CloseHandle(writeHandle) == FALSE)
            {
                std::cerr << "Error closing write handle: " << GetLastError();
                return false;
            }
            writeHandle = nullptr;
        }

        return true;
    }

    bool valid() const { return readHandle != nullptr || writeHandle != nullptr; }

    bool initPipe(SECURITY_ATTRIBUTES *securityAttribs)
    {
        if (::CreatePipe(&readHandle, &writeHandle, securityAttribs, 0) == FALSE)
        {
            std::cerr << "Error creating pipe: " << GetLastError() << "\n";
            return false;
        }

#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
        // Ensure the read handles to the pipes are not inherited.
        if (::SetHandleInformation(readHandle, HANDLE_FLAG_INHERIT, 0) == FALSE)
        {
            std::cerr << "Error setting handle info on pipe: " << GetLastError() << "\n";
            return false;
        }
#endif  // !defined(ANGLE_ENABLE_WINDOWS_UWP)

        return true;
    }

    HANDLE readHandle  = nullptr;
    HANDLE writeHandle = nullptr;
};

// Returns false on EOF or error.
void ReadFromFile(bool blocking, HANDLE handle, std::string *out)
{
    char buffer[8192];
    DWORD bytesRead = 0;

    while (true)
    {
        if (!blocking)
        {
            BOOL success = ::PeekNamedPipe(handle, nullptr, 0, nullptr, &bytesRead, nullptr);
            if (success == FALSE || bytesRead == 0)
                return;
        }

        BOOL success = ::ReadFile(handle, buffer, sizeof(buffer), &bytesRead, nullptr);
        if (success == FALSE || bytesRead == 0)
            return;

        out->append(buffer, bytesRead);
    }

    // unreachable.
}

// Returns the Win32 last error code or ERROR_SUCCESS if the last error code is
// ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND. This is useful in cases where
// the absence of a file or path is a success condition (e.g., when attempting
// to delete an item in the filesystem).
bool ReturnSuccessOnNotFound()
{
    const DWORD error_code = ::GetLastError();
    return (error_code == ERROR_FILE_NOT_FOUND || error_code == ERROR_PATH_NOT_FOUND);
}

// Job objects seems to have problems on the Chromium CI and Windows 7.
bool ShouldUseJobObjects()
{
#if defined(ANGLE_ENABLE_WINDOWS_UWP)
    return false;
#else
    return (::IsWindows10OrGreater());
#endif
}

class WindowsProcess : public Process
{
  public:
    WindowsProcess(const std::vector<const char *> &commandLineArgs,
                   bool captureStdOut,
                   bool captureStdErr)
    {
        mProcessInfo.hProcess = INVALID_HANDLE_VALUE;
        mProcessInfo.hThread  = INVALID_HANDLE_VALUE;

        std::vector<char> commandLineString;
        for (const char *arg : commandLineArgs)
        {
            if (arg)
            {
                if (!commandLineString.empty())
                {
                    commandLineString.push_back(' ');
                }
                commandLineString.insert(commandLineString.end(), arg, arg + strlen(arg));
            }
        }
        commandLineString.push_back('\0');

        // Set the bInheritHandle flag so pipe handles are inherited.
        SECURITY_ATTRIBUTES securityAttribs;
        securityAttribs.nLength              = sizeof(SECURITY_ATTRIBUTES);
        securityAttribs.bInheritHandle       = TRUE;
        securityAttribs.lpSecurityDescriptor = nullptr;

        STARTUPINFOA startInfo = {};

        // Create pipes for stdout and stderr.
        startInfo.cb        = sizeof(STARTUPINFOA);
        startInfo.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
        if (captureStdOut)
        {
            if (!mStdoutPipe.initPipe(&securityAttribs))
            {
                return;
            }
            startInfo.hStdOutput = mStdoutPipe.writeHandle;
        }
        else
        {
            startInfo.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
        }

        if (captureStdErr)
        {
            if (!mStderrPipe.initPipe(&securityAttribs))
            {
                return;
            }
            startInfo.hStdError = mStderrPipe.writeHandle;
        }
        else
        {
            startInfo.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
        }

#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
        if (captureStdOut || captureStdErr)
        {
            startInfo.dwFlags |= STARTF_USESTDHANDLES;
        }

        if (ShouldUseJobObjects())
        {
            // Create job object. Job objects allow us to automatically force child processes to
            // exit if the parent process is unexpectedly killed. This should prevent ghost
            // processes from hanging around.
            mJobHandle = ::CreateJobObjectA(nullptr, nullptr);
            if (mJobHandle == NULL)
            {
                std::cerr << "Error creating job object: " << GetLastError() << "\n";
                return;
            }

            JOBOBJECT_EXTENDED_LIMIT_INFORMATION limitInfo = {};
            limitInfo.BasicLimitInformation.LimitFlags     = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
            if (::SetInformationJobObject(mJobHandle, JobObjectExtendedLimitInformation, &limitInfo,
                                          sizeof(limitInfo)) == FALSE)
            {
                std::cerr << "Error setting job information: " << GetLastError() << "\n";
                return;
            }
        }
#endif  // !defined(ANGLE_ENABLE_WINDOWS_UWP)

        // Create the child process.
        if (::CreateProcessA(nullptr, commandLineString.data(), nullptr, nullptr,
                             TRUE,  // Handles are inherited.
                             0, nullptr, nullptr, &startInfo, &mProcessInfo) == FALSE)
        {
            std::cerr << "CreateProcessA Error code: " << GetLastError() << "\n";
            return;
        }

#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
        if (mJobHandle != nullptr)
        {
            if (::AssignProcessToJobObject(mJobHandle, mProcessInfo.hProcess) == FALSE)
            {
                std::cerr << "AssignProcessToJobObject failed: " << GetLastError() << "\n";
                return;
            }
        }
#endif  // !defined(ANGLE_ENABLE_WINDOWS_UWP)

        // Close the write end of the pipes, so EOF can be generated when child exits.
        if (!mStdoutPipe.closeWriteHandle() || !mStderrPipe.closeWriteHandle())
            return;

        mStarted = true;
        mTimer.start();
    }

    ~WindowsProcess() override
    {
        if (mProcessInfo.hProcess != INVALID_HANDLE_VALUE)
        {
            ::CloseHandle(mProcessInfo.hProcess);
        }
        if (mProcessInfo.hThread != INVALID_HANDLE_VALUE)
        {
            ::CloseHandle(mProcessInfo.hThread);
        }
        if (mJobHandle != nullptr)
        {
            ::CloseHandle(mJobHandle);
        }
    }

    bool started() override { return mStarted; }

    bool finish() override
    {
        if (mStdoutPipe.valid())
        {
            ReadFromFile(true, mStdoutPipe.readHandle, &mStdout);
        }

        if (mStderrPipe.valid())
        {
            ReadFromFile(true, mStderrPipe.readHandle, &mStderr);
        }

        DWORD result = ::WaitForSingleObject(mProcessInfo.hProcess, INFINITE);
        mTimer.stop();
        return result == WAIT_OBJECT_0;
    }

    bool finished() override
    {
        if (!mStarted)
            return false;

        // Pipe stdin and stdout.
        if (mStdoutPipe.valid())
        {
            ReadFromFile(false, mStdoutPipe.readHandle, &mStdout);
        }

        if (mStderrPipe.valid())
        {
            ReadFromFile(false, mStderrPipe.readHandle, &mStderr);
        }

        DWORD result = ::WaitForSingleObject(mProcessInfo.hProcess, 0);
        if (result == WAIT_OBJECT_0)
        {
            mTimer.stop();
            return true;
        }
        if (result == WAIT_TIMEOUT)
            return false;

        mTimer.stop();
        std::cerr << "Unexpected result from WaitForSingleObject: " << result
                  << ". Last error: " << ::GetLastError() << "\n";
        return false;
    }

    int getExitCode() override
    {
        if (!mStarted)
            return -1;

        if (mProcessInfo.hProcess == INVALID_HANDLE_VALUE)
            return -1;

        DWORD exitCode = 0;
        if (::GetExitCodeProcess(mProcessInfo.hProcess, &exitCode) == FALSE)
            return -1;

        return static_cast<int>(exitCode);
    }

    bool kill() override
    {
        if (!mStarted)
            return true;

        HANDLE newHandle;
        if (::DuplicateHandle(::GetCurrentProcess(), mProcessInfo.hProcess, ::GetCurrentProcess(),
                              &newHandle, PROCESS_ALL_ACCESS, false,
                              DUPLICATE_CLOSE_SOURCE) == FALSE)
        {
            std::cerr << "Error getting permission to terminate process: " << ::GetLastError()
                      << "\n";
            return false;
        }
        mProcessInfo.hProcess = newHandle;

#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
        if (::TerminateThread(mProcessInfo.hThread, 1) == FALSE)
        {
            std::cerr << "TerminateThread failed: " << GetLastError() << "\n";
            return false;
        }
#endif  // !defined(ANGLE_ENABLE_WINDOWS_UWP)

        if (::TerminateProcess(mProcessInfo.hProcess, 1) == FALSE)
        {
            std::cerr << "TerminateProcess failed: " << GetLastError() << "\n";
            return false;
        }

        mStarted = false;
        mTimer.stop();
        return true;
    }

  private:
    bool mStarted = false;
    ScopedPipe mStdoutPipe;
    ScopedPipe mStderrPipe;
    PROCESS_INFORMATION mProcessInfo = {};
    HANDLE mJobHandle                = nullptr;
};
}  // namespace

void Sleep(unsigned int milliseconds)
{
    ::Sleep(static_cast<DWORD>(milliseconds));
}

void WriteDebugMessage(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    int size = vsnprintf(nullptr, 0, format, args);
    va_end(args);

    std::vector<char> buffer(size + 2);
    va_start(args, format);
    vsnprintf(buffer.data(), size + 1, format, args);
    va_end(args);

    OutputDebugStringA(buffer.data());
}

Process *LaunchProcess(const std::vector<const char *> &args,
                       bool captureStdout,
                       bool captureStderr)
{
    return new WindowsProcess(args, captureStdout, captureStderr);
}

bool GetTempDir(char *tempDirOut, uint32_t maxDirNameLen)
{
    DWORD pathLen = ::GetTempPathA(maxDirNameLen, tempDirOut);
    return (pathLen < MAX_PATH && pathLen > 0);
}

bool CreateTemporaryFileInDir(const char *dir, char *tempFileNameOut, uint32_t maxFileNameLen)
{
    char fileName[MAX_PATH + 1];
    if (::GetTempFileNameA(dir, "ANGLE", 0, fileName) == 0)
        return false;

    strncpy(tempFileNameOut, fileName, maxFileNameLen);
    return true;
}

bool DeleteFile(const char *path)
{
    if (strlen(path) >= MAX_PATH)
        return false;

    const DWORD attr = ::GetFileAttributesA(path);
    // Report success if the file or path does not exist.
    if (attr == INVALID_FILE_ATTRIBUTES)
    {
        return ReturnSuccessOnNotFound();
    }

    // Clear the read-only bit if it is set.
    if ((attr & FILE_ATTRIBUTE_READONLY) &&
        !::SetFileAttributesA(path, attr & ~FILE_ATTRIBUTE_READONLY))
    {
        // It's possible for |path| to be gone now under a race with other deleters.
        return ReturnSuccessOnNotFound();
    }

    // We don't handle directories right now.
    if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
    {
        return false;
    }

    return !!::DeleteFileA(path) ? true : ReturnSuccessOnNotFound();
}
}  // namespace angle
