// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "include/bin/native_assets_api.h"

#include <cstring>

#include "platform/globals.h"
#include "platform/utils.h"

#if defined(DART_HOST_OS_WINDOWS)
#include <Psapi.h>
#include <Windows.h>
#include <combaseapi.h>
#include <stdio.h>
#include <tchar.h>
#endif
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) ||              \
    defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
#include <dlfcn.h>
#endif

#include "bin/uri.h"

namespace dart {
namespace bin {

#define SET_ERROR_MSG(error_msg, format, ...)                                  \
  intptr_t len = snprintf(nullptr, 0, format, ##__VA_ARGS__);                  \
  char* msg = reinterpret_cast<char*>(malloc(len + 1));                        \
  snprintf(msg, len + 1, format, ##__VA_ARGS__);                               \
  *error_msg = msg

#if defined(DART_HOST_OS_WINDOWS)
// Replaces back slashes with forward slashes in place.
static void ReplaceBackSlashes(char* cstr) {
  const intptr_t length = strlen(cstr);
  for (int i = 0; i < length; i++) {
    cstr[i] = cstr[i] == '\\' ? '/' : cstr[i];
  }
}

// Replaces forward slashes with back slashes in place.
static void ReplaceForwardSlashes(char* cstr) {
  const intptr_t length = strlen(cstr);
  for (int i = 0; i < length; i++) {
    cstr[i] = cstr[i] == '/' ? '\\' : cstr[i];
  }
}
#endif

// If an error occurs populates |error| (if provided) with an error message
// (caller must free this message when it is no longer needed).
static void* LoadDynamicLibrary(const char* library_file,
                                bool search_dll_load_dir = false,
                                char** error = nullptr) {
  char* utils_error = nullptr;
  void* handle = Utils::LoadDynamicLibrary(library_file, search_dll_load_dir,
                                           &utils_error);
  if (utils_error != nullptr) {
    if (error != nullptr) {
      SET_ERROR_MSG(error, "Failed to load dynamic library '%s': %s",
                    library_file != nullptr ? library_file : "<process>",
                    utils_error);
    }
    free(utils_error);
  }
  return handle;
}

#if defined(DART_HOST_OS_WINDOWS)
// On windows, nullptr signals trying a lookup in all loaded modules.
const nullptr_t kWindowsDynamicLibraryProcessPtr = nullptr;
#endif

static void WrapError(const char* path, char** error) {
  if (*error != nullptr) {
    char* inner_error = *error;
    SET_ERROR_MSG(error, "Failed to load dynamic library '%s': %s", path,
                  inner_error);
    free(inner_error);
  }
}

static void WrapErrorRelative(const char* path,
                              const char* base_path,
                              char** error) {
  if (*error != nullptr) {
    char* inner_error = *error;
    SET_ERROR_MSG(error,
                  "Failed to load dynamic library '%s' relative to '%s': %s",
                  path, base_path, inner_error);
    free(inner_error);
  }
}

void* NativeAssets::DlopenAbsolute(const char* path, char** error) {
  // If we'd want to be strict, it should not take into account include paths.
  void* handle =
      LoadDynamicLibrary(path, /* search_dll_load_dir= */ true, error);
  WrapError(path, error);
  return handle;
}

void* NativeAssets::DlopenRelative(const char* path,
                                   const char* base_path,
                                   char** error) {
  if (base_path == nullptr) {
    SET_ERROR_MSG(
        error, "Failed to resolve relative path '%s', no base path provided.",
        path);
    return nullptr;
  }
  void* handle = nullptr;

#if defined(DART_HOST_OS_WINDOWS)
  char* path_copy = strdup(path);
  char* base_path_copy = strdup(base_path);
  ReplaceBackSlashes(path_copy);
  ReplaceBackSlashes(base_path_copy);
  auto target_path = ResolvePath(path_copy, base_path_copy);
  free(path_copy);
  free(base_path_copy);
#else
  auto target_path = ResolvePath(path, base_path);
#endif
  if (!target_path) {
    SET_ERROR_MSG(error, "Failed to resolve '%s' relative to '%s'.", path,
                  base_path);
  } else {
#if defined(DART_HOST_OS_WINDOWS)
    ReplaceForwardSlashes(target_path.get());
#endif
    handle = LoadDynamicLibrary(target_path.get(),
                                /* search_dll_load_dir= */ true, error);
  }
  WrapErrorRelative(path, base_path, error);
  return handle;
}

void* NativeAssets::DlopenSystem(const char* path, char** error) {
  // Should take into account LD_PATH etc.
  void* handle =
      LoadDynamicLibrary(path, /* search_dll_load_dir= */ false, error);
  WrapError(path, error);
  return handle;
}

void* NativeAssets::DlopenProcess(char** error) {
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) ||              \
    defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
  return RTLD_DEFAULT;
#else
  return kWindowsDynamicLibraryProcessPtr;
#endif
}

void* NativeAssets::DlopenExecutable(char** error) {
  return LoadDynamicLibrary(nullptr, /* search_dll_load_dir= */ false, error);
}

#if defined(DART_HOST_OS_WINDOWS)
void* co_task_mem_allocated = nullptr;

// If an error occurs populates |error| with an error message
// (caller must free this message when it is no longer needed).
void* LookupSymbolInProcess(const char* symbol, char** error) {
  // Force loading ole32.dll.
  if (co_task_mem_allocated == nullptr) {
    co_task_mem_allocated = CoTaskMemAlloc(sizeof(intptr_t));
    CoTaskMemFree(co_task_mem_allocated);
  }

  HANDLE current_process =
      OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE,
                  GetCurrentProcessId());
  if (current_process == nullptr) {
    SET_ERROR_MSG(error, "Failed to open current process.");
    return nullptr;
  }

  HMODULE modules[1024];
  DWORD cb_needed;
  if (EnumProcessModules(current_process, modules, sizeof(modules),
                         &cb_needed) != 0) {
    for (intptr_t i = 0; i < (cb_needed / sizeof(HMODULE)); i++) {
      if (auto result =
              reinterpret_cast<void*>(GetProcAddress(modules[i], symbol))) {
        CloseHandle(current_process);
        return result;
      }
    }
  }
  CloseHandle(current_process);

  SET_ERROR_MSG(
      error, "None of the loaded modules contained the requested symbol '%s'.",
      symbol);
  return nullptr;
}
#endif

// If an error occurs populates |error| with an error message
// (caller must free this message when it is no longer needed).
static void* ResolveSymbol(void* handle, const char* symbol, char** error) {
#if defined(DART_HOST_OS_WINDOWS)
  if (handle == kWindowsDynamicLibraryProcessPtr) {
    return LookupSymbolInProcess(symbol, error);
  }
#endif
  return Utils::ResolveSymbolInDynamicLibrary(handle, symbol, error);
}

void* NativeAssets::Dlsym(void* handle, const char* symbol, char** error) {
  void* const result = ResolveSymbol(handle, symbol, error);
  if (*error != nullptr) {
    char* inner_error = *error;
    SET_ERROR_MSG(error, "Failed to lookup symbol '%s': %s", symbol,
                  inner_error);
    free(inner_error);
  }
  return result;
}

void NativeAssets::Dlclose(void* handle, char** error) {
  Utils::UnloadDynamicLibrary(handle, error);
}

}  // namespace bin
}  // namespace dart
