This commit is contained in:
Andrew Stanton-Nurse 2015-11-04 09:00:17 -08:00
parent b1d3ef4b75
commit d55f9a6e89
12 changed files with 749 additions and 749 deletions

View file

@ -6,15 +6,15 @@
struct arguments_t struct arguments_t
{ {
trace::level_t trace_level; trace::level_t trace_level;
pal::string_t own_path; pal::string_t own_path;
pal::string_t managed_application; pal::string_t managed_application;
pal::string_t clr_path; pal::string_t clr_path;
int app_argc; int app_argc;
const pal::char_t** app_argv; const pal::char_t** app_argv;
arguments_t(); arguments_t();
}; };
bool parse_arguments(const int argc, const pal::char_t* argv[], arguments_t& args); bool parse_arguments(const int argc, const pal::char_t* argv[], arguments_t& args);

View file

@ -6,31 +6,31 @@
namespace coreclr namespace coreclr
{ {
typedef void* host_handle_t; typedef void* host_handle_t;
typedef unsigned int domain_id_t; typedef unsigned int domain_id_t;
bool bind(const pal::string_t& libcoreclr_path); bool bind(const pal::string_t& libcoreclr_path);
void unload(); void unload();
pal::hresult_t initialize( pal::hresult_t initialize(
const char* exe_path, const char* exe_path,
const char* app_domain_friendly_name, const char* app_domain_friendly_name,
const char** property_keys, const char** property_keys,
const char** property_values, const char** property_values,
int property_count, int property_count,
host_handle_t* host_handle, host_handle_t* host_handle,
domain_id_t* domain_id); domain_id_t* domain_id);
pal::hresult_t shutdown(host_handle_t host_handle, domain_id_t domain_id); pal::hresult_t shutdown(host_handle_t host_handle, domain_id_t domain_id);
pal::hresult_t execute_assembly( pal::hresult_t execute_assembly(
host_handle_t host_handle, host_handle_t host_handle,
domain_id_t domain_id, domain_id_t domain_id,
int argc, int argc,
const char** argv, const char** argv,
const char* managed_assembly_path, const char* managed_assembly_path,
unsigned int* exit_code); unsigned int* exit_code);
}; };
#endif #endif

View file

@ -59,52 +59,52 @@ namespace pal
{ {
#if defined(_WIN32) #if defined(_WIN32)
typedef wchar_t char_t; typedef wchar_t char_t;
typedef std::wstring string_t; typedef std::wstring string_t;
typedef std::wstringstream stringstream_t; typedef std::wstringstream stringstream_t;
typedef std::ifstream ifstream_t; typedef std::ifstream ifstream_t;
typedef HRESULT hresult_t; typedef HRESULT hresult_t;
typedef HMODULE dll_t; typedef HMODULE dll_t;
typedef FARPROC proc_t; typedef FARPROC proc_t;
inline int strcmp(const char_t* str1, const char_t* str2) { return ::wcscmp(str1, str2); } inline int strcmp(const char_t* str1, const char_t* str2) { return ::wcscmp(str1, str2); }
inline int strcasecmp(const char_t* str1, const char_t* str2) { return ::_wcsicmp(str1, str2); } inline int strcasecmp(const char_t* str1, const char_t* str2) { return ::_wcsicmp(str1, str2); }
inline size_t strlen(const char_t* str) { return ::wcslen(str); } inline size_t strlen(const char_t* str) { return ::wcslen(str); }
inline void err_vprintf(const char_t* format, va_list vl) { ::vfwprintf(stderr, format, vl); ::fputws(_X("\r\n"), stderr); } inline void err_vprintf(const char_t* format, va_list vl) { ::vfwprintf(stderr, format, vl); ::fputws(_X("\r\n"), stderr); }
pal::string_t to_palstring(const std::string& str); pal::string_t to_palstring(const std::string& str);
std::string to_stdstring(const pal::string_t& str); std::string to_stdstring(const pal::string_t& str);
#else #else
typedef char char_t; typedef char char_t;
typedef std::string string_t; typedef std::string string_t;
typedef std::stringstream stringstream_t; typedef std::stringstream stringstream_t;
typedef std::ifstream ifstream_t; typedef std::ifstream ifstream_t;
typedef long hresult_t; typedef long hresult_t;
typedef void* dll_t; typedef void* dll_t;
typedef void* proc_t; typedef void* proc_t;
inline int strcmp(const char_t* str1, const char_t* str2) { return ::strcmp(str1, str2); } inline int strcmp(const char_t* str1, const char_t* str2) { return ::strcmp(str1, str2); }
inline int strcasecmp(const char_t* str1, const char_t* str2) { return ::strcasecmp(str1, str2); } inline int strcasecmp(const char_t* str1, const char_t* str2) { return ::strcasecmp(str1, str2); }
inline size_t strlen(const char_t* str) { return ::strlen(str); } inline size_t strlen(const char_t* str) { return ::strlen(str); }
inline void err_vprintf(const char_t* format, va_list vl) { ::vfprintf(stderr, format, vl); ::fputc('\n', stderr); } inline void err_vprintf(const char_t* format, va_list vl) { ::vfprintf(stderr, format, vl); ::fputc('\n', stderr); }
inline pal::string_t to_palstring(const std::string& str) { return str; } inline pal::string_t to_palstring(const std::string& str) { return str; }
inline std::string to_stdstring(const pal::string_t& str) { return str; } inline std::string to_stdstring(const pal::string_t& str) { return str; }
#endif #endif
bool realpath(string_t& path); bool realpath(string_t& path);
bool file_exists(const string_t& path); bool file_exists(const string_t& path);
std::vector<pal::string_t> readdir(const string_t& path); std::vector<pal::string_t> readdir(const string_t& path);
bool get_own_executable_path(string_t& recv); bool get_own_executable_path(string_t& recv);
bool getenv(const char_t* name, string_t& recv); bool getenv(const char_t* name, string_t& recv);
bool get_default_packages_directory(string_t& recv); bool get_default_packages_directory(string_t& recv);
bool is_path_rooted(const string_t& path); bool is_path_rooted(const string_t& path);
int xtoi(const char_t* input); int xtoi(const char_t* input);
bool load_library(const char_t* path, dll_t& dll); bool load_library(const char_t* path, dll_t& dll);
proc_t get_symbol(dll_t library, const char* name); proc_t get_symbol(dll_t library, const char* name);
void unload_library(dll_t library); void unload_library(dll_t library);
} }
#endif // PAL_H #endif // PAL_H

View file

