Add -onlinefix support for games that use EOS matchmaking#97
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a5cdee8974
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| ## Usage | ||
| 1. Run `build.bat` from the project root to build the project. | ||
| 2. Copy generated `dwmapi.dll`, `xinput1_4.dll` and `OpenSteamTool.dll` to the Steam root directory. |
There was a problem hiding this comment.
Include the EOS payload in install instructions
For a fresh install following this Usage step, OnlineFix.dll is never copied to the Steam root, but InitializeSteamComponents now sets PayloadPath to <Steam>\OnlineFix.dll and the injection hook loads exactly that path. That means the new EOS -onlinefix path silently fails to install the payload even though the README says EOS matchmaking is supported; the copy step should include OnlineFix.dll.
Useful? React with 👍 / 👎.
| oCreateProcessW = reinterpret_cast<CreateProcessW_t> (GetProcAddress(k32, "CreateProcessW")); | ||
| oCreateProcessAsUserW = reinterpret_cast<CreateProcessAsUserW_t>(GetProcAddress(k32, "CreateProcessAsUserW")); |
There was a problem hiding this comment.
Follow launchers that use ANSI process creation
When the injected process is only a launcher and it starts the actual EOS game via CreateProcessA/CreateProcessAsUserA, this propagation hook never runs because it only resolves and attaches the wide-character exports. In that scenario the child process starts without OnlineFix.dll, so EOSSDK-Win64-Shipping.dll loads unpatched and EOS matchmaking support fails for those launcher-based games; add the ANSI entry points or hook a common lower-level process creation path.
Useful? React with 👍 / 👎.
|
Thanks for the detailed explanation and for putting this together. That said, I am currently not comfortable merging a feature that injects a companion DLL into the game process. One of the boundaries I want to keep for OpenSteamTool is that it mainly works on the SteamClient side. However, I understand that EOS support may be useful for some users. If you want, you can open a GitHub Discussion with a poll about this approach, so the community can share their opinions on whether OpenSteamTool should support EOS onlinefix through an optional injected payload. If there is strong interest and the maintenance scope are clear, I may reconsider it later, possibly as an optional or experimental feature rather than something enabled by default. |
|
@OpenSteam001 Since you're not comfortable with injecting a companion DLL (to be fair, neither am I), and it goes against the boundary of OpenSteamTool. Is it possible to come to a compromise where OpenSteamTool provides support for injecting DLLs into the game If you agree, then I can open another PR that adds third-party DLL injection support along with probably an API of some sort for all the information the DLL may need. |
|
@Ran-Mewo I’m okay with OpenSteamTool providing a generic, opt-in DLL injection API/support layer, as long as OpenSteamTool itself does not ship or maintain the OnlineFix DLL. The actual third-party DLL can stay in your repo, and users would explicitly configure it in opensteamtool.toml. Coincidentally, I’ve been working on game PID / pipe monitoring recently, mainly to distinguish the Denuvo authorization pipe from the game’s normal runtime pipe. During that work, I inevitably need to know when the real game process is created and associate some process-related information with the Steam pipe. Because of that, I think the IPC handshake stage — for example when the game process calls something like SteamAPI_Init and establishes communication with Steam — may be a better injection point than raw CreateProcess interception.At that point,We wouldn't need a SelfPropagate-style mechanism. That said, I haven’t actually tested this design yet, so this is only my current preferred direction rather than a final decision. I’ll probably finish the pipe monitoring work within the next few days. After that, I can take a closer look at the injection mechanism you proposed and evaluate how it might fit into OpenSteamTool. |
|
Alright, that sounds great! Let me know what direction you want me to take after you're done with the new changes. Thanks! |
|
Hey guys. I absolutely don't have your level of expertise in this area, so here's what I'd like as an "Open Steam Tools user" regarding online fixes. What I love about OpenSteamTools is its almost "Plug N play" aspect. I have my lua files that I drop into my lua folder and it appears on steam, I can download the game and apply or not goldberg to the game, in short, I love that. Regarding the online fix, that's where I didn't quite understand the discussion so here's my point of view: I found the solution of simply adding -onlinefix to the game's startup parameters exceptional because it bypassed the need to go to a third-party site for this, except that, obviously, as previously mentioned, this solution does not work for all games. That's exactly why, if you're doing a straw poll for the community, I am 100% in favor of integrating this. It would perfectly restore that seamless "plug and play" experience. Basically, would this completely eliminate the need for me to manually find, download, and drag-and-drop specific OnlineFix files into each game's folder? Thanks a lot for your hard work on this project! |
|
@26mataa yes So far in my testing, every online game just works now |
|
@Ran-Mewo That sounds good to me! |
Extends the existing
-onlinefixflag to also work for games whose multiplayer runs on EOS instead of Steam. The 480-AppId trick can't reach those games (EOS traffic never crosses Steam) so the fix has to live inside the game process. This PR adds a small companion DLL (OnlineFix.dll) that the host injects into the game on launch, plus the host-side hook needed to inject it.It's a very small DLL and doesn't need much maintenance. I know you might be against it, but it's a really simple solution that worked for all games I've tested.
Behavior for
-onlinefixgames that use Steam matchmaking is unchanged.Explanation
Host side
Hooks_Inject— hooksCreateProcessW/CreateProcessAsUserW.Hooks_Misc::OnSpawnProcessHitqueues(exe basename → real AppId)when it sees a-onlinefixgame.CREATE_SUSPENDED, and getsOnlineFix.dllinjected via a remote-threadLoadLibraryW, then resumes.CreateProcessWfire on different threads.RemoteInject::LoadDll—VirtualAllocEx+WriteProcessMemory+CreateRemoteThread(LoadLibraryW). Header-only since the host andOnlineFix.dllare separate binaries that can't share a.obj.Payload (
src/Payload/, built asOnlineFix.dll)payload.cpp— subscribes toLdrRegisterDllNotificationand also walksEnumProcessModules, soEOSSDK-Win64-Shipping.dllis caught whether it's already loaded or arrives later.EosBridge— the actual patch:EOS_Connect_Loginis rewritten asCreateDeviceId→ re-LoginwithEOS_ECT_DEVICEID_ACCESS_TOKEN. Device ID auth has no Steam-ticket ownership check.SteamFriends::GetPersonaName, so everyone still sees your actual name.bPresenceEnabledis stripped fromEOS_Lobby_CreateLobby/JoinLobby/JoinLobbyById— Device ID auth has no Epic presence to attach.EOS_IntegratedPlatformOptionsContainer_Addis no-op'd, same reason.SelfPropagate— Does the sameCreateProcess*Whook that the host has but inside the game process. EOS titles are often spawned by a launcher, so the payload has to follow the process tree down to where the SDK actually loads.PayloadLog— per-pid file at<Steam>/opensteamtool/payload/<pid>.log.Debugonly;Releaseis empty stubs. This payload folder is also deleted on every Steam launch so that it doesn't bloat the disk.Config / wiring
[inject].enabledtoggle (defaulttrue). Disabling skips the payload entirely; the 480 swap is unaffected.injectlog module.OnlineFixis a newadd_library(... SHARED)target insrc/CMakeLists.txtlinkingdetours+psapi, withOPENSTEAMTOOL_LOGGING_ENABLEDonly onDebug— same convention as the host.[inject]block documented in the example TOML.Notes on the diff
The diffs against
README.md,src/CMakeLists.txt,src/Utils/Config.cpp,src/Utils/Config.handsrc/dllmain.hlook much larger than they really are because.gitattributeshaseol=lfbut the existing blobs for those files are CRLF, sogit addre-normalizes them as a side effect of editing. Reviewing with?w=1(orgit diff --ignore-all-space) shows the actual logical changes, which are small.