//===-- PlatformWindows.cpp -----------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "PlatformWindows.h"

#include <cstdio>
#include <optional>
#if defined(_WIN32)
#include "lldb/Host/windows/windows.h"
#include <winsock2.h>
#endif

#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Status.h"

#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/ConvertUTF.h"

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE(PlatformWindows)

static uint32_t g_initialize_count = 0;

PlatformSP PlatformWindows::CreateInstance(bool force,
                                           const lldb_private::ArchSpec *arch) {
  // The only time we create an instance is when we are creating a remote
  // windows platform
  const bool is_host = false;

  bool create = force;
  if (!create && arch && arch->IsValid()) {
    const llvm::Triple &triple = arch->GetTriple();
    switch (triple.getVendor()) {
    case llvm::Triple::PC:
      create = true;
      break;

    case llvm::Triple::UnknownVendor:
      create = !arch->TripleVendorWasSpecified();
      break;

    default:
      break;
    }

    if (create) {
      switch (triple.getOS()) {
      case llvm::Triple::Win32:
        break;

      case llvm::Triple::UnknownOS:
        create = arch->TripleOSWasSpecified();
        break;

      default:
        create = false;
        break;
      }
    }
  }
  if (create)
    return PlatformSP(new PlatformWindows(is_host));
  return PlatformSP();
}

llvm::StringRef PlatformWindows::GetPluginDescriptionStatic(bool is_host) {
  return is_host ? "Local Windows user platform plug-in."
                 : "Remote Windows user platform plug-in.";
}

void PlatformWindows::Initialize() {
  Platform::Initialize();

  if (g_initialize_count++ == 0) {
#if defined(_WIN32)
    // Force a host flag to true for the default platform object.
    PlatformSP default_platform_sp(new PlatformWindows(true));
    default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
    Platform::SetHostPlatform(default_platform_sp);
#endif
    PluginManager::RegisterPlugin(
        PlatformWindows::GetPluginNameStatic(false),
        PlatformWindows::GetPluginDescriptionStatic(false),
        PlatformWindows::CreateInstance);
  }
}

void PlatformWindows::Terminate() {
  if (g_initialize_count > 0) {
    if (--g_initialize_count == 0) {
      PluginManager::UnregisterPlugin(PlatformWindows::CreateInstance);
    }
  }

  Platform::Terminate();
}

/// Default Constructor
PlatformWindows::PlatformWindows(bool is_host) : RemoteAwarePlatform(is_host) {
  const auto &AddArch = [&](const ArchSpec &spec) {
    if (llvm::any_of(m_supported_architectures, [spec](const ArchSpec &rhs) {
          return spec.IsExactMatch(rhs);
        }))
      return;
    if (spec.IsValid())
      m_supported_architectures.push_back(spec);
  };
  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind32));
  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind64));
}

Status PlatformWindows::ConnectRemote(Args &args) {
  Status error;
  if (IsHost()) {
    error = Status::FromErrorStringWithFormatv(
        "can't connect to the host platform '{0}', always connected",
        GetPluginName());
  } else {
    if (!m_remote_platform_sp)
      m_remote_platform_sp =
          platform_gdb_server::PlatformRemoteGDBServer::CreateInstance(
              /*force=*/true, nullptr);

    if (m_remote_platform_sp) {
      if (error.Success()) {
        if (m_remote_platform_sp) {
          error = m_remote_platform_sp->ConnectRemote(args);
        } else {
          error = Status::FromErrorString(
              "\"platform connect\" takes a single argument: <connect-url>");
        }
      }
    } else
      error = Status::FromErrorString(
          "failed to create a 'remote-gdb-server' platform");

    if (error.Fail())
      m_remote_platform_sp.reset();
  }

  return error;
}

