1
Fork 0
mirror of https://github.com/redstrate/LauncherTweaks.git synced 2025-05-20 17:37:46 +00:00

Add option to disable WebView2 install and boot version checks

These use terribly made function sigs but do work. WebView2 keeps
failing to install, so this is actuallt quite useful for me.
This commit is contained in:
Joshua Goins 2025-04-22 15:45:08 -04:00
parent 78548403e6
commit f17c70d3ac
3 changed files with 129 additions and 1 deletions

View file

@ -4,8 +4,10 @@ Tweaks for the official FFXIV launcher.
## Features ## Features
* Allows configuring the launcher URL, enabling you to write custom launcher pages. * Configure the launcher URL, enabling you to write custom launcher pages.
* Force the launcher/boot executable to use the system proxy. (The web browser portions of the launcher already use the system proxy.) * Force the launcher/boot executable to use the system proxy. (The web browser portions of the launcher already use the system proxy.)
* Bypasses the (soft) WebView2 requirement introduced in Patch 7.21.
* Disable the boot version check.
## Usage ## Usage

View file

@ -4,6 +4,20 @@ use serde::Deserialize;
pub struct Config { pub struct Config {
pub launcher_url: Option<String>, pub launcher_url: Option<String>,
pub winhttp_proxy: Option<String>, pub winhttp_proxy: Option<String>,
#[serde(default = "Config::default_disable_webview2_install")]
pub disable_webview2_install: bool,
#[serde(default = "Config::default_disable_boot_version_check")]
pub disable_boot_version_check: bool,
}
impl Config {
fn default_disable_webview2_install() -> bool {
false
}
fn default_disable_boot_version_check() -> bool {
false
}
} }
pub fn get_config() -> Config { pub fn get_config() -> Config {

View file

@ -9,6 +9,8 @@ use utilities::{find_signature, find_symbol, get_utf16_bytes, show_message};
use proxy_dll::proxy; use proxy_dll::proxy;
use retour::static_detour; use retour::static_detour;
use skidscan::Signature; use skidscan::Signature;
use std::ffi::CStr;
use std::ffi::c_char;
use std::ffi::c_void; use std::ffi::c_void;
use windows::{Win32::Networking::WinHttp::*, core::*}; use windows::{Win32::Networking::WinHttp::*, core::*};
@ -111,6 +113,114 @@ fn use_system_proxy() {
} }
} }
static_detour! {
static InstallWebView2: fn(u64) -> i32;
}
fn install_webview2_detour(_unk: u64) -> i32 {
// non-zero: will let us through, even if we don't have WebView2
// 0 = will do the "webview2 failed to install message"
return 1;
}
fn disable_webview2_install() {
let config = get_config();
if !config.disable_webview2_install {
return;
}
unsafe {
// TODO: wow, that func sig is baaaad
let install_webview2_addr =
skidscan::signature!("48 89 5c 24 10 48 89 7c 24 18 55 48 8d 6c 24 c0 48 81 ec 40 01 00 00 48 8b 05 6a 4f 0f 00 48 33 c4 48 89 45 30 48 8b d9 e8 d3 cb ff ff").scan_module(BOOT_FILENAME).unwrap();
let install_webview2_fn =
std::mem::transmute::<*mut u8, fn(u64) -> i32>(install_webview2_addr);
InstallWebView2
.initialize(install_webview2_fn, install_webview2_detour)
.expect("Failed to initialize InstallWebView2 hook");
InstallWebView2
.enable()
.expect("Failed to hook into InstallWebView2");
}
}
static_detour! {
static GetConfigOption: fn(*const ConfigBase, u32) -> *mut ConfigEntry;
}
#[repr(C)]
struct ConfigEntry {
_padding: [u8; 0x10],
name: *const c_char,
config_type: ConfigType,
_padding2: [u8; 0x4],
config_value: ConfigValue,
}
#[repr(i32)]
#[derive(Debug)]
enum ConfigType {
Unused = 0,
Category = 1,
UInt = 2,
Float = 3,
String = 4,
}
#[repr(C)]
union ConfigValue {
UInt: u32,
Float: f32,
}
#[repr(C)]
struct ConfigBase {
_padding: [u8; 0x18],
ConfigEntry: *const ConfigEntry,
}
fn get_config_option_detour(
config_base: *const ConfigBase,
config_option: u32,
) -> *mut ConfigEntry {
unsafe {
let option = GetConfigOption.call(config_base, config_option);
if option != std::ptr::null_mut() {
if (*option).name != std::ptr::null() {
let name = CStr::from_ptr((*option).name as *const i8);
if name.to_str().unwrap() == "SkipBootupVercheck" {
(*option).config_value.UInt = 1;
}
}
}
option
}
}
fn disable_boot_version_check() {
let config = get_config();
if !config.disable_boot_version_check {
return;
}
unsafe {
// TODO: *terrible* function man
let get_config_option_addr = skidscan::signature!("48 89 5c 24 08 48 89 6c 24 10 48 89 74 24 18 57 48 83 ec 20 8b f2 48 8d b9 c8 00 00 00 48 8b e9 33 db").scan_module(BOOT_FILENAME).unwrap();
let get_config_option_fn = std::mem::transmute::<
*mut u8,
fn(*const ConfigBase, u32) -> *mut ConfigEntry,
>(get_config_option_addr);
GetConfigOption
.initialize(get_config_option_fn, get_config_option_detour)
.expect("Failed to initialize GetConfigOption hook");
GetConfigOption
.enable()
.expect("Failed to hook into GetConfigOption");
}
}
#[proxy] #[proxy]
fn main() { fn main() {
// Emit panic messages with message boxes // Emit panic messages with message boxes
@ -141,6 +251,8 @@ fn main() {
} }
BOOT_FILENAME => { BOOT_FILENAME => {
use_system_proxy(); use_system_proxy();
disable_webview2_install();
disable_boot_version_check();
} }
_ => {} _ => {}
} }