mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-05 13:20:11 +00:00
Since #12621 a Windows runtime module that another runtime module needs is deferred instead of started at boot, but loading a deferred module only started that module. A Unity plugin such as SPFXUnityPlugin that calls into a deferred module it needs (Il2CppUserAssemblies in Media/Modules) ran against code whose initializers had never run, and PPSA03743 crashed about 2.6 s in. A deferred module's initialization table now lists the deferred modules it depends on (names, after the initializer array, behind a magic number so older output reads as having none). DynamicLoader starts those first, transitively and once each through the existing per-module state, with the start arguments of the load that began it, then starts the module itself. The module start result stays the module's own. Boot still starts no deferred module. Linux is unchanged: its deferred modules still start only when loaded.
42 lines
1.5 KiB
C++
42 lines
1.5 KiB
C++
#include "GuestDeferredModule.hpp"
|
|
#include <atomic>
|
|
#include <cstddef>
|
|
#include <cstdlib>
|
|
|
|
#ifdef GUEST_DEFERRED_DEPENDENT_FIXTURE
|
|
static constexpr bool Dependent = true;
|
|
#else
|
|
static constexpr bool Dependent = false;
|
|
#endif
|
|
|
|
static std::atomic<int> starts{0};
|
|
static std::atomic<std::size_t> lastBytes{0};
|
|
static std::atomic<int> constructors{0};
|
|
|
|
extern "C" int APS5_VABI DeferredStart_nid_no_patch(std::size_t bytes, const void* argument, void*) {
|
|
++starts;
|
|
lastBytes = bytes;
|
|
if (bytes != 0) {
|
|
if (bytes != sizeof(GuestDeferredModuleArgs) || !argument) std::abort();
|
|
const auto& args = *static_cast<const GuestDeferredModuleArgs*>(argument);
|
|
if (args.Mode == 1) {
|
|
if (!SetEvent(args.Entered) || WaitForSingleObject(args.Release, 10000) != WAIT_OBJECT_0)
|
|
std::abort();
|
|
} else if (args.Mode == 2 || (args.Mode == 3 && Dependent) || (args.Mode == 4 && !Dependent)) args.Reenter(args.Path);
|
|
}
|
|
return GuestDeferredModuleResult;
|
|
}
|
|
|
|
extern "C" void APS5_VABI DeferredConstructor_nid_no_patch(int, char**, char**) {
|
|
++constructors;
|
|
}
|
|
|
|
using Initializer = void (APS5_VABI*)(int, char**, char**);
|
|
extern "C" {
|
|
Initializer DeferredInitializerSlot_nid_no_patch = DeferredConstructor_nid_no_patch;
|
|
}
|
|
|
|
extern "C" int APS5_VABI DeferredStarts_nid_no_patch() { return starts.load(); }
|
|
extern "C" int APS5_VABI DeferredConstructors_nid_no_patch() { return constructors.load(); }
|
|
extern "C" int APS5_VABI DeferredLastArgumentBytes_nid_no_patch() { return static_cast<int>(lastBytes.load()); }
|