[Kernel] Implemented XexLoadImageFromMemory
This commit is contained in:
parent
1a9ff8fe67
commit
a867320a87
|
@ -443,7 +443,7 @@ object_ref<UserModule> KernelState::LoadUserModule(
|
||||||
|
|
||||||
// See if we've already loaded it
|
// See if we've already loaded it
|
||||||
for (auto& existing_module : user_modules_) {
|
for (auto& existing_module : user_modules_) {
|
||||||
if (existing_module->path() == path) {
|
if (existing_module->Matches(path)) {
|
||||||
return existing_module;
|
return existing_module;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -466,6 +466,39 @@ object_ref<UserModule> KernelState::LoadUserModule(
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object_ref<UserModule> KernelState::LoadUserModuleFromMemory(
|
||||||
|
const std::string_view raw_name, const void* addr, const size_t length) {
|
||||||
|
auto name = xe::utf8::find_base_name_from_guest_path(raw_name);
|
||||||
|
|
||||||
|
object_ref<UserModule> module;
|
||||||
|
{
|
||||||
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
|
|
||||||
|
// See if we've already loaded it
|
||||||
|
for (auto& existing_module : user_modules_) {
|
||||||
|
if (existing_module->Matches(name)) {
|
||||||
|
return existing_module;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global_lock.unlock();
|
||||||
|
|
||||||
|
// Module wasn't loaded, so load it.
|
||||||
|
module = object_ref<UserModule>(new UserModule(this));
|
||||||
|
X_STATUS status = module->LoadFromMemoryNamed(name, addr, length);
|
||||||
|
if (XFAILED(status)) {
|
||||||
|
object_table()->ReleaseHandle(module->handle());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
global_lock.lock();
|
||||||
|
|
||||||
|
// Putting into the listing automatically retains.
|
||||||
|
user_modules_.push_back(module);
|
||||||
|
}
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
X_RESULT KernelState::FinishLoadingUserModule(
|
X_RESULT KernelState::FinishLoadingUserModule(
|
||||||
const object_ref<UserModule> module, bool call_entry) {
|
const object_ref<UserModule> module, bool call_entry) {
|
||||||
// TODO(Gliniak): Apply custom patches here
|
// TODO(Gliniak): Apply custom patches here
|
||||||
|
|
|
@ -258,6 +258,9 @@ class KernelState {
|
||||||
void SetExecutableModule(object_ref<UserModule> module);
|
void SetExecutableModule(object_ref<UserModule> module);
|
||||||
object_ref<UserModule> LoadUserModule(const std::string_view name,
|
object_ref<UserModule> LoadUserModule(const std::string_view name,
|
||||||
bool call_entry = true);
|
bool call_entry = true);
|
||||||
|
object_ref<UserModule> LoadUserModuleFromMemory(const std::string_view name,
|
||||||
|
const void* addr,
|
||||||
|
const size_t length);
|
||||||
X_RESULT FinishLoadingUserModule(const object_ref<UserModule> module,
|
X_RESULT FinishLoadingUserModule(const object_ref<UserModule> module,
|
||||||
bool call_entry = true);
|
bool call_entry = true);
|
||||||
void UnloadUserModule(const object_ref<UserModule>& module,
|
void UnloadUserModule(const object_ref<UserModule>& module,
|
||||||
|
|
|
@ -182,6 +182,13 @@ X_STATUS UserModule::LoadFromMemory(const void* addr, const size_t length) {
|
||||||
return X_STATUS_SUCCESS;
|
return X_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X_STATUS UserModule::LoadFromMemoryNamed(const std::string_view raw_name,
|
||||||
|
const void* addr,
|
||||||
|
const size_t length) {
|
||||||
|
name_ = std::string(raw_name);
|
||||||
|
return LoadFromMemory(addr, length);
|
||||||
|
}
|
||||||
|
|
||||||
X_STATUS UserModule::LoadContinue() {
|
X_STATUS UserModule::LoadContinue() {
|
||||||
// LoadXexContinue: finishes loading XEX after a patch has been applied (or
|
// LoadXexContinue: finishes loading XEX after a patch has been applied (or
|
||||||
// patch wasn't found)
|
// patch wasn't found)
|
||||||
|
|
|
@ -76,6 +76,8 @@ class UserModule : public XModule {
|
||||||
|
|
||||||
X_STATUS LoadFromFile(const std::string_view path);
|
X_STATUS LoadFromFile(const std::string_view path);
|
||||||
X_STATUS LoadFromMemory(const void* addr, const size_t length);
|
X_STATUS LoadFromMemory(const void* addr, const size_t length);
|
||||||
|
X_STATUS LoadFromMemoryNamed(const std::string_view name, const void* addr,
|
||||||
|
const size_t length);
|
||||||
X_STATUS LoadContinue();
|
X_STATUS LoadContinue();
|
||||||
X_STATUS Unload();
|
X_STATUS Unload();
|
||||||
|
|
||||||
|
|
|
@ -91,19 +91,28 @@ dword_result_t XexGetModuleSection_entry(lpvoid_t hmodule, lpstring_t name,
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(XexGetModuleSection, kModules, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(XexGetModuleSection, kModules, kImplemented);
|
||||||
|
|
||||||
dword_result_t XexLoadImage_entry(lpstring_t module_name, dword_t module_flags,
|
dword_result_t xeXexLoadImage(
|
||||||
dword_t min_version, lpdword_t hmodule_ptr) {
|
lpstring_t module_name, dword_t module_flags, dword_t min_version,
|
||||||
|
lpdword_t hmodule_ptr,
|
||||||
|
const std::function<object_ref<UserModule>()>& load_callback,
|
||||||
|
bool isFromMemory) {
|
||||||
X_STATUS result = X_STATUS_NO_SUCH_FILE;
|
X_STATUS result = X_STATUS_NO_SUCH_FILE;
|
||||||
|
|
||||||
uint32_t hmodule = 0;
|
uint32_t hmodule = 0;
|
||||||
auto module = kernel_state()->GetModule(module_name.value());
|
auto module = kernel_state()->GetModule(module_name.value());
|
||||||
if (module) {
|
if (module) {
|
||||||
|
if (isFromMemory) {
|
||||||
|
// Existing module found; return error status.
|
||||||
|
*hmodule_ptr = hmodule;
|
||||||
|
return X_STATUS_OBJECT_NAME_COLLISION;
|
||||||
|
} else {
|
||||||
// Existing module found.
|
// Existing module found.
|
||||||
hmodule = module->hmodule_ptr();
|
hmodule = module->hmodule_ptr();
|
||||||
result = X_STATUS_SUCCESS;
|
result = X_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not found; attempt to load as a user module.
|
// Not found; attempt to load as a user module.
|
||||||
auto user_module = kernel_state()->LoadUserModule(module_name.value());
|
auto user_module = load_callback();
|
||||||
if (user_module) {
|
if (user_module) {
|
||||||
kernel_state()->FinishLoadingUserModule(user_module);
|
kernel_state()->FinishLoadingUserModule(user_module);
|
||||||
// Give up object ownership, this reference will be released by the last
|
// Give up object ownership, this reference will be released by the last
|
||||||
|
@ -125,8 +134,31 @@ dword_result_t XexLoadImage_entry(lpstring_t module_name, dword_t module_flags,
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dword_result_t XexLoadImage_entry(lpstring_t module_name, dword_t module_flags,
|
||||||
|
dword_t min_version, lpdword_t hmodule_ptr) {
|
||||||
|
auto load_callback = [module_name] {
|
||||||
|
return kernel_state()->LoadUserModule(module_name.value());
|
||||||
|
};
|
||||||
|
return xeXexLoadImage(module_name, module_flags, min_version, hmodule_ptr,
|
||||||
|
load_callback, false);
|
||||||
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(XexLoadImage, kModules, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(XexLoadImage, kModules, kImplemented);
|
||||||
|
|
||||||
|
dword_result_t XexLoadImageFromMemory_entry(lpdword_t buffer, dword_t size,
|
||||||
|
lpstring_t module_name,
|
||||||
|
dword_t module_flags,
|
||||||
|
dword_t min_version,
|
||||||
|
lpdword_t hmodule_ptr) {
|
||||||
|
auto load_callback = [module_name, buffer, size] {
|
||||||
|
return kernel_state()->LoadUserModuleFromMemory(module_name.value(), buffer,
|
||||||
|
size);
|
||||||
|
};
|
||||||
|
return xeXexLoadImage(module_name, module_flags, min_version, hmodule_ptr,
|
||||||
|
load_callback, true);
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(XexLoadImageFromMemory, kModules, kImplemented);
|
||||||
|
|
||||||
dword_result_t XexLoadExecutable_entry(lpstring_t module_name,
|
dword_result_t XexLoadExecutable_entry(lpstring_t module_name,
|
||||||
dword_t module_flags,
|
dword_t module_flags,
|
||||||
dword_t min_version,
|
dword_t min_version,
|
||||||
|
|
Loading…
Reference in New Issue