From 2f99a77662fb396659a66be1721bff9779ed67d5 Mon Sep 17 00:00:00 2001 From: Archie_UwU Date: Tue, 21 Nov 2023 20:13:59 +0100 Subject: [PATCH] Exported module operation callbacks - Added support for having plugins export their ModuleOperationCallback routine for instant registration without the need for a ObpSetModuleOperationCallback - Updated function prototype for Module Operation Callbacks to allow for easy and backwards-compatible extensions - Fixed possible crashes on unload with module operation callbacks of unmapped modules being invoked --- Aurie/source/AurieMain.cpp | 1 + .../framework/Module Manager/module.cpp | 27 ++++++++++++++++--- .../framework/Module Manager/module.hpp | 1 + .../framework/Object Manager/object.cpp | 20 +++++++++++++- .../framework/Object Manager/object.hpp | 5 ++++ Aurie/source/framework/shared.hpp | 19 +++++++++++-- TestModule/source/Aurie/shared.hpp | 19 +++++++++++-- 7 files changed, 84 insertions(+), 8 deletions(-) diff --git a/Aurie/source/AurieMain.cpp b/Aurie/source/AurieMain.cpp index f33a66b..154c8cc 100644 --- a/Aurie/source/AurieMain.cpp +++ b/Aurie/source/AurieMain.cpp @@ -82,6 +82,7 @@ void ArProcessAttach(HINSTANCE Instance) nullptr, nullptr, nullptr, + nullptr, 0, initial_module ) diff --git a/Aurie/source/framework/Module Manager/module.cpp b/Aurie/source/framework/Module Manager/module.cpp index 918c179..d8d88e5 100644 --- a/Aurie/source/framework/Module Manager/module.cpp +++ b/Aurie/source/framework/Module Manager/module.cpp @@ -10,6 +10,7 @@ namespace Aurie IN AurieEntry ModulePreinitialize, IN AurieEntry ModuleUnload, IN AurieLoaderEntry FrameworkInitialize, + IN AurieModuleCallback ModuleOperationCallback, IN uint8_t BitFlags, OUT AurieModule& Module ) @@ -23,6 +24,7 @@ namespace Aurie temp_module.ModuleInitialize = ModuleInitialize; temp_module.ModulePreinitialize = ModulePreinitialize; temp_module.FrameworkInitialize = FrameworkInitialize; + temp_module.ModuleOperationCallback = ModuleOperationCallback; temp_module.ModuleUnload = ModuleUnload; last_status = MdpQueryModuleInformation( @@ -302,13 +304,17 @@ namespace Aurie ); } + // Remove the module's operation callback + Module->ModuleOperationCallback = nullptr; + + // Destory all interfaces created by the module for (auto& module_interface : Module->InterfaceTable) { if (module_interface.Interface) module_interface.Interface->Destroy(); } - // Invalidate all interfaces + // Wipe them off the interface table // Note these can't be freed, they're allocated by the owner module Module->InterfaceTable.clear(); @@ -344,7 +350,11 @@ namespace Aurie if (Module == g_ArInitialImage) return AURIE_SUCCESS; - ObpDispatchModuleOperationCallbacks(Module, Entry, true); + ObpDispatchModuleOperationCallbacks( + Module, + Entry, + true + ); AurieStatus module_status = Module->FrameworkInitialize( g_ArInitialImage, @@ -354,7 +364,11 @@ namespace Aurie Module ); - ObpDispatchModuleOperationCallbacks(Module, Entry, false); + ObpDispatchModuleOperationCallbacks( + Module, + Entry, + false + ); return module_status; } @@ -424,6 +438,8 @@ namespace Aurie // Find all the required functions uintptr_t framework_init_offset = PpFindFileExportByName(ImagePath, "__AurieFrameworkInit"); uintptr_t module_init_offset = PpFindFileExportByName(ImagePath, "ModuleInitialize"); + + uintptr_t module_callback_offset = PpFindFileExportByName(ImagePath, "ModuleOperationCallback"); uintptr_t module_preload_offset = PpFindFileExportByName(ImagePath, "ModulePreinitialize"); uintptr_t module_unload_offset = PpFindFileExportByName(ImagePath, "ModuleUnload"); @@ -431,6 +447,7 @@ namespace Aurie AurieEntry module_preload = reinterpret_cast((char*)image_base + module_preload_offset); AurieEntry module_unload = reinterpret_cast((char*)image_base + module_unload_offset); AurieLoaderEntry fwk_init = reinterpret_cast((char*)image_base + framework_init_offset); + AurieModuleCallback module_callback = reinterpret_cast((char*)image_base + module_callback_offset); // Verify image integrity last_status = Internal::MmpVerifyCallback(image_base, module_init); @@ -449,6 +466,9 @@ namespace Aurie if (!module_unload_offset) module_unload = nullptr; + if (!module_callback_offset) + module_callback = nullptr; + // Create the module object AurieModule module_object = {}; last_status = Internal::MdpCreateModule( @@ -458,6 +478,7 @@ namespace Aurie module_preload, module_unload, fwk_init, + module_callback, 0, module_object ); diff --git a/Aurie/source/framework/Module Manager/module.hpp b/Aurie/source/framework/Module Manager/module.hpp index e0b2833..fcf5516 100644 --- a/Aurie/source/framework/Module Manager/module.hpp +++ b/Aurie/source/framework/Module Manager/module.hpp @@ -48,6 +48,7 @@ namespace Aurie IN AurieEntry ModulePreinitialize, IN AurieEntry ModuleUnload, IN AurieLoaderEntry FrameworkInitialize, + IN AurieModuleCallback ModuleOperationCallback, IN uint8_t BitFlags, OUT AurieModule& Module ); diff --git a/Aurie/source/framework/Object Manager/object.cpp b/Aurie/source/framework/Object Manager/object.cpp index 0e6de2f..2cdce24 100644 --- a/Aurie/source/framework/Object Manager/object.cpp +++ b/Aurie/source/framework/Object Manager/object.cpp @@ -110,6 +110,11 @@ namespace Aurie else if (Routine == AffectedModule->ModuleUnload) current_operation_type = AURIE_OPERATION_UNLOAD; + AurieOperationInfo operation_information = ObpCreateOperationInfo( + AffectedModule, + IsFutureCall + ); + for (auto& loaded_module : g_LdrModuleList) { if (!loaded_module.ModuleOperationCallback) @@ -118,7 +123,7 @@ namespace Aurie loaded_module.ModuleOperationCallback( AffectedModule, current_operation_type, - IsFutureCall + &operation_information ); } } @@ -133,6 +138,19 @@ namespace Aurie return AURIE_SUCCESS; } + AurieOperationInfo ObpCreateOperationInfo( + IN AurieModule* Module, + IN bool IsFutureCall + ) + { + AurieOperationInfo operation_information = {}; + + operation_information.IsFutureCall = IsFutureCall; + operation_information.ModuleBaseAddress = MdpGetModuleBaseAddress(Module); + + return operation_information; + } + AurieStatus ObpDestroyInterface( IN AurieModule* Module, IN AurieInterfaceBase* Interface, diff --git a/Aurie/source/framework/Object Manager/object.hpp b/Aurie/source/framework/Object Manager/object.hpp index 4dfad7d..3f807d7 100644 --- a/Aurie/source/framework/Object Manager/object.hpp +++ b/Aurie/source/framework/Object Manager/object.hpp @@ -43,6 +43,11 @@ namespace Aurie IN AurieInterfaceTableEntry& Entry ); + AurieOperationInfo ObpCreateOperationInfo( + IN AurieModule* Module, + IN bool IsFutureCall + ); + AurieStatus ObpDestroyInterface( IN AurieModule* Module, IN AurieInterfaceBase* Interface, diff --git a/Aurie/source/framework/shared.hpp b/Aurie/source/framework/shared.hpp index cc70063..88fad5b 100644 --- a/Aurie/source/framework/shared.hpp +++ b/Aurie/source/framework/shared.hpp @@ -48,7 +48,7 @@ #endif // AURIE_FWK_MINOR #ifndef AURIE_FWK_PATCH -#define AURIE_FWK_PATCH 1 +#define AURIE_FWK_PATCH 2 #endif // AURIE_FWK_PATCH @@ -145,6 +145,21 @@ namespace Aurie ) = 0; }; + struct AurieOperationInfo + { + union + { + uint8_t Flags; + struct + { + bool IsFutureCall : 1; + bool Reserved : 7; + }; + }; + + PVOID ModuleBaseAddress; + }; + // Always points to the initial Aurie image // Initialized in either ArProcessAttach or __aurie_fwk_init inline AurieModule* g_ArInitialImage = nullptr; @@ -165,7 +180,7 @@ namespace Aurie using AurieModuleCallback = void(*)( IN AurieModule* AffectedModule, IN AurieModuleOperationType OperationType, - IN bool IsFutureCall + OPTIONAL IN OUT AurieOperationInfo* OperationInfo ); } diff --git a/TestModule/source/Aurie/shared.hpp b/TestModule/source/Aurie/shared.hpp index cc70063..88fad5b 100644 --- a/TestModule/source/Aurie/shared.hpp +++ b/TestModule/source/Aurie/shared.hpp @@ -48,7 +48,7 @@ #endif // AURIE_FWK_MINOR #ifndef AURIE_FWK_PATCH -#define AURIE_FWK_PATCH 1 +#define AURIE_FWK_PATCH 2 #endif // AURIE_FWK_PATCH @@ -145,6 +145,21 @@ namespace Aurie ) = 0; }; + struct AurieOperationInfo + { + union + { + uint8_t Flags; + struct + { + bool IsFutureCall : 1; + bool Reserved : 7; + }; + }; + + PVOID ModuleBaseAddress; + }; + // Always points to the initial Aurie image // Initialized in either ArProcessAttach or __aurie_fwk_init inline AurieModule* g_ArInitialImage = nullptr; @@ -165,7 +180,7 @@ namespace Aurie using AurieModuleCallback = void(*)( IN AurieModule* AffectedModule, IN AurieModuleOperationType OperationType, - IN bool IsFutureCall + OPTIONAL IN OUT AurieOperationInfo* OperationInfo ); }