Compare commits
1 Commits
3174fe4c1f
...
c5424158b9
| Author | SHA1 | Date | |
|---|---|---|---|
| c5424158b9 |
@@ -24,6 +24,7 @@
|
|||||||
//! falls back to it, so an existing working setup cannot be broken by upgrading.
|
//! falls back to it, so an existing working setup cannot be broken by upgrading.
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::io::{BufRead, BufReader};
|
use std::io::{BufRead, BufReader};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Child, Command, Stdio};
|
use std::process::{Child, Command, Stdio};
|
||||||
@@ -67,6 +68,7 @@ pub fn launch(
|
|||||||
for (k, v) in &profile.env {
|
for (k, v) in &profile.env {
|
||||||
cmd.env(k, v);
|
cmd.env(k, v);
|
||||||
}
|
}
|
||||||
|
cmd.env("WINEDLLOVERRIDES", hook_dll_overrides(&profile.env));
|
||||||
if !profile.wine_prefix.trim().is_empty() {
|
if !profile.wine_prefix.trim().is_empty() {
|
||||||
cmd.env("WINEPREFIX", &profile.wine_prefix);
|
cmd.env("WINEPREFIX", &profile.wine_prefix);
|
||||||
}
|
}
|
||||||
@@ -93,6 +95,30 @@ pub fn launch(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `WINEDLLOVERRIDES` value the game must be started with.
|
||||||
|
///
|
||||||
|
/// The hook ships as a `version.dll` proxy inside the game directory, and Proton
|
||||||
|
/// prefers a local DLL over its own builtin ONLY when `WINEDLLOVERRIDES` names it
|
||||||
|
/// (see `setup::STEAM_LAUNCH_OPTIONS`). Steam users get that from their launch
|
||||||
|
/// options; when the launcher spawns the runner itself, nothing else supplies it.
|
||||||
|
///
|
||||||
|
/// Without it the failure is silent and badly misleading: the hook never loads, so
|
||||||
|
/// the `openfut.cfg` the launcher just wrote is inert, the game ignores the
|
||||||
|
/// configured Blaze ports, and `/etc/hosts` quietly routes it to whatever answers
|
||||||
|
/// on EA's real ports. It looks like a working launch against the configured
|
||||||
|
/// server while actually talking to a different one.
|
||||||
|
///
|
||||||
|
/// A profile that already pins `version=` wins: an operator overriding the hijack
|
||||||
|
/// deliberately must not be silently overruled.
|
||||||
|
fn hook_dll_overrides(env: &BTreeMap<String, String>) -> String {
|
||||||
|
const HOOK: &str = "version=n,b";
|
||||||
|
match env.get("WINEDLLOVERRIDES").map(|v| v.trim()) {
|
||||||
|
Some(existing) if existing.contains("version=") => existing.to_string(),
|
||||||
|
Some(existing) if !existing.is_empty() => format!("{existing};{HOOK}"),
|
||||||
|
_ => HOOK.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create the Wine prefix's `dosdevices` entries the profile asks for.
|
/// Create the Wine prefix's `dosdevices` entries the profile asks for.
|
||||||
///
|
///
|
||||||
/// Equivalent to `mkdir -p $WINEPREFIX/dosdevices && ln -sfn <target> <link>`:
|
/// Equivalent to `mkdir -p $WINEPREFIX/dosdevices && ln -sfn <target> <link>`:
|
||||||
@@ -463,4 +489,32 @@ mod tests {
|
|||||||
let err = launch(&profile, &log(), || {}).unwrap_err().to_string();
|
let err = launch(&profile, &log(), || {}).unwrap_err().to_string();
|
||||||
assert!(err.contains("game_dir does not exist"), "{err}");
|
assert!(err.contains("game_dir does not exist"), "{err}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn a_profile_without_overrides_still_gets_the_hook_hijack() {
|
||||||
|
// The regression this guards: FIFA launched from the launcher ignored the
|
||||||
|
// configured Blaze ports entirely, because Proton loaded its own builtin
|
||||||
|
// version.dll and the hook proxy never ran. The launch looked healthy.
|
||||||
|
assert_eq!(hook_dll_overrides(&BTreeMap::new()), "version=n,b");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unrelated_overrides_are_preserved_and_appended_to() {
|
||||||
|
let env = BTreeMap::from([("WINEDLLOVERRIDES".to_string(), "d3d11=n".to_string())]);
|
||||||
|
assert_eq!(hook_dll_overrides(&env), "d3d11=n;version=n,b");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn an_explicit_version_override_is_never_overruled() {
|
||||||
|
// An operator disabling the hijack on purpose must win, otherwise the
|
||||||
|
// setting is a lie.
|
||||||
|
let env = BTreeMap::from([("WINEDLLOVERRIDES".to_string(), "version=b".to_string())]);
|
||||||
|
assert_eq!(hook_dll_overrides(&env), "version=b");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn a_blank_override_is_treated_as_absent_rather_than_appended_to() {
|
||||||
|
let env = BTreeMap::from([("WINEDLLOVERRIDES".to_string(), " ".to_string())]);
|
||||||
|
assert_eq!(hook_dll_overrides(&env), "version=n,b");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user