//===- Win32/Process.cpp - Win32 Process Implementation ------- -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file provides the Win32 specific implementation of the Process class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Allocator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/WindowsError.h"
#include <malloc.h>

// The Windows.h header must be after LLVM and standard headers.
#include "llvm/Support/Windows/WindowsSupport.h"

#include <direct.h>
#include <io.h>
#include <psapi.h>
#include <shellapi.h>

#if !defined(__MINGW32__)
 #pragma comment(lib, "psapi.lib")
 #pragma comment(lib, "shell32.lib")
#endif

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only Win32 specific code
//===          and must not be UNIX code
//===----------------------------------------------------------------------===//

#ifdef __MINGW32__
// This ban should be lifted when MinGW 1.0+ has defined this value.
#  define _HEAPOK (-2)
#endif

using namespace llvm;

// This function retrieves the page size using GetNativeSystemInfo() and is
// present solely so it can be called once to initialize the self_process member
// below.
static unsigned computePageSize() {
  // GetNativeSystemInfo() provides the physical page size which may differ
  // from GetSystemInfo() in 32-bit applications running under WOW64.
  SYSTEM_INFO info;
  GetNativeSystemInfo(&info);
  // FIXME: FileOffset in MapViewOfFile() should be aligned to not dwPageSize,
  // but dwAllocationGranularity.
  return static_cast<unsigned>(info.dwPageSize);
}

Expected<unsigned> Process::getPageSize() {
  static unsigned Ret = computePageSize();
  return Ret;
}

size_t
Process::GetMallocUsage()
{
  _HEAPINFO hinfo;
  hinfo._pentry = NULL;

  size_t size = 0;

  while (_heapwalk(&hinfo) == _HEAPOK)
    size += hinfo._size;

  return size;
}

void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time,
                           std::chrono::nanoseconds &sys_time) {
  elapsed = std::chrono::system_clock::now();;

  FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
  if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
                      &UserTime) == 0)
    return;

  user_time = toDuration(UserTime);
  sys_time = toDuration(KernelTime);
}

// Some LLVM programs such as bugpoint produce core files as a normal part of
// their operation. To prevent the disk from filling up, this configuration
// item does what's necessary to prevent their generation.
void Process::PreventCoreFiles() {
  // Windows does have the concept of core files, called minidumps.  However,
  // disabling minidumps for a particular application extends past the lifetime
  // of that application, which is the incorrect behavior for this API.
  // Additionally, the APIs require elevated privileges to disable and re-
  // enable minidumps, which makes this untenable. For more information, see
  // WerAddExcludedApplication and WerRemoveExcludedApplication (Vista and
  // later).
  //
  // Windows also has modal pop-up message boxes.  As this method is used by
  // bugpoint, preventing these pop-ups is additionally important.
  SetErrorMode(SEM_FAILCRITICALERRORS |
               SEM_NOGPFAULTERRORBOX |
               SEM_NOOPENFILEERRORBOX);

  coreFilesPrevented = true;
}

/// Returns the environment variable \arg Name's value as a string encoded in
/// UTF-8. \arg Name is assumed to be in UTF-8 encoding.
Optional<std::string> Process::GetEnv(StringRef Name) {
  // Convert the argument to UTF-16 to pass it to _wgetenv().
  SmallVector<wchar_t, 128> NameUTF16;
  if (windows::UTF8ToUTF16(Name, NameUTF16))
    return None;

  // Environment variable can be encoded in non-UTF8 encoding, and there's no
  // way to know what the encoding is. The only reliable way to look up
  // multibyte environment variable is to use GetEnvironmentVariableW().
  SmallVector<wchar_t, MAX_PATH> Buf;
  size_t Size = MAX_PATH;
  do {
    Buf.reserve(Size);
    SetLastError(NO_ERROR);
    Size =
      GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity());
    if (Size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND)
      return None;

    // Try again with larger buffer.
  } while (Size > Buf.capacity());
  Buf.set_size(Size);

  // Convert the result from UTF-16 to UTF-8.
  SmallVector<char, MAX_PATH> Res;
  if (windows::UTF16ToUTF8(Buf.data(), Size, Res))
    return None;
  return std::string(Res.data());
}