uint32_t PlatformWindows::DoLoadImage(Process *process,
                                      const FileSpec &remote_file,
                                      const std::vector<std::string> *paths,
                                      Status &error, FileSpec *loaded_image) {
  DiagnosticManager diagnostics;

  if (loaded_image)
    loaded_image->Clear();

  ThreadSP thread = process->GetThreadList().GetExpressionExecutionThread();
  if (!thread) {
    error = Status::FromErrorString(
        "LoadLibrary error: no thread available to invoke LoadLibrary");
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  ExecutionContext context;
  thread->CalculateExecutionContext(context);

  Status status;
  UtilityFunction *loader =
      process->GetLoadImageUtilityFunction(this, [&]() -> std::unique_ptr<UtilityFunction> {
        return MakeLoadImageUtilityFunction(context, status);
      });
  if (loader == nullptr)
    return LLDB_INVALID_IMAGE_TOKEN;

  FunctionCaller *invocation = loader->GetFunctionCaller();
  if (!invocation) {
    error = Status::FromErrorString(
        "LoadLibrary error: could not get function caller");
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  /* Convert name */
  llvm::SmallVector<llvm::UTF16, 261> name;
  if (!llvm::convertUTF8ToUTF16String(remote_file.GetPath(), name)) {
    error = Status::FromErrorString(
        "LoadLibrary error: could not convert path to UCS2");
    return LLDB_INVALID_IMAGE_TOKEN;
  }
  name.emplace_back(L'\0');

  /* Inject name paramter into inferior */
  lldb::addr_t injected_name =
      process->AllocateMemory(name.size() * sizeof(llvm::UTF16),
                              ePermissionsReadable | ePermissionsWritable,
                              status);
  if (injected_name == LLDB_INVALID_ADDRESS) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: unable to allocate memory for name: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  auto name_cleanup = llvm::make_scope_exit([process, injected_name]() {
    process->DeallocateMemory(injected_name);
  });

  process->WriteMemory(injected_name, name.data(),
                       name.size() * sizeof(llvm::UTF16), status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: unable to write name: %s", status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  /* Inject paths parameter into inferior */
  lldb::addr_t injected_paths{0x0};
  std::optional<llvm::detail::scope_exit<std::function<void()>>> paths_cleanup;
  if (paths) {
    llvm::SmallVector<llvm::UTF16, 261> search_paths;

    for (const auto &path : *paths) {
      if (path.empty())
        continue;

      llvm::SmallVector<llvm::UTF16, 261> buffer;
      if (!llvm::convertUTF8ToUTF16String(path, buffer))
        continue;

      search_paths.append(std::begin(buffer), std::end(buffer));
      search_paths.emplace_back(L'\0');
    }
    search_paths.emplace_back(L'\0');

    injected_paths =
        process->AllocateMemory(search_paths.size() * sizeof(llvm::UTF16),
                                ePermissionsReadable | ePermissionsWritable,
                                status);
    if (injected_paths == LLDB_INVALID_ADDRESS) {
      error = Status::FromErrorStringWithFormat(
          "LoadLibrary error: unable to allocate memory for paths: %s",
          status.AsCString());
      return LLDB_INVALID_IMAGE_TOKEN;
    }

    paths_cleanup.emplace([process, injected_paths]() {
      process->DeallocateMemory(injected_paths);
    });

    process->WriteMemory(injected_paths, search_paths.data(),
                         search_paths.size() * sizeof(llvm::UTF16), status);
    if (status.Fail()) {
      error = Status::FromErrorStringWithFormat(
          "LoadLibrary error: unable to write paths: %s", status.AsCString());
      return LLDB_INVALID_IMAGE_TOKEN;
    }
  }

  /* Inject wszModulePath into inferior */
  // FIXME(compnerd) should do something better for the length?
  // GetModuleFileNameA is likely limited to PATH_MAX rather than the NT path
  // limit.
  unsigned injected_length = 261;

  lldb::addr_t injected_module_path =
      process->AllocateMemory(injected_length + 1,
                              ePermissionsReadable | ePermissionsWritable,
                              status);
  if (injected_module_path == LLDB_INVALID_ADDRESS) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: unable to allocate memory for module location: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  auto injected_module_path_cleanup =
      llvm::make_scope_exit([process, injected_module_path]() {
    process->DeallocateMemory(injected_module_path);
  });

  /* Inject __lldb_LoadLibraryResult into inferior */
  const uint32_t word_size = process->GetAddressByteSize();
  lldb::addr_t injected_result =
      process->AllocateMemory(3 * word_size,
                              ePermissionsReadable | ePermissionsWritable,
                              status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not allocate memory for result: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  auto result_cleanup = llvm::make_scope_exit([process, injected_result]() {
    process->DeallocateMemory(injected_result);
  });

  process->WritePointerToMemory(injected_result + word_size,
                                injected_module_path, status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not initialize result: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  // XXX(compnerd) should we use the compiler to get the sizeof(unsigned)?
  process->WriteScalarToMemory(injected_result + 2 * word_size,
                               Scalar{injected_length}, sizeof(unsigned),
                               status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not initialize result: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  /* Setup Formal Parameters */
  ValueList parameters = invocation->GetArgumentValues();
  parameters.GetValueAtIndex(0)->GetScalar() = injected_name;
  parameters.GetValueAtIndex(1)->GetScalar() = injected_paths;
  parameters.GetValueAtIndex(2)->GetScalar() = injected_result;

  lldb::addr_t injected_parameters = LLDB_INVALID_ADDRESS;
  diagnostics.Clear();
  if (!invocation->WriteFunctionArguments(context, injected_parameters,
                                          parameters, diagnostics)) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: unable to write function parameters: %s",
        diagnostics.GetString().c_str());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  auto parameter_cleanup =
      llvm::make_scope_exit([invocation, &context, injected_parameters]() {
        invocation->DeallocateFunctionResults(context, injected_parameters);
      });

  TypeSystemClangSP scratch_ts_sp =
      ScratchTypeSystemClang::GetForTarget(process->GetTarget());
  if (!scratch_ts_sp) {
    error = Status::FromErrorString(
        "LoadLibrary error: unable to get (clang) type system");
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  /* Setup Return Type */
  CompilerType VoidPtrTy =
      scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();

  Value value;
  value.SetCompilerType(VoidPtrTy);

  /* Invoke expression */
  EvaluateExpressionOptions options;
  options.SetExecutionPolicy(eExecutionPolicyAlways);
  options.SetLanguage(eLanguageTypeC_plus_plus);
  options.SetIgnoreBreakpoints(true);
  options.SetUnwindOnError(true);
  // LoadLibraryEx{A,W}/FreeLibrary cannot raise exceptions which we can handle.
  // They may potentially throw SEH exceptions which we do not know how to
  // handle currently.
  options.SetTrapExceptions(false);
  options.SetTimeout(process->GetUtilityExpressionTimeout());
  options.SetIsForUtilityExpr(true);

  ExpressionResults result =
      invocation->ExecuteFunction(context, &injected_parameters, options,
                                  diagnostics, value);
  if (result != eExpressionCompleted) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: failed to execute LoadLibrary helper: %s",
        diagnostics.GetString().c_str());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  /* Read result */
  lldb::addr_t token = process->ReadPointerFromMemory(injected_result, status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not read the result: %s", status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  if (!token) {
    // XXX(compnerd) should we use the compiler to get the sizeof(unsigned)?
    uint64_t error_code =
        process->ReadUnsignedIntegerFromMemory(injected_result + 2 * word_size + sizeof(unsigned),
                                               word_size, 0, status);
    if (status.Fail()) {
      error = Status::FromErrorStringWithFormat(
          "LoadLibrary error: could not read error status: %s",
          status.AsCString());
      return LLDB_INVALID_IMAGE_TOKEN;
    }

    error = Status::FromErrorStringWithFormat("LoadLibrary Error: %" PRIu64,
                                              error_code);
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  std::string module_path;
  process->ReadCStringFromMemory(injected_module_path, module_path, status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not read module path: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  if (loaded_image)
    loaded_image->SetFile(module_path, llvm::sys::path::Style::native);
  return process->AddImageToken(token);
}

Status PlatformWindows::UnloadImage(Process *process, uint32_t image_token) {
  const addr_t address = process->GetImagePtrFromToken(image_token);
  if (address == LLDB_INVALID_IMAGE_TOKEN)
    return Status::FromErrorString("invalid image token");

  StreamString expression;
  expression.Printf("FreeLibrary((HMODULE)0x%" PRIx64 ")", address);

  ValueObjectSP value;
  Status result =
      EvaluateLoaderExpression(process, expression.GetData(), value);
  if (result.Fail())
    return result;

  if (value->GetError().Fail())
    return value->GetError().Clone();

  Scalar scalar;
  if (value->ResolveValue(scalar)) {
    if (scalar.UInt(1))
      return Status::FromErrorStringWithFormat("expression failed: \"%s\"",
                                               expression.GetData());
    process->ResetImageToken(image_token);
  }

  return Status();
}

Status PlatformWindows::DisconnectRemote() {
  Status error;

  if (IsHost()) {
    error = Status::FromErrorStringWithFormatv(
        "can't disconnect from the host platform '{0}', always connected",
        GetPluginName());
  } else {
    if (m_remote_platform_sp)
      error = m_remote_platform_sp->DisconnectRemote();
    else
      error =
          Status::FromErrorString("the platform is not currently connected");
  }
  return error;
}

ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info,
                                        Debugger &debugger, Target &target,
                                        Status &error) {
  // Windows has special considerations that must be followed when launching or
  // attaching to a process.  The key requirement is that when launching or
  // attaching to a process, you must do it from the same the thread that will
  // go into a permanent loop which will then receive debug events from the
  // process.  In particular, this means we can't use any of LLDB's generic
  // mechanisms to do it for us, because it doesn't have the special knowledge
  // required for setting up the background thread or passing the right flags.
  //
  // Another problem is that LLDB's standard model for debugging a process
  // is to first launch it, have it stop at the entry point, and then attach to
  // it.  In Windows this doesn't quite work, you have to specify as an
  // argument to CreateProcess() that you're going to debug the process.  So we
  // override DebugProcess here to handle this.  Launch operations go directly
  // to the process plugin, and attach operations almost go directly to the
  // process plugin (but we hijack the events first).  In essence, we
  // encapsulate all the logic of Launching and Attaching in the process
  // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to
  // the process plugin.

  if (IsRemote()) {
    if (m_remote_platform_sp)
      return m_remote_platform_sp->DebugProcess(launch_info, debugger, target,
                                                error);
    else
      error =
          Status::FromErrorString("the platform is not currently connected");
  }

  if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
    // This is a process attach.  Don't need to launch anything.
    ProcessAttachInfo attach_info(launch_info);
    return Attach(attach_info, debugger, &target, error);
  }

  ProcessSP process_sp =
      target.CreateProcess(launch_info.GetListener(),
                           launch_info.GetProcessPluginName(), nullptr, false);

  process_sp->HijackProcessEvents(launch_info.GetHijackListener());

  // We need to launch and attach to the process.
  launch_info.GetFlags().Set(eLaunchFlagDebug);
  if (process_sp)
    error = process_sp->Launch(launch_info);

  return process_sp;
}

lldb::ProcessSP PlatformWindows::Attach(ProcessAttachInfo &attach_info,
                                        Debugger &debugger, Target *target,
                                        Status &error) {
  error.Clear();
  lldb::ProcessSP process_sp;
  if (!IsHost()) {
    if (m_remote_platform_sp)
      process_sp =
          m_remote_platform_sp->Attach(attach_info, debugger, target, error);
    else
      error =
          Status::FromErrorString("the platform is not currently connected");
    return process_sp;
  }

  if (target == nullptr) {
    TargetSP new_target_sp;
    FileSpec emptyFileSpec;
    ArchSpec emptyArchSpec;

    error = debugger.GetTargetList().CreateTarget(
        debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
    target = new_target_sp.get();
  }

  if (!target || error.Fail())
    return process_sp;

  process_sp =
      target->CreateProcess(attach_info.GetListenerForProcess(debugger),
                            attach_info.GetProcessPluginName(), nullptr, false);

  process_sp->HijackProcessEvents(attach_info.GetHijackListener());
  if (process_sp)
    error = process_sp->Attach(attach_info);

  return process_sp;
}

void PlatformWindows::GetStatus(Stream &strm) {
  Platform::GetStatus(strm);

#ifdef _WIN32
  llvm::VersionTuple version = HostInfo::GetOSVersion();
  strm << "      Host: Windows " << version.getAsString() << '\n';
#endif
}

bool PlatformWindows::CanDebugProcess() { return true; }

ConstString PlatformWindows::GetFullNameForDylib(ConstString basename) {
  if (basename.IsEmpty())
    return basename;

  StreamString stream;
  stream.Printf("%s.dll", basename.GetCString());
  return ConstString(stream.GetString());
}

size_t
PlatformWindows::GetSoftwareBreakpointTrapOpcode(Target &target,
                                                 BreakpointSite *bp_site) {
  ArchSpec arch = target.GetArchitecture();
  assert(arch.IsValid());
  const uint8_t *trap_opcode = nullptr;
  size_t trap_opcode_size = 0;

  switch (arch.GetMachine()) {
  case llvm::Triple::aarch64: {
    static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000
    trap_opcode = g_aarch64_opcode;
    trap_opcode_size = sizeof(g_aarch64_opcode);

    if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
      return trap_opcode_size;
    return 0;
  } break;

  case llvm::Triple::arm:
  case llvm::Triple::thumb: {
    static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
    trap_opcode = g_thumb_opcode;
    trap_opcode_size = sizeof(g_thumb_opcode);

    if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
      return trap_opcode_size;
    return 0;
  } break;

  default:
    return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
  }
}

std::unique_ptr<UtilityFunction>
PlatformWindows::MakeLoadImageUtilityFunction(ExecutionContext &context,
                                              Status &status) {
  // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
  static constexpr const char kLoaderDecls[] = R"(
extern "C" {
// errhandlingapi.h

// `LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS`
//
// Directories in the standard search path are not searched. This value cannot
// be combined with `LOAD_WITH_ALTERED_SEARCH_PATH`.
//
// This value represents the recommended maximum number of directories an
// application should include in its DLL search path.
#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000

// WINBASEAPI DWORD WINAPI GetLastError(VOID);
/* __declspec(dllimport) */ uint32_t __stdcall GetLastError();

// libloaderapi.h

// WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
/* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);

// WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
/* __declspec(dllimport) */ int __stdcall FreeModule(void *hLibModule);

// WINBASEAPI DWORD WINAPI GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
/* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, uint32_t);

// WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
/* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);

// corecrt_wstring.h

// _ACRTIMP size_t __cdecl wcslen(wchar_t const *_String);
/* __declspec(dllimport) */ size_t __cdecl wcslen(const wchar_t *);

// lldb specific code

struct __lldb_LoadLibraryResult {
  void *ImageBase;
  char *ModulePath;
  unsigned Length;
  unsigned ErrorCode;
};

_Static_assert(sizeof(struct __lldb_LoadLibraryResult) <= 3 * sizeof(void *),
               "__lldb_LoadLibraryResult size mismatch");

void * __lldb_LoadLibraryHelper(const wchar_t *name, const wchar_t *paths,
                                __lldb_LoadLibraryResult *result) {
  for (const wchar_t *path = paths; path && *path; ) {
    (void)AddDllDirectory(path);
    path += wcslen(path) + 1;
  }

  result->ImageBase = LoadLibraryExW(name, nullptr,
                                     LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
  if (result->ImageBase == nullptr)
    result->ErrorCode = GetLastError();
  else
    result->Length = GetModuleFileNameA(result->ImageBase, result->ModulePath,
                                        result->Length);

  return result->ImageBase;
}
}
  )";

  static constexpr const char kName[] = "__lldb_LoadLibraryHelper";

  ProcessSP process = context.GetProcessSP();
  Target &target = process->GetTarget();

  auto function = target.CreateUtilityFunction(std::string{kLoaderDecls}, kName,
                                               eLanguageTypeC_plus_plus,
                                               context);
  if (!function) {
    std::string error = llvm::toString(function.takeError());
    status = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not create utility function: %s",
        error.c_str());
    return nullptr;
  }

  TypeSystemClangSP scratch_ts_sp =
      ScratchTypeSystemClang::GetForTarget(target);
  if (!scratch_ts_sp)
    return nullptr;

  CompilerType VoidPtrTy =
      scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
  CompilerType WCharPtrTy =
      scratch_ts_sp->GetBasicType(eBasicTypeWChar).GetPointerType();

  ValueList parameters;

  Value value;
  value.SetValueType(Value::ValueType::Scalar);

  value.SetCompilerType(WCharPtrTy);
  parameters.PushValue(value);  // name
  parameters.PushValue(value);  // paths

  value.SetCompilerType(VoidPtrTy);
  parameters.PushValue(value);  // result

  Status error;
  std::unique_ptr<UtilityFunction> utility{std::move(*function)};
  utility->MakeFunctionCaller(VoidPtrTy, parameters, context.GetThreadSP(),
                              error);
  if (error.Fail()) {
    status = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not create function caller: %s",
        error.AsCString());
    return nullptr;
  }

  if (!utility->GetFunctionCaller()) {
    status = Status::FromErrorString(
        "LoadLibrary error: could not get function caller");
    return nullptr;
  }

  return utility;
}

Status PlatformWindows::EvaluateLoaderExpression(Process *process,
                                                 const char *expression,
                                                 ValueObjectSP &value) {
  // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
  static constexpr const char kLoaderDecls[] = R"(
extern "C" {
// libloaderapi.h

// WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
/* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);

// WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
/* __declspec(dllimport) */ int __stdcall FreeModule(void *);

// WINBASEAPI DWORD WINAPI GetModuleFileNameA(HMODULE, LPSTR, DWORD);
/* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, uint32_t);

// WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
/* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
}
  )";

  if (DynamicLoader *loader = process->GetDynamicLoader()) {
    Status result = loader->CanLoadImage();
    if (result.Fail())
      return result;
  }

  ThreadSP thread = process->GetThreadList().GetExpressionExecutionThread();
  if (!thread)
    return Status::FromErrorString("selected thread is invalid");

  StackFrameSP frame = thread->GetStackFrameAtIndex(0);
  if (!frame)
    return Status::FromErrorString("frame 0 is invalid");

  ExecutionContext context;
  frame->CalculateExecutionContext(context);

  EvaluateExpressionOptions options;
  options.SetUnwindOnError(true);
  options.SetIgnoreBreakpoints(true);
  options.SetExecutionPolicy(eExecutionPolicyAlways);
  options.SetLanguage(eLanguageTypeC_plus_plus);
  // LoadLibraryEx{A,W}/FreeLibrary cannot raise exceptions which we can handle.
  // They may potentially throw SEH exceptions which we do not know how to
  // handle currently.
  options.SetTrapExceptions(false);
  options.SetTimeout(process->GetUtilityExpressionTimeout());

  Status error;
  ExpressionResults result = UserExpression::Evaluate(
      context, options, expression, kLoaderDecls, value, error);
  if (result != eExpressionCompleted)
    return error;

  if (value->GetError().Fail())
    return value->GetError().Clone();

  return Status();
}