@ -8,31 +8,31 @@
struct tpaentry_t struct tpaentry_t
{ {
pal::string_t library_type; pal::string_t library_type;
pal::string_t library_name; pal::string_t library_name;
pal::string_t library_version; pal::string_t library_version;
pal::string_t library_hash; pal::string_t library_hash;
pal::string_t asset_type; pal::string_t asset_type;
pal::string_t asset_name; pal::string_t asset_name;
pal::string_t relative_path; pal::string_t relative_path;
}; };
class tpafile class tpafile
{ {
public: public:
bool load(pal::string_t path); bool load(pal::string_t path);
void add_from_local_dir(const pal::string_t& dir); void add_from_local_dir(const pal::string_t& dir);
void add_package_dir(pal::string_t dir); void add_package_dir(pal::string_t dir);
void add_native_search_path(pal::string_t dir); void add_native_search_path(pal::string_t dir);
void write_tpa_list(pal::string_t& output); void write_tpa_list(pal::string_t& output);
void write_native_paths(pal::string_t& output); void write_native_paths(pal::string_t& output);
private: private:
std::vector<tpaentry_t> m_entries; std::vector<tpaentry_t> m_entries;
std::vector<pal::string_t> m_native_search_paths; std::vector<pal::string_t> m_native_search_paths;
std::vector<pal::string_t> m_package_search_paths; std::vector<pal::string_t> m_package_search_paths;
}; };
#endif // TPAFILE_H #endif // TPAFILE_H

View file

@ -5,20 +5,20 @@
namespace trace namespace trace
{ {
enum class level_t enum class level_t
{ {
Error = 0, Error = 0,
Warning = 1, Warning = 1,
Info = 2, Info = 2,
Verbose = 3 Verbose = 3
}; };
void set_level(level_t level); void set_level(level_t level);
bool is_enabled(level_t level); bool is_enabled(level_t level);
void verbose(const pal::char_t* format, ...); void verbose(const pal::char_t* format, ...);
void info(const pal::char_t* format, ...); void info(const pal::char_t* format, ...);
void warning(const pal::char_t* format, ...); void warning(const pal::char_t* format, ...);
void error(const pal::char_t* format, ...); void error(const pal::char_t* format, ...);
}; };
#endif // TRACE_H #endif // TRACE_H

View file

@ -2,73 +2,73 @@
#include "utils.h" #include "utils.h"
arguments_t::arguments_t() : arguments_t::arguments_t() :
trace_level(trace::level_t::Error), trace_level(trace::level_t::Error),
managed_application(_X("")), managed_application(_X("")),
clr_path(_X("")), clr_path(_X("")),
app_argc(0), app_argc(0),
app_argv(nullptr) app_argv(nullptr)
{ {
} }
void display_help() void display_help()
{ {
xerr << xerr <<
_X("Usage: " HOST_EXE_NAME " [ASSEMBLY] [ARGUMENTS]\n") _X("Usage: " HOST_EXE_NAME " [ASSEMBLY] [ARGUMENTS]\n")
_X("Execute the specified managed assembly with the passed in arguments\n\n") _X("Execute the specified managed assembly with the passed in arguments\n\n")
_X("The Host's behavior can be altered using the following environment variables:\n") _X("The Host's behavior can be altered using the following environment variables:\n")
_X(" CLRHOST_CLR_PATH Set the directory which contains the CoreCLR runtime. Overrides all other values for CLR search paths\n") _X(" CLRHOST_CLR_PATH Set the directory which contains the CoreCLR runtime. Overrides all other values for CLR search paths\n")
_X(" CLRHOST_TRACE Set to affect trace levels (0 = Errors only (default), 1 = Warnings, 2 = Info, 3 = Verbose)\n"); _X(" CLRHOST_TRACE Set to affect trace levels (0 = Errors only (default), 1 = Warnings, 2 = Info, 3 = Verbose)\n");
} }
bool parse_arguments(const int argc, const pal::char_t* argv[], arguments_t& args) bool parse_arguments(const int argc, const pal::char_t* argv[], arguments_t& args)
{ {
// Get the full name of the application // Get the full name of the application
if (!pal::get_own_executable_path(args.own_path) || !pal::realpath(args.own_path)) if (!pal::get_own_executable_path(args.own_path) || !pal::realpath(args.own_path))
{ {
trace::error(_X("failed to locate current executable")); trace::error(_X("failed to locate current executable"));
return false; return false;
} }
auto own_name = get_filename(args.own_path); auto own_name = get_filename(args.own_path);
auto own_dir = get_directory(args.own_path); auto own_dir = get_directory(args.own_path);
if (own_name.compare(HOST_EXE_NAME) == 0) if (own_name.compare(HOST_EXE_NAME) == 0)
{ {
// corerun mode. First argument is managed app // corerun mode. First argument is managed app
if (argc < 2) if (argc < 2)
{ {
display_help(); display_help();
return false; return false;
} }
args.managed_application = pal::string_t(argv[1]); args.managed_application = pal::string_t(argv[1]);
args.app_argc = argc - 2; args.app_argc = argc - 2;
args.app_argv = &argv[2]; args.app_argv = &argv[2];
} }
else else
{ {
// coreconsole mode. Find the managed app in the same directory // coreconsole mode. Find the managed app in the same directory
pal::string_t managed_app(own_dir); pal::string_t managed_app(own_dir);
managed_app.push_back(DIR_SEPARATOR); managed_app.push_back(DIR_SEPARATOR);
managed_app.append(get_executable(own_name)); managed_app.append(get_executable(own_name));
managed_app.append(_X(".dll")); managed_app.append(_X(".dll"));
args.managed_application = managed_app; args.managed_application = managed_app;
args.app_argv = &argv[1]; args.app_argv = &argv[1];
args.app_argc = argc - 1; args.app_argc = argc - 1;
} }
// Read trace environment variable // Read trace environment variable
pal::string_t trace_str; pal::string_t trace_str;
if (pal::getenv(_X("CLRHOST_TRACE"), trace_str)) if (pal::getenv(_X("CLRHOST_TRACE"), trace_str))
{ {
auto trace_val = pal::xtoi(trace_str.c_str()); auto trace_val = pal::xtoi(trace_str.c_str());
if (trace_val >= (int)trace::level_t::Error && trace_val <= (int)trace::level_t::Verbose) if (trace_val >= (int)trace::level_t::Error && trace_val <= (int)trace::level_t::Verbose)
{ {
args.trace_level = (trace::level_t)trace_val; args.trace_level = (trace::level_t)trace_val;
} }
} }
// Read CLR path from environment variable // Read CLR path from environment variable
pal::getenv(_X("CLRHOST_CLR_PATH"), args.clr_path); pal::getenv(_X("CLRHOST_CLR_PATH"), args.clr_path);
return true; return true;
} }

View file