/// Perform wildcard expansion of Arg, or just push it into Args if it doesn't
/// have wildcards or doesn't match any files.
static std::error_code WildcardExpand(StringRef Arg,
                                      SmallVectorImpl<const char *> &Args,
                                      StringSaver &Saver) {
  std::error_code EC;

  // Don't expand Arg if it does not contain any wildcard characters. This is
  // the common case. Also don't wildcard expand /?. Always treat it as an
  // option.
  if (Arg.find_first_of("*?") == StringRef::npos || Arg == "/?" ||
      Arg == "-?") {
    Args.push_back(Arg.data());
    return EC;
  }

  // Convert back to UTF-16 so we can call FindFirstFileW.
  SmallVector<wchar_t, MAX_PATH> ArgW;
  EC = windows::UTF8ToUTF16(Arg, ArgW);
  if (EC)
    return EC;

  // Search for matching files.
  // FIXME:  This assumes the wildcard is only in the file name and not in the
  // directory portion of the file path.  For example, it doesn't handle
  // "*\foo.c" nor "s?c\bar.cpp".
  WIN32_FIND_DATAW FileData;
  HANDLE FindHandle = FindFirstFileW(ArgW.data(), &FileData);
  if (FindHandle == INVALID_HANDLE_VALUE) {
    Args.push_back(Arg.data());
    return EC;
  }

  // Extract any directory part of the argument.
  SmallString<MAX_PATH> Dir = Arg;
  sys::path::remove_filename(Dir);
  const int DirSize = Dir.size();

  do {
    SmallString<MAX_PATH> FileName;
    EC = windows::UTF16ToUTF8(FileData.cFileName, wcslen(FileData.cFileName),
                              FileName);
    if (EC)
      break;

    // Append FileName to Dir, and remove it afterwards.
    llvm::sys::path::append(Dir, FileName);
    Args.push_back(Saver.save(StringRef(Dir)).data());
    Dir.resize(DirSize);
  } while (FindNextFileW(FindHandle, &FileData));

  FindClose(FindHandle);
  return EC;
}

static std::error_code GetExecutableName(SmallVectorImpl<char> &Filename) {
  // The first argument may contain just the name of the executable (e.g.,
  // "clang") rather than the full path, so swap it with the full path.
  wchar_t ModuleName[MAX_PATH];
  size_t Length = ::GetModuleFileNameW(NULL, ModuleName, MAX_PATH);
  if (Length == 0 || Length == MAX_PATH) {
    return mapWindowsError(GetLastError());
  }

  // If the first argument is a shortened (8.3) name (which is possible even
  // if we got the module name), the driver will have trouble distinguishing it
  // (e.g., clang.exe v. clang++.exe), so expand it now.
  Length = GetLongPathNameW(ModuleName, ModuleName, MAX_PATH);
  if (Length == 0)
    return mapWindowsError(GetLastError());
  if (Length > MAX_PATH) {
    // We're not going to try to deal with paths longer than MAX_PATH, so we'll
    // treat this as an error.  GetLastError() returns ERROR_SUCCESS, which
    // isn't useful, so we'll hardcode an appropriate error value.
    return mapWindowsError(ERROR_INSUFFICIENT_BUFFER);
  }

  std::error_code EC = windows::UTF16ToUTF8(ModuleName, Length, Filename);
  if (EC)
    return EC;

  StringRef Base = sys::path::filename(Filename.data());
  Filename.assign(Base.begin(), Base.end());
  return std::error_code();
}

std::error_code
windows::GetCommandLineArguments(SmallVectorImpl<const char *> &Args,
                                 BumpPtrAllocator &Alloc) {
  const wchar_t *CmdW = GetCommandLineW();
  assert(CmdW);
  std::error_code EC;
  SmallString<MAX_PATH> Cmd;
  EC = windows::UTF16ToUTF8(CmdW, wcslen(CmdW), Cmd);
  if (EC)
    return EC;

  SmallVector<const char *, 20> TmpArgs;
  StringSaver Saver(Alloc);
  cl::TokenizeWindowsCommandLine(Cmd, Saver, TmpArgs, /*MarkEOLs=*/false);

  for (const char *Arg : TmpArgs) {
    EC = WildcardExpand(Arg, Args, Saver);
    if (EC)
      return EC;
  }

  SmallVector<char, MAX_PATH> Arg0(Args[0], Args[0] + strlen(Args[0]));
  SmallVector<char, MAX_PATH> Filename;
  sys::path::remove_filename(Arg0);
  EC = GetExecutableName(Filename);
  if (EC)
    return EC;
  sys::path::append(Arg0, Filename);
  Args[0] = Saver.save(Arg0).data();
  return std::error_code();
}

std::error_code Process::FixupStandardFileDescriptors() {
  return std::error_code();
}

std::error_code Process::SafelyCloseFileDescriptor(int FD) {
  if (::close(FD) < 0)
    return std::error_code(errno, std::generic_category());
  return std::error_code();
}

bool Process::StandardInIsUserInput() {
  return FileDescriptorIsDisplayed(0);
}

bool Process::StandardOutIsDisplayed() {
  return FileDescriptorIsDisplayed(1);
}

bool Process::StandardErrIsDisplayed() {
  return FileDescriptorIsDisplayed(2);
}

bool Process::FileDescriptorIsDisplayed(int fd) {
  DWORD Mode;  // Unused
  return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
}

unsigned Process::StandardOutColumns() {
  unsigned Columns = 0;
  CONSOLE_SCREEN_BUFFER_INFO csbi;
  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
    Columns = csbi.dwSize.X;
  return Columns;
}

unsigned Process::StandardErrColumns() {
  unsigned Columns = 0;
  CONSOLE_SCREEN_BUFFER_INFO csbi;
  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi))
    Columns = csbi.dwSize.X;
  return Columns;
}

// The terminal always has colors.
bool Process::FileDescriptorHasColors(int fd) {
  return FileDescriptorIsDisplayed(fd);
}

bool Process::StandardOutHasColors() {
  return FileDescriptorHasColors(1);
}

