/*
 * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include <algorithm>
#include "Executor.h"
#include "Log.h"
#include "WinErrorHandling.h"


namespace {

void escapeArg(std::wstring& str) {
    if (str.empty()) {
        return;
    }

    if (str.front() == L'\"' && str.back() == L'\"' && str.size() > 1) {
        return;
    }

    if (str.find_first_of(L" \t") != std::wstring::npos) {
        str = L'"' + str + L'"';
    }
}

} // namespace


std::wstring Executor::args() const {
    tstring_array tmpArgs;
    // argv[0] is the module name.
    tmpArgs.push_back(appPath);
    tmpArgs.insert(tmpArgs.end(), argsArray.begin(), argsArray.end());

    std::for_each(tmpArgs.begin(), tmpArgs.end(), escapeArg);
    return tstrings::join(tmpArgs.begin(), tmpArgs.end(), _T(" "));
}


int Executor::execAndWaitForExit() const {
    UniqueHandle threadHandle;
    UniqueHandle h = startProcess(&threadHandle);

    if (theSuspended) {
        LOG_TRACE(tstrings::any() << "ResumeThread()");
        if (((DWORD)-1) == ResumeThread(threadHandle.get())) {
            JP_THROW(SysError("ResumeThread() failed", ResumeThread));
        }
    }

    const DWORD res = ::WaitForSingleObject(h.get(), INFINITE);
    if (WAIT_FAILED ==  res) {
        JP_THROW(SysError("WaitForSingleObject() failed", WaitForSingleObject));
    }

    DWORD exitCode = 0;
    if (!GetExitCodeProcess(h.get(), &exitCode)) {
        // Error reading process's exit code.
        JP_THROW(SysError("GetExitCodeProcess() failed", GetExitCodeProcess));
    }

    const DWORD processId = GetProcessId(h.get());
    if (!processId) {
        JP_THROW(SysError("GetProcessId() failed.", GetProcessId));
    }

    LOG_TRACE(tstrings::any() << "Process with PID=" << processId
                                << " terminated. Exit code=" << exitCode);

    return static_cast<int>(exitCode);
}


UniqueHandle Executor::startProcess(UniqueHandle* threadHandle) const {
    const std::wstring argsStr = args();

    std::vector<TCHAR> argsBuffer(argsStr.begin(), argsStr.end());
    argsBuffer.push_back(0); // terminating '\0'

    STARTUPINFO startupInfo;
    ZeroMemory(&startupInfo, sizeof(startupInfo));
    startupInfo.cb = sizeof(startupInfo);

    PROCESS_INFORMATION processInfo;
    ZeroMemory(&processInfo, sizeof(processInfo));

    DWORD creationFlags = 0;

    if (theSuspended) {
        creationFlags |= CREATE_SUSPENDED;
    }

    if (!theVisible) {
        // For GUI applications.
        startupInfo.dwFlags |= STARTF_USESHOWWINDOW;
        startupInfo.wShowWindow = SW_HIDE;

        // For console applications.
        creationFlags |= CREATE_NO_WINDOW;
    }

    tstrings::any msg;
    msg << "CreateProcess";
    if (theSuspended) {
        msg << "[suspended]";
    }
    if (theVisible) {
        msg << "[visible]";
    }
    if (theInherit) {
        msg << "[inherit]";
    }
    msg << "(" << appPath << ", " << argsStr << ")";

    if (!CreateProcess(appPath.c_str(), argsBuffer.data(), NULL, NULL,
                      theInherit ? TRUE : FALSE, creationFlags, NULL, NULL,
                      &startupInfo, &processInfo)) {
        msg << " failed";
        JP_THROW(SysError(msg, CreateProcess));
    }

    msg << " succeeded; PID=" << processInfo.dwProcessId;
    LOG_TRACE(msg);

    if (threadHandle) {
        *threadHandle = UniqueHandle(processInfo.hThread);
    } else {
        // Close unneeded handle immediately.
        UniqueHandle(processInfo.hThread);
    }

    if (jobHandle != NULL) {
        LOG_TRACE(tstrings::any() << "AssignProcessToJobObject(PID="
                << processInfo.dwProcessId << ")");
        if (!AssignProcessToJobObject(jobHandle, processInfo.hProcess)) {
            JP_THROW(SysError(tstrings::any() <<
                    "AssignProcessToJobObject() failed",
                    AssignProcessToJobObject));
        }
    }

    if (afterProcessCreatedCallback) {
      afterProcessCreatedCallback(processInfo.hProcess);
    }

    // Return process handle.
    return UniqueHandle(processInfo.hProcess);
}