@ -7,27 +7,27 @@ static pal::dll_t g_coreclr = nullptr;
// Prototype of the coreclr_initialize function from coreclr.dll // Prototype of the coreclr_initialize function from coreclr.dll
typedef pal::hresult_t(*coreclr_initialize_fn)( typedef pal::hresult_t(*coreclr_initialize_fn)(
const char* exePath, const char* exePath,
const char* appDomainFriendlyName, const char* appDomainFriendlyName,
int propertyCount, int propertyCount,
const char** propertyKeys, const char** propertyKeys,
const char** propertyValues, const char** propertyValues,
coreclr::host_handle_t* hostHandle, coreclr::host_handle_t* hostHandle,
unsigned int* domainId); unsigned int* domainId);
// Prototype of the coreclr_shutdown function from coreclr.dll // Prototype of the coreclr_shutdown function from coreclr.dll
typedef pal::hresult_t(*coreclr_shutdown_fn)( typedef pal::hresult_t(*coreclr_shutdown_fn)(
coreclr::host_handle_t hostHandle, coreclr::host_handle_t hostHandle,
unsigned int domainId); unsigned int domainId);
// Prototype of the coreclr_execute_assembly function from coreclr.dll // Prototype of the coreclr_execute_assembly function from coreclr.dll
typedef pal::hresult_t(*coreclr_execute_assembly_fn)( typedef pal::hresult_t(*coreclr_execute_assembly_fn)(
coreclr::host_handle_t hostHandle, coreclr::host_handle_t hostHandle,
unsigned int domainId, unsigned int domainId,
int argc, int argc,
const char** argv, const char** argv,
const char* managedAssemblyPath, const char* managedAssemblyPath,
unsigned int* exitCode); unsigned int* exitCode);
static coreclr_shutdown_fn coreclr_shutdown = nullptr; static coreclr_shutdown_fn coreclr_shutdown = nullptr;
static coreclr_initialize_fn coreclr_initialize = nullptr; static coreclr_initialize_fn coreclr_initialize = nullptr;
@ -35,73 +35,73 @@ static coreclr_execute_assembly_fn coreclr_execute_assembly = nullptr;
bool coreclr::bind(const pal::string_t& libcoreclr_path) bool coreclr::bind(const pal::string_t& libcoreclr_path)
{ {
assert(g_coreclr == nullptr); assert(g_coreclr == nullptr);
pal::string_t coreclr_dll_path(libcoreclr_path); pal::string_t coreclr_dll_path(libcoreclr_path);
append_path(coreclr_dll_path, LIBCORECLR_NAME); append_path(coreclr_dll_path, LIBCORECLR_NAME);
if (!pal::load_library(coreclr_dll_path.c_str(), g_coreclr)) if (!pal::load_library(coreclr_dll_path.c_str(), g_coreclr))
{ {
return false; return false;
} }
coreclr_initialize = (coreclr_initialize_fn)pal::get_symbol(g_coreclr, "coreclr_initialize"); coreclr_initialize = (coreclr_initialize_fn)pal::get_symbol(g_coreclr, "coreclr_initialize");
coreclr_shutdown = (coreclr_shutdown_fn)pal::get_symbol(g_coreclr, "coreclr_shutdown"); coreclr_shutdown = (coreclr_shutdown_fn)pal::get_symbol(g_coreclr, "coreclr_shutdown");
coreclr_execute_assembly = (coreclr_execute_assembly_fn)pal::get_symbol(g_coreclr, "coreclr_execute_assembly"); coreclr_execute_assembly = (coreclr_execute_assembly_fn)pal::get_symbol(g_coreclr, "coreclr_execute_assembly");
return true; return true;
} }
void coreclr::unload() void coreclr::unload()
{ {
assert(g_coreclr != nullptr && coreclr_initialize != nullptr); assert(g_coreclr != nullptr && coreclr_initialize != nullptr);
pal::unload_library(g_coreclr); pal::unload_library(g_coreclr);
} }
pal::hresult_t coreclr::initialize( pal::hresult_t coreclr::initialize(
const char* exe_path, const char* exe_path,
const char* app_domain_friendly_name, const char* app_domain_friendly_name,
const char** property_keys, const char** property_keys,
const char** property_values, const char** property_values,
int property_count, int property_count,
host_handle_t* host_handle, host_handle_t* host_handle,
domain_id_t* domain_id) domain_id_t* domain_id)
{ {
assert(g_coreclr != nullptr && coreclr_initialize != nullptr); assert(g_coreclr != nullptr && coreclr_initialize != nullptr);
return coreclr_initialize( return coreclr_initialize(
exe_path, exe_path,
app_domain_friendly_name, app_domain_friendly_name,
property_count, property_count,
property_keys, property_keys,
property_values, property_values,
host_handle, host_handle,
domain_id); domain_id);
} }
pal::hresult_t coreclr::shutdown(host_handle_t host_handle, domain_id_t domain_id) pal::hresult_t coreclr::shutdown(host_handle_t host_handle, domain_id_t domain_id)
{ {
assert(g_coreclr != nullptr && coreclr_shutdown != nullptr); assert(g_coreclr != nullptr && coreclr_shutdown != nullptr);
return coreclr_shutdown(host_handle, domain_id); return coreclr_shutdown(host_handle, domain_id);
} }
pal::hresult_t coreclr::execute_assembly( pal::hresult_t coreclr::execute_assembly(
host_handle_t host_handle, host_handle_t host_handle,
domain_id_t domain_id, domain_id_t domain_id,
int argc, int argc,
const char** argv, const char** argv,
const char* managed_assembly_path, const char* managed_assembly_path,
unsigned int* exit_code) unsigned int* exit_code)
{ {
assert(g_coreclr != nullptr && coreclr_execute_assembly != nullptr); assert(g_coreclr != nullptr && coreclr_execute_assembly != nullptr);
return coreclr_execute_assembly( return coreclr_execute_assembly(
host_handle, host_handle,
domain_id, domain_id,
argc, argc,
argv, argv,
managed_assembly_path, managed_assembly_path,
exit_code); exit_code);
} }

View file