bool Process::StandardErrHasColors() {
  return FileDescriptorHasColors(2);
}

static bool UseANSI = false;
void Process::UseANSIEscapeCodes(bool enable) {
#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
  if (enable) {
    HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
    DWORD Mode;
    GetConsoleMode(Console, &Mode);
    Mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    SetConsoleMode(Console, Mode);
  }
#endif
  UseANSI = enable;
}

namespace {
class DefaultColors
{
  private:
    WORD defaultColor;
  public:
    DefaultColors()
     :defaultColor(GetCurrentColor()) {}
    static unsigned GetCurrentColor() {
      CONSOLE_SCREEN_BUFFER_INFO csbi;
      if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
        return csbi.wAttributes;
      return 0;
    }
    WORD operator()() const { return defaultColor; }
};

DefaultColors defaultColors;

WORD fg_color(WORD color) {
  return color & (FOREGROUND_BLUE | FOREGROUND_GREEN |
                  FOREGROUND_INTENSITY | FOREGROUND_RED);
}

WORD bg_color(WORD color) {
  return color & (BACKGROUND_BLUE | BACKGROUND_GREEN |
                  BACKGROUND_INTENSITY | BACKGROUND_RED);
}
}

bool Process::ColorNeedsFlush() {
  return !UseANSI;
}

const char *Process::OutputBold(bool bg) {
  if (UseANSI) return "\033[1m";

  WORD colors = DefaultColors::GetCurrentColor();
  if (bg)
    colors |= BACKGROUND_INTENSITY;
  else
    colors |= FOREGROUND_INTENSITY;
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
  return 0;
}

const char *Process::OutputColor(char code, bool bold, bool bg) {
  if (UseANSI) return colorcodes[bg?1:0][bold?1:0][code&7];

  WORD current = DefaultColors::GetCurrentColor();
  WORD colors;
  if (bg) {
    colors = ((code&1) ? BACKGROUND_RED : 0) |
      ((code&2) ? BACKGROUND_GREEN : 0 ) |
      ((code&4) ? BACKGROUND_BLUE : 0);
    if (bold)
      colors |= BACKGROUND_INTENSITY;
    colors |= fg_color(current);
  } else {
    colors = ((code&1) ? FOREGROUND_RED : 0) |
      ((code&2) ? FOREGROUND_GREEN : 0 ) |
      ((code&4) ? FOREGROUND_BLUE : 0);
    if (bold)
      colors |= FOREGROUND_INTENSITY;
    colors |= bg_color(current);
  }
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
  return 0;
}

static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) {
  CONSOLE_SCREEN_BUFFER_INFO info;
  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
  return info.wAttributes;
}

const char *Process::OutputReverse() {
  if (UseANSI) return "\033[7m";

  const WORD attributes
   = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE));

  const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
    FOREGROUND_RED | FOREGROUND_INTENSITY;
  const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
    BACKGROUND_RED | BACKGROUND_INTENSITY;
  const WORD color_mask = foreground_mask | background_mask;

  WORD new_attributes =
    ((attributes & FOREGROUND_BLUE     )?BACKGROUND_BLUE     :0) |
    ((attributes & FOREGROUND_GREEN    )?BACKGROUND_GREEN    :0) |
    ((attributes & FOREGROUND_RED      )?BACKGROUND_RED      :0) |
    ((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) |
    ((attributes & BACKGROUND_BLUE     )?FOREGROUND_BLUE     :0) |
    ((attributes & BACKGROUND_GREEN    )?FOREGROUND_GREEN    :0) |
    ((attributes & BACKGROUND_RED      )?FOREGROUND_RED      :0) |
    ((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) |
    0;
  new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask);

  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes);
  return 0;
}

const char *Process::ResetColor() {
  if (UseANSI) return "\033[0m";
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
  return 0;
}

unsigned Process::GetRandomNumber() {
  HCRYPTPROV HCPC;
  if (!::CryptAcquireContextW(&HCPC, NULL, NULL, PROV_RSA_FULL,
                              CRYPT_VERIFYCONTEXT))
    ReportLastErrorFatal("Could not acquire a cryptographic context");

  ScopedCryptContext CryptoProvider(HCPC);
  unsigned Ret;
  if (!::CryptGenRandom(CryptoProvider, sizeof(Ret),
                        reinterpret_cast<BYTE *>(&Ret)))
    ReportLastErrorFatal("Could not generate a random number");
  return Ret;
}

typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)

llvm::VersionTuple llvm::GetWindowsOSVersion() {
  HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
  if (hMod) {
    auto getVer = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
    if (getVer) {
      RTL_OSVERSIONINFOEXW info{};
      info.dwOSVersionInfoSize = sizeof(info);
      if (getVer((PRTL_OSVERSIONINFOW)&info) == STATUS_SUCCESS) {
        return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, 0,
                                  info.dwBuildNumber);
      }
    }
  }
  return llvm::VersionTuple(0, 0, 0, 0);
}

bool llvm::RunningWindows8OrGreater() {
  // Windows 8 is version 6.2, service pack 0.
  return GetWindowsOSVersion() >= llvm::VersionTuple(6, 2, 0, 0);
}
