/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2013 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/kernel/xmodule.h" #include "xenia/base/byte_stream.h" #include "xenia/base/logging.h" #include "xenia/base/string.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/user_module.h" namespace xe { namespace kernel { XModule::XModule(KernelState* kernel_state, ModuleType module_type) : XObject(kernel_state, kTypeModule), module_type_(module_type), processor_module_(nullptr), hmodule_ptr_(0) { // Loader data (HMODULE) hmodule_ptr_ = memory()->SystemHeapAlloc(sizeof(X_LDR_DATA_TABLE_ENTRY)); // Hijack the checksum field to store our kernel object handle. auto ldr_data = memory()->TranslateVirtual(hmodule_ptr_); ldr_data->checksum = handle(); } XModule::~XModule() { kernel_state_->UnregisterModule(this); // Destroy the loader data. memory()->SystemHeapFree(hmodule_ptr_); } bool XModule::Matches(const std::string& name) const { if (strcasecmp(xe::find_name_from_path(path_).c_str(), name.c_str()) == 0) { return true; } if (strcasecmp(name_.c_str(), name.c_str()) == 0) { return true; } if (strcasecmp(path_.c_str(), name.c_str()) == 0) { return true; } return false; } void XModule::OnLoad() { kernel_state_->RegisterModule(this); } void XModule::OnUnload() { kernel_state_->UnregisterModule(this); } X_STATUS XModule::GetSection(const char* name, uint32_t* out_section_data, uint32_t* out_section_size) { return X_STATUS_UNSUCCESSFUL; } object_ref XModule::GetFromHModule(KernelState* kernel_state, void* hmodule) { // Grab the object from our stashed kernel handle return kernel_state->object_table()->LookupObject( GetHandleFromHModule(hmodule)); } uint32_t XModule::GetHandleFromHModule(void* hmodule) { auto ldr_data = reinterpret_cast(hmodule); return ldr_data->checksum; } std::string XModule::NameFromPath(std::string path) { std::string name; auto last_slash = path.find_last_of('/'); if (last_slash == path.npos) { last_slash = path.find_last_of('\\'); } if (last_slash == path.npos) { name = path; } else { name = path.substr(last_slash + 1); } auto dot = name.find_last_of('.'); if (dot != name.npos) { name = name.substr(0, dot); } return name; } bool XModule::Save(ByteStream* stream) { XELOGD("XModule %.8X (%s)", handle(), path_.c_str()); stream->Write('XMOD'); stream->Write(path_); stream->Write(hmodule_ptr_); if (!SaveObject(stream)) { return false; } return true; } object_ref XModule::Restore(KernelState* kernel_state, ByteStream* stream) { if (stream->Read() != 'XMOD') { return nullptr; } auto path = stream->Read(); auto hmodule_ptr = stream->Read(); // Can only save user modules at the moment, so just redirect. // TODO: Find a way to call RestoreObject here before UserModule::Restore. auto module = UserModule::Restore(kernel_state, stream, path); if (!module) { return nullptr; } XELOGD("XModule %.8X (%s)", module->handle(), module->path_.c_str()); module->hmodule_ptr_ = hmodule_ptr; return module; } } // namespace kernel } // namespace xe