@ -7,143 +7,143 @@
void get_tpafile_path(const pal::string_t& app_base, const pal::string_t& app_name, pal::string_t& tpapath) void get_tpafile_path(const pal::string_t& app_base, const pal::string_t& app_name, pal::string_t& tpapath)
{ {
tpapath.reserve(app_base.length() + app_name.length() + 5); tpapath.reserve(app_base.length() + app_name.length() + 5);
tpapath.append(app_base); tpapath.append(app_base);
tpapath.push_back(DIR_SEPARATOR); tpapath.push_back(DIR_SEPARATOR);
// Remove the extension from the app_name // Remove the extension from the app_name
auto ext_location = app_name.find_last_of('.'); auto ext_location = app_name.find_last_of('.');
if (ext_location != std::string::npos) if (ext_location != std::string::npos)
{ {
tpapath.append(app_name.substr(0, ext_location)); tpapath.append(app_name.substr(0, ext_location));
} }
else else
{ {
tpapath.append(app_name); tpapath.append(app_name);
} }
tpapath.append(_X(".deps")); tpapath.append(_X(".deps"));
} }
int run(arguments_t args, pal::string_t app_base, tpafile tpa) int run(arguments_t args, pal::string_t app_base, tpafile tpa)
{ {
tpa.add_from_local_dir(app_base); tpa.add_from_local_dir(app_base);
// Add packages directory // Add packages directory
pal::string_t packages_dir; pal::string_t packages_dir;
if (!pal::get_default_packages_directory(packages_dir)) if (!pal::get_default_packages_directory(packages_dir))
{ {
trace::info(_X("did not find local packages directory")); trace::info(_X("did not find local packages directory"));
// We can continue, the app may have it's dependencies locally // We can continue, the app may have it's dependencies locally
} }
else else
{ {
trace::info(_X("using packages directory: %s"), packages_dir.c_str()); trace::info(_X("using packages directory: %s"), packages_dir.c_str());
tpa.add_package_dir(packages_dir); tpa.add_package_dir(packages_dir);
} }
// Add native search path // Add native search path
trace::info(_X("using native search path: %s"), packages_dir.c_str()); trace::info(_X("using native search path: %s"), packages_dir.c_str());
tpa.add_native_search_path(args.clr_path); tpa.add_native_search_path(args.clr_path);
// Build TPA list and search paths // Build TPA list and search paths
pal::string_t tpalist; pal::string_t tpalist;
tpa.write_tpa_list(tpalist); tpa.write_tpa_list(tpalist);
pal::string_t search_paths; pal::string_t search_paths;
tpa.write_native_paths(search_paths); tpa.write_native_paths(search_paths);
// Build CoreCLR properties // Build CoreCLR properties
const char* property_keys[] = { const char* property_keys[] = {
"TRUSTED_PLATFORM_ASSEMBLIES", "TRUSTED_PLATFORM_ASSEMBLIES",
"APP_PATHS", "APP_PATHS",
"APP_NI_PATHS", "APP_NI_PATHS",
"NATIVE_DLL_SEARCH_DIRECTORIES", "NATIVE_DLL_SEARCH_DIRECTORIES",
"AppDomainCompatSwitch" "AppDomainCompatSwitch"
}; };
auto tpa_cstr = pal::to_stdstring(tpalist); auto tpa_cstr = pal::to_stdstring(tpalist);
auto app_base_cstr = pal::to_stdstring(app_base); auto app_base_cstr = pal::to_stdstring(app_base);
auto search_paths_cstr = pal::to_stdstring(search_paths); auto search_paths_cstr = pal::to_stdstring(search_paths);
const char* property_values[] = { const char* property_values[] = {
// TRUSTED_PLATFORM_ASSEMBLIES // TRUSTED_PLATFORM_ASSEMBLIES
tpa_cstr.c_str(), tpa_cstr.c_str(),
// APP_PATHS // APP_PATHS
app_base_cstr.c_str(), app_base_cstr.c_str(),
// APP_NI_PATHS // APP_NI_PATHS
app_base_cstr.c_str(), app_base_cstr.c_str(),
// NATIVE_DLL_SEARCH_DIRECTORIES // NATIVE_DLL_SEARCH_DIRECTORIES
search_paths_cstr.c_str(), search_paths_cstr.c_str(),
// AppDomainCompatSwitch // AppDomainCompatSwitch
"UseLatestBehaviorWhenTFMNotSpecified" "UseLatestBehaviorWhenTFMNotSpecified"
}; };
// Dump TPA list // Dump TPA list
trace::verbose(_X("TPA List: %s"), tpalist.c_str()); trace::verbose(_X("TPA List: %s"), tpalist.c_str());
// Dump native search paths // Dump native search paths
trace::verbose(_X("Native Paths: %s"), search_paths.c_str()); trace::verbose(_X("Native Paths: %s"), search_paths.c_str());
// Bind CoreCLR // Bind CoreCLR
if (!coreclr::bind(args.clr_path)) if (!coreclr::bind(args.clr_path))
{ {
trace::error(_X("failed to bind to coreclr")); trace::error(_X("failed to bind to coreclr"));
return 1; return 1;
} }
// Initialize CoreCLR // Initialize CoreCLR
coreclr::host_handle_t host_handle; coreclr::host_handle_t host_handle;
coreclr::domain_id_t domain_id; coreclr::domain_id_t domain_id;
auto hr = coreclr::initialize( auto hr = coreclr::initialize(
pal::to_stdstring(args.own_path).c_str(), pal::to_stdstring(args.own_path).c_str(),
"clrhost", "clrhost",
property_keys, property_keys,
property_values, property_values,
sizeof(property_keys) / sizeof(property_keys[0]), sizeof(property_keys) / sizeof(property_keys[0]),
&host_handle, &host_handle,
&domain_id); &domain_id);
if (!SUCCEEDED(hr)) if (!SUCCEEDED(hr))
{ {
trace::error(_X("failed to initialize CoreCLR, HRESULT: 0x%X"), hr); trace::error(_X("failed to initialize CoreCLR, HRESULT: 0x%X"), hr);
return 1; return 1;
} }
// Convert the args (probably not the most performant way to do this...) // Convert the args (probably not the most performant way to do this...)
auto argv_strs = new std::string[args.app_argc]; auto argv_strs = new std::string[args.app_argc];
auto argv = new const char*[args.app_argc]; auto argv = new const char*[args.app_argc];
for (int i = 0; i < args.app_argc; i++) for (int i = 0; i < args.app_argc; i++)
{ {
argv_strs[i] = pal::to_stdstring(pal::string_t(args.app_argv[i])); argv_strs[i] = pal::to_stdstring(pal::string_t(args.app_argv[i]));
argv[i] = argv_strs[i].c_str(); argv[i] = argv_strs[i].c_str();
} }
// Execute the application // Execute the application
unsigned int exit_code = 1; unsigned int exit_code = 1;
hr = coreclr::execute_assembly( hr = coreclr::execute_assembly(
host_handle, host_handle,
domain_id, domain_id,
args.app_argc, args.app_argc,
argv, argv,
pal::to_stdstring(args.managed_application).c_str(), pal::to_stdstring(args.managed_application).c_str(),
&exit_code); &exit_code);
if (!SUCCEEDED(hr)) if (!SUCCEEDED(hr))
{ {
trace::error(_X("failed to execute managed app, HRESULT: 0x%X"), hr); trace::error(_X("failed to execute managed app, HRESULT: 0x%X"), hr);
return 1; return 1;
} }
// Shut down the CoreCLR // Shut down the CoreCLR
hr = coreclr::shutdown(host_handle, domain_id); hr = coreclr::shutdown(host_handle, domain_id);
if (!SUCCEEDED(hr)) if (!SUCCEEDED(hr))
{ {
trace::warning(_X("failed to shut down CoreCLR, HRESULT: 0x%X"), hr); trace::warning(_X("failed to shut down CoreCLR, HRESULT: 0x%X"), hr);
} }
coreclr::unload(); coreclr::unload();
return exit_code; return exit_code;
} }
#if defined(_WIN32) #if defined(_WIN32)
@ -152,66 +152,66 @@ int __cdecl wmain(const int argc, const pal::char_t* argv[])
int main(const int argc, const pal::char_t* argv[]) int main(const int argc, const pal::char_t* argv[])
#endif #endif
{ {
arguments_t args; arguments_t args;
if (!parse_arguments(argc, argv, args)) if (!parse_arguments(argc, argv, args))
{ {
return 1; return 1;
} }
// Configure tracing // Configure tracing
trace::set_level(args.trace_level); trace::set_level(args.trace_level);
trace::info(_X("tracing enabled")); trace::info(_X("tracing enabled"));
// Resolve paths // Resolve paths
if (!pal::realpath(args.managed_application)) if (!pal::realpath(args.managed_application))
{ {
trace::error(_X("failed to locate managed application: %s"), args.managed_application.c_str()); trace::error(_X("failed to locate managed application: %s"), args.managed_application.c_str());
return 1; return 1;
} }
trace::info(_X("preparing to launch managed application: %s"), args.managed_application.c_str()); trace::info(_X("preparing to launch managed application: %s"), args.managed_application.c_str());
trace::info(_X("host path: %s"), args.own_path.c_str()); trace::info(_X("host path: %s"), args.own_path.c_str());
pal::string_t argstr; pal::string_t argstr;
for (int i = 0; i < args.app_argc; i++) for (int i = 0; i < args.app_argc; i++)
{ {
argstr.append(args.app_argv[i]); argstr.append(args.app_argv[i]);
argstr.append(_X(",")); argstr.append(_X(","));
} }
trace::info(_X("App argc: %d"), args.app_argc); trace::info(_X("App argc: %d"), args.app_argc);
trace::info(_X("App argv: %s"), argstr.c_str()); trace::info(_X("App argv: %s"), argstr.c_str());
auto app_base = get_directory(args.managed_application); auto app_base = get_directory(args.managed_application);
auto app_name = get_filename(args.managed_application); auto app_name = get_filename(args.managed_application);
if (args.clr_path.empty()) if (args.clr_path.empty())
{ {
// Use the directory containing the managed assembly // Use the directory containing the managed assembly
if (!find_coreclr(app_base, args.clr_path)) if (!find_coreclr(app_base, args.clr_path))
{ {
trace::error(_X("failed to locate CLR files")); trace::error(_X("failed to locate CLR files"));
return 1; return 1;
} }
} }
if (!pal::realpath(args.clr_path)) if (!pal::realpath(args.clr_path))
{ {
trace::error(_X("failed to locate CLR files at %s"), args.clr_path.c_str()); trace::error(_X("failed to locate CLR files at %s"), args.clr_path.c_str());
return 1; return 1;
} }
trace::info(_X("using CLR files from: %s"), args.clr_path.c_str()); trace::info(_X("using CLR files from: %s"), args.clr_path.c_str());
trace::info(_X("preparing to launch: %s"), app_name.c_str()); trace::info(_X("preparing to launch: %s"), app_name.c_str());
trace::info(_X("using app base: %s"), app_base.c_str()); trace::info(_X("using app base: %s"), app_base.c_str());
// Check for and load tpa file // Check for and load tpa file
pal::string_t tpafile_path; pal::string_t tpafile_path;
get_tpafile_path(app_base, app_name, tpafile_path); get_tpafile_path(app_base, app_name, tpafile_path);
trace::info(_X("checking for TPA File at: %s"), tpafile_path.c_str()); trace::info(_X("checking for TPA File at: %s"), tpafile_path.c_str());
tpafile tpa; tpafile tpa;
if (!tpa.load(tpafile_path)) if (!tpa.load(tpafile_path))
{ {
trace::error(_X("invalid TPA file")); trace::error(_X("invalid TPA file"));
return 1; return 1;
} }
return run(args, app_base, tpa); return run(args, app_base, tpa);
} }

View file

@ -9,148 +9,148 @@ static std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> g_converter;
bool pal::load_library(const char_t* path, dll_t& dll) bool pal::load_library(const char_t* path, dll_t& dll)
{ {
dll = ::LoadLibraryW(path); dll = ::LoadLibraryW(path);
if (dll == nullptr) if (dll == nullptr)
{ {
trace::error(_X("failed to load coreclr.dll from %s, HRESULT: 0x%X"), path, HRESULT_FROM_WIN32(GetLastError())); trace::error(_X("failed to load coreclr.dll from %s, HRESULT: 0x%X"), path, HRESULT_FROM_WIN32(GetLastError()));
return false; return false;
} }
// Pin the module // Pin the module
HMODULE dummy_module; HMODULE dummy_module;
if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, path, &dummy_module)) if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, path, &dummy_module))
{ {
trace::error(_X("failed to pin library: %s")); trace::error(_X("failed to pin library: %s"));
return false; return false;
} }
if (trace::is_enabled(trace::level_t::Info)) if (trace::is_enabled(trace::level_t::Info))
{ {
pal::char_t buf[PATH_MAX]; pal::char_t buf[PATH_MAX];
::GetModuleFileNameW(dll, buf, PATH_MAX); ::GetModuleFileNameW(dll, buf, PATH_MAX);
trace::info(_X("loaded library from %s"), buf); trace::info(_X("loaded library from %s"), buf);
} }
return true; return true;
} }
pal::proc_t pal::get_symbol(dll_t library, const char* name) pal::proc_t pal::get_symbol(dll_t library, const char* name)
{ {
return ::GetProcAddress(library, name); return ::GetProcAddress(library, name);
} }
void pal::unload_library(dll_t library) void pal::unload_library(dll_t library)
{ {
// No-op. On windows, we pin the library, so it can't be unloaded. // No-op. On windows, we pin the library, so it can't be unloaded.
} }
bool pal::get_default_packages_directory(string_t& recv) bool pal::get_default_packages_directory(string_t& recv)
{ {
if (!pal::getenv(_X("USERPROFILE"), recv)) if (!pal::getenv(_X("USERPROFILE"), recv))
{ {
return false; return false;
} }
append_path(recv, _X(".dnx")); append_path(recv, _X(".dnx"));
append_path(recv, _X("packages")); append_path(recv, _X("packages"));
return true; return true;
} }
bool pal::is_path_rooted(const string_t& path) bool pal::is_path_rooted(const string_t& path)
{ {
return path.length() >= 2 && path[1] == L':'; return path.length() >= 2 && path[1] == L':';
} }
bool pal::getenv(const char_t* name, string_t& recv) bool pal::getenv(const char_t* name, string_t& recv)
{ {
auto length = ::GetEnvironmentVariableW(name, nullptr, 0); auto length = ::GetEnvironmentVariableW(name, nullptr, 0);
if (length == 0) if (length == 0)
{ {
auto err = GetLastError(); auto err = GetLastError();
if (err == ERROR_ENVVAR_NOT_FOUND) if (err == ERROR_ENVVAR_NOT_FOUND)
{ {
// Leave the receiver empty and return success // Leave the receiver empty and return success
return true; return true;
} }
trace::error(_X("failed to read enviroment variable '%s', HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError())); trace::error(_X("failed to read enviroment variable '%s', HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError()));
return false; return false;
} }
auto buf = new char_t[length]; auto buf = new char_t[length];
if (::GetEnvironmentVariableW(name, buf, length) == 0) if (::GetEnvironmentVariableW(name, buf, length) == 0)
{ {
trace::error(_X("failed to read enviroment variable '%s', HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError())); trace::error(_X("failed to read enviroment variable '%s', HRESULT: 0x%X"), name, HRESULT_FROM_WIN32(GetLastError()));
return false; return false;
} }
recv.assign(buf); recv.assign(buf);
delete[] buf; delete[] buf;
return true; return true;
} }
int pal::xtoi(const char_t* input) int pal::xtoi(const char_t* input)
{ {
return ::_wtoi(input); return ::_wtoi(input);
} }
bool pal::get_own_executable_path(string_t& recv) bool pal::get_own_executable_path(string_t& recv)
{ {
char_t program_path[MAX_PATH]; char_t program_path[MAX_PATH];
DWORD dwModuleFileName = ::GetModuleFileNameW(NULL, program_path, MAX_PATH); DWORD dwModuleFileName = ::GetModuleFileNameW(NULL, program_path, MAX_PATH);
if (dwModuleFileName == 0 || dwModuleFileName >= MAX_PATH) { if (dwModuleFileName == 0 || dwModuleFileName >= MAX_PATH) {
return false; return false;
} }
recv.assign(program_path); recv.assign(program_path);
return true; return true;
} }
std::string pal::to_stdstring(const string_t& str) std::string pal::to_stdstring(const string_t& str)
{ {
return g_converter.to_bytes(str); return g_converter.to_bytes(str);
} }
pal::string_t pal::to_palstring(const std::string& str) pal::string_t pal::to_palstring(const std::string& str)
{ {
return g_converter.from_bytes(str); return g_converter.from_bytes(str);
} }
bool pal::realpath(string_t& path) bool pal::realpath(string_t& path)
{ {
char_t buf[MAX_PATH]; char_t buf[MAX_PATH];
auto res = ::GetFullPathNameW(path.c_str(), MAX_PATH, buf, nullptr); auto res = ::GetFullPathNameW(path.c_str(), MAX_PATH, buf, nullptr);
if (res == 0 || res > MAX_PATH) if (res == 0 || res > MAX_PATH)
{ {
trace::error(_X("error resolving path: %s"), path.c_str()); trace::error(_X("error resolving path: %s"), path.c_str());
return false; return false;
} }
path.assign(buf); path.assign(buf);
return true; return true;
} }
bool pal::file_exists(const string_t& path) bool pal::file_exists(const string_t& path)
{ {
WIN32_FIND_DATAW data; WIN32_FIND_DATAW data;
auto find_handle = ::FindFirstFileW(path.c_str(), &data); auto find_handle = ::FindFirstFileW(path.c_str(), &data);
bool found = find_handle != INVALID_HANDLE_VALUE; bool found = find_handle != INVALID_HANDLE_VALUE;
::FindClose(find_handle); ::FindClose(find_handle);
return found; return found;
} }
std::vector<pal::string_t> pal::readdir(const string_t& path) std::vector<pal::string_t> pal::readdir(const string_t& path)
{ {
std::vector<string_t> files; std::vector<string_t> files;
string_t search_string(path); string_t search_string(path);
search_string.push_back(DIR_SEPARATOR); search_string.push_back(DIR_SEPARATOR);
search_string.push_back(L'*'); search_string.push_back(L'*');
WIN32_FIND_DATAW data; WIN32_FIND_DATAW data;
auto handle = ::FindFirstFileW(search_string.c_str(), &data); auto handle = ::FindFirstFileW(search_string.c_str(), &data);
do do
{ {
string_t filepath(data.cFileName); string_t filepath(data.cFileName);
files.push_back(filepath); files.push_back(filepath);
} while (::FindNextFileW(handle, &data)); } while (::FindNextFileW(handle, &data));
::FindClose(handle); ::FindClose(handle);
return files; return files;
} }

View file

@ -7,242 +7,242 @@
bool read_field(pal::string_t line, int& offset, pal::string_t& value_recv) bool read_field(pal::string_t line, int& offset, pal::string_t& value_recv)
{ {
// The first character should be a '"' // The first character should be a '"'
if (line[offset] != '"') if (line[offset] != '"')
{ {
trace::error(_X("error reading TPA file")); trace::error(_X("error reading TPA file"));
return false; return false;
} }
offset++; offset++;
// Set up destination buffer (it can't be bigger than the original line) // Set up destination buffer (it can't be bigger than the original line)
pal::char_t buf[PATH_MAX]; pal::char_t buf[PATH_MAX];
auto buf_offset = 0; auto buf_offset = 0;
// Iterate through characters in the string // Iterate through characters in the string
for (; offset < line.length(); offset++) for (; offset < line.length(); offset++)
{ {
// Is this a '\'? // Is this a '\'?
if (line[offset] == '\\') if (line[offset] == '\\')
{ {
// Skip this character and read the next character into the buffer // Skip this character and read the next character into the buffer
offset++; offset++;
buf[buf_offset] = line[offset]; buf[buf_offset] = line[offset];
} }
// Is this a '"'? // Is this a '"'?
else if (line[offset] == '\"') else if (line[offset] == '\"')
{ {
// Done! Advance to the pointer after the input // Done! Advance to the pointer after the input
offset++; offset++;
break; break;
} }
else else
{ {
// Take the character // Take the character
buf[buf_offset] = line[offset]; buf[buf_offset] = line[offset];
} }
buf_offset++; buf_offset++;
} }
buf[buf_offset] = '\0'; buf[buf_offset] = '\0';
value_recv.assign(buf); value_recv.assign(buf);
// Consume the ',' if we have one // Consume the ',' if we have one
if (line[offset] == ',') if (line[offset] == ',')
{ {
offset++; offset++;
} }
return true; return true;
} }
bool tpafile::load(pal::string_t path) bool tpafile::load(pal::string_t path)
{ {
// Check if the file exists, if not, there is nothing to add // Check if the file exists, if not, there is nothing to add
if (!pal::file_exists(path)) if (!pal::file_exists(path))
{ {
return true; return true;
} }
// Open the file // Open the file
pal::ifstream_t file(path); pal::ifstream_t file(path);
if (!file.good()) if (!file.good())
{ {
// Failed to open the file! // Failed to open the file!
return false; return false;
} }
// Read lines from the file // Read lines from the file
while (true) while (true)
{ {
std::string line; std::string line;
std::getline(file, line); std::getline(file, line);
auto line_palstr = pal::to_palstring(line); auto line_palstr = pal::to_palstring(line);
if (file.eof()) if (file.eof())
{ {
break; break;
} }
auto offset = 0; auto offset = 0;
tpaentry_t entry; tpaentry_t entry;
// Read fields // Read fields
if (!(read_field(line_palstr, offset, entry.library_type))) return false; if (!(read_field(line_palstr, offset, entry.library_type))) return false;
if (!(read_field(line_palstr, offset, entry.library_name))) return false; if (!(read_field(line_palstr, offset, entry.library_name))) return false;
if (!(read_field(line_palstr, offset, entry.library_version))) return false; if (!(read_field(line_palstr, offset, entry.library_version))) return false;
if (!(read_field(line_palstr, offset, entry.library_hash))) return false; if (!(read_field(line_palstr, offset, entry.library_hash))) return false;
if (!(read_field(line_palstr, offset, entry.asset_type))) return false; if (!(read_field(line_palstr, offset, entry.asset_type))) return false;
if (!(read_field(line_palstr, offset, entry.asset_name))) return false; if (!(read_field(line_palstr, offset, entry.asset_name))) return false;
if (!(read_field(line_palstr, offset, entry.relative_path))) return false; if (!(read_field(line_palstr, offset, entry.relative_path))) return false;
m_entries.push_back(entry); m_entries.push_back(entry);
} }
return true; return true;
} }
void tpafile::add_from_local_dir(const pal::string_t& dir) void tpafile::add_from_local_dir(const pal::string_t& dir)
{ {
trace::verbose(_X("adding files from %s to TPA"), dir.c_str()); trace::verbose(_X("adding files from %s to TPA"), dir.c_str());
const pal::char_t * const tpa_extensions[] = { const pal::char_t * const tpa_extensions[] = {
_X(".ni.dll"), // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir _X(".ni.dll"), // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir
_X(".dll"), _X(".dll"),
_X(".ni.exe"), _X(".ni.exe"),
_X(".exe"), _X(".exe"),
}; };
std::set<pal::string_t> added_assemblies; std::set<pal::string_t> added_assemblies;
// Get directory entries // Get directory entries
auto files = pal::readdir(dir); auto files = pal::readdir(dir);
for (auto ext : tpa_extensions) for (auto ext : tpa_extensions)
{ {
auto len = pal::strlen(ext); auto len = pal::strlen(ext);
for (auto file : files) for (auto file : files)
{ {
// Can't be a match if it's the same length as the extension :) // Can't be a match if it's the same length as the extension :)
if (file.length() > len) if (file.length() > len)
{ {
// Extract the same amount of text from the end of file name // Extract the same amount of text from the end of file name
auto file_ext = file.substr(file.length() - len, len); auto file_ext = file.substr(file.length() - len, len);
// Check if this file name matches // Check if this file name matches
if (pal::strcasecmp(ext, file_ext.c_str()) == 0) if (pal::strcasecmp(ext, file_ext.c_str()) == 0)
{ {
// Get the assembly name by stripping the extension // Get the assembly name by stripping the extension
// and add it to the set so we can de-dupe // and add it to the set so we can de-dupe
auto asm_name = file.substr(0, file.length() - len); auto asm_name = file.substr(0, file.length() - len);
// TODO(anurse): Also check if already in TPA file // TODO(anurse): Also check if already in TPA file
if (added_assemblies.find(asm_name) == added_assemblies.end()) if (added_assemblies.find(asm_name) == added_assemblies.end())
{ {
added_assemblies.insert(asm_name); added_assemblies.insert(asm_name);
tpaentry_t entry; tpaentry_t entry;
entry.asset_type = pal::string_t(_X("runtime")); entry.asset_type = pal::string_t(_X("runtime"));
entry.library_name = pal::string_t(asm_name); entry.library_name = pal::string_t(asm_name);
entry.library_version = pal::string_t(_X("")); entry.library_version = pal::string_t(_X(""));
pal::string_t relpath(dir); pal::string_t relpath(dir);
relpath.push_back(DIR_SEPARATOR); relpath.push_back(DIR_SEPARATOR);
relpath.append(file); relpath.append(file);
entry.relative_path = relpath; entry.relative_path = relpath;
entry.asset_name = asm_name; entry.asset_name = asm_name;
trace::verbose(_X("adding %s to TPA list from %s"), asm_name.c_str(), relpath.c_str()); trace::verbose(_X("adding %s to TPA list from %s"), asm_name.c_str(), relpath.c_str());
m_entries.push_back(entry); m_entries.push_back(entry);
} }
} }
} }
} }
} }
} }
void tpafile::write_tpa_list(pal::string_t& output) void tpafile::write_tpa_list(pal::string_t& output)
{ {
std::set<pal::string_t> items; std::set<pal::string_t> items;
for (auto entry : m_entries) for (auto entry : m_entries)
{ {
if (pal::strcmp(entry.asset_type.c_str(), _X("runtime")) == 0 && items.find(entry.asset_name) == items.end()) if (pal::strcmp(entry.asset_type.c_str(), _X("runtime")) == 0 && items.find(entry.asset_name) == items.end())
{ {
// Resolve the full path // Resolve the full path
for (auto search_path : m_package_search_paths) for (auto search_path : m_package_search_paths)
{ {
pal::string_t candidate; pal::string_t candidate;
candidate.reserve(search_path.length() + candidate.reserve(search_path.length() +
entry.library_name.length() + entry.library_name.length() +
entry.library_version.length() + entry.library_version.length() +
entry.relative_path.length() + 3); entry.relative_path.length() + 3);
candidate.append(search_path); candidate.append(search_path);
append_path(candidate, entry.library_name.c_str()); append_path(candidate, entry.library_name.c_str());
append_path(candidate, entry.library_version.c_str()); append_path(candidate, entry.library_version.c_str());
append_path(candidate, entry.relative_path.c_str()); append_path(candidate, entry.relative_path.c_str());
if (pal::file_exists(candidate)) if (pal::file_exists(candidate))
{ {
trace::verbose(_X("adding tpa entry: %s"), candidate.c_str()); trace::verbose(_X("adding tpa entry: %s"), candidate.c_str());
output.append(candidate); output.append(candidate);
output.push_back(PATH_SEPARATOR); output.push_back(PATH_SEPARATOR);
items.insert(entry.asset_name); items.insert(entry.asset_name);
break; break;
} }
} }
} }
} }
} }
void tpafile::write_native_paths(pal::string_t& output) void tpafile::write_native_paths(pal::string_t& output)
{ {
std::set<pal::string_t> items; std::set<pal::string_t> items;
for (auto search_path : m_native_search_paths) for (auto search_path : m_native_search_paths)
{ {
if (items.find(search_path) == items.end()) if (items.find(search_path) == items.end())
{ {
trace::verbose(_X("adding native search path: %s"), search_path.c_str()); trace::verbose(_X("adding native search path: %s"), search_path.c_str());
output.append(search_path); output.append(search_path);
output.push_back(PATH_SEPARATOR); output.push_back(PATH_SEPARATOR);
items.insert(search_path); items.insert(search_path);
} }
} }
for (auto entry : m_entries) for (auto entry : m_entries)
{ {
auto dir = entry.relative_path.substr(0, entry.relative_path.find_last_of(DIR_SEPARATOR)); auto dir = entry.relative_path.substr(0, entry.relative_path.find_last_of(DIR_SEPARATOR));
if (pal::strcmp(entry.asset_type.c_str(), _X("native")) == 0 && items.find(dir) == items.end()) if (pal::strcmp(entry.asset_type.c_str(), _X("native")) == 0 && items.find(dir) == items.end())
{ {
// Resolve the full path // Resolve the full path
for (auto search_path : m_package_search_paths) for (auto search_path : m_package_search_paths)
{ {
pal::string_t candidate; pal::string_t candidate;
candidate.reserve(search_path.length() + candidate.reserve(search_path.length() +
entry.library_name.length() + entry.library_name.length() +
entry.library_version.length() + entry.library_version.length() +
dir.length() + 3); dir.length() + 3);
candidate.append(search_path); candidate.append(search_path);
append_path(candidate, entry.library_name.c_str()); append_path(candidate, entry.library_name.c_str());
append_path(candidate, entry.library_version.c_str()); append_path(candidate, entry.library_version.c_str());
append_path(candidate, get_directory(entry.relative_path).c_str()); append_path(candidate, get_directory(entry.relative_path).c_str());
if (pal::file_exists(candidate)) if (pal::file_exists(candidate))
{ {
trace::verbose(_X("adding native search path: %s"), candidate.c_str()); trace::verbose(_X("adding native search path: %s"), candidate.c_str());
output.append(candidate); output.append(candidate);
output.push_back(PATH_SEPARATOR); output.push_back(PATH_SEPARATOR);
items.insert(dir); items.insert(dir);
break; break;
} }
} }
} }
} }
} }
void tpafile::add_package_dir(pal::string_t dir) void tpafile::add_package_dir(pal::string_t dir)
{ {
m_package_search_paths.push_back(dir); m_package_search_paths.push_back(dir);
} }
void tpafile::add_native_search_path(pal::string_t dir) void tpafile::add_native_search_path(pal::string_t dir)
{ {
m_native_search_paths.push_back(dir); m_native_search_paths.push_back(dir);
} }

View file

@ -4,54 +4,54 @@ static trace::level_t g_level = trace::level_t::Error;
void trace::set_level(trace::level_t new_level) void trace::set_level(trace::level_t new_level)
{ {
g_level = new_level; g_level = new_level;
} }
bool trace::is_enabled(trace::level_t level) bool trace::is_enabled(trace::level_t level)
{ {
return level <= g_level; return level <= g_level;
} }
void trace::verbose(const pal::char_t* format, ...) void trace::verbose(const pal::char_t* format, ...)
{ {
if (trace::is_enabled(trace::level_t::Verbose)) if (trace::is_enabled(trace::level_t::Verbose))
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
pal::err_vprintf(format, args); pal::err_vprintf(format, args);
va_end(args); va_end(args);
} }
} }
void trace::info(const pal::char_t* format, ...) void trace::info(const pal::char_t* format, ...)
{ {
if (trace::is_enabled(trace::level_t::Info)) if (trace::is_enabled(trace::level_t::Info))
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
pal::err_vprintf(format, args); pal::err_vprintf(format, args);
va_end(args); va_end(args);
} }
} }
void trace::error(const pal::char_t* format, ...) void trace::error(const pal::char_t* format, ...)
{ {
if (trace::is_enabled(trace::level_t::Error)) if (trace::is_enabled(trace::level_t::Error))
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
pal::err_vprintf(format, args); pal::err_vprintf(format, args);
va_end(args); va_end(args);
} }
} }
void trace::warning(const pal::char_t* format, ...) void trace::warning(const pal::char_t* format, ...)
{ {
if (trace::is_enabled(trace::level_t::Warning)) if (trace::is_enabled(trace::level_t::Warning))
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
pal::err_vprintf(format, args); pal::err_vprintf(format, args);
va_end(args); va_end(args);
} }
} }

View file

@ -2,92 +2,92 @@
bool ends_with(const pal::string_t& value, const pal::string_t& suffix) bool ends_with(const pal::string_t& value, const pal::string_t& suffix)
{ {
return (0 == value.compare(value.length() - suffix.length(), suffix.length(), suffix)); return (0 == value.compare(value.length() - suffix.length(), suffix.length(), suffix));
} }
bool find_coreclr(const pal::string_t& appbase, pal::string_t& recv) bool find_coreclr(const pal::string_t& appbase, pal::string_t& recv)
{ {
pal::string_t candidate; pal::string_t candidate;
// Check if it exists in the appbase // Check if it exists in the appbase
candidate.assign(appbase); candidate.assign(appbase);
append_path(candidate, LIBCORECLR_NAME); append_path(candidate, LIBCORECLR_NAME);
if (pal::file_exists(candidate)) if (pal::file_exists(candidate))
{ {
recv.assign(appbase); recv.assign(appbase);
return true; return true;
} }
// TODO: Have a cleaner search strategy that supports multiple versions // TODO: Have a cleaner search strategy that supports multiple versions
// Search the PATH // Search the PATH
pal::string_t path; pal::string_t path;
if (!pal::getenv(_X("PATH"), path)) if (!pal::getenv(_X("PATH"), path))
{ {
return false; return false;
} }
pal::stringstream_t path_stream(path); pal::stringstream_t path_stream(path);
pal::string_t entry; pal::string_t entry;
while (std::getline(path_stream, entry, PATH_SEPARATOR)) while (std::getline(path_stream, entry, PATH_SEPARATOR))
{ {
candidate.assign(entry); candidate.assign(entry);
append_path(candidate, LIBCORECLR_NAME); append_path(candidate, LIBCORECLR_NAME);
if (pal::file_exists(candidate)) if (pal::file_exists(candidate))
{ {
recv.assign(entry); recv.assign(entry);
return true; return true;
} }
} }
return false; return false;
} }
void append_path(pal::string_t& path1, const pal::char_t* path2) void append_path(pal::string_t& path1, const pal::char_t* path2)
{ {
if (pal::is_path_rooted(path2)) if (pal::is_path_rooted(path2))
{ {
path1.assign(path2); path1.assign(path2);
} }
else else
{ {
if (path1.back() != DIR_SEPARATOR) if (path1.back() != DIR_SEPARATOR)
{ {
path1.push_back(DIR_SEPARATOR); path1.push_back(DIR_SEPARATOR);
} }
path1.append(path2); path1.append(path2);
} }
} }
pal::string_t get_executable(const pal::string_t& filename) pal::string_t get_executable(const pal::string_t& filename)
{ {
pal::string_t result(filename); pal::string_t result(filename);
if (ends_with(result, _X(".exe"))) if (ends_with(result, _X(".exe")))
{ {
// We need to strip off the old extension // We need to strip off the old extension
result.erase(result.length() - 4); result.erase(result.length() - 4);
} }
return result; return result;
} }
pal::string_t get_filename(const pal::string_t& path) pal::string_t get_filename(const pal::string_t& path)
{ {
// Find the last dir separator // Find the last dir separator
auto path_sep = path.find_last_of(DIR_SEPARATOR); auto path_sep = path.find_last_of(DIR_SEPARATOR);
if (path_sep == pal::string_t::npos) if (path_sep == pal::string_t::npos)
{ {
return pal::string_t(path); return pal::string_t(path);
} }
return path.substr(path_sep + 1); return path.substr(path_sep + 1);
} }
pal::string_t get_directory(const pal::string_t& path) pal::string_t get_directory(const pal::string_t& path)
{ {
// Find the last dir separator // Find the last dir separator
auto path_sep = path.find_last_of(DIR_SEPARATOR); auto path_sep = path.find_last_of(DIR_SEPARATOR);
if (path_sep == pal::string_t::npos) if (path_sep == pal::string_t::npos)
{ {
return pal::string_t(path); return pal::string_t(path);
} }
return path.substr(0, path_sep); return path.substr(0, path_sep);
} }