From 6c44aeeff33d629d72d895c1919109dfb791abec Mon Sep 17 00:00:00 2001 From: Vurv <56230599+Vurv78@users.noreply.github.com> Date: Sun, 5 Dec 2021 13:17:55 -0800 Subject: [PATCH] 0.7.0 * winapi * Fix double loading * awesome proper changelogs maybe later --- Cargo.toml | 5 ++- src/detours/mod.rs | 1 - src/lib.rs | 102 +++++++++++++++++++++++++-------------------- src/sys/runlua.rs | 41 +++++++----------- src/sys/util.rs | 10 ++--- 5 files changed, 79 insertions(+), 80 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 55cd368..031df3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "autorun" -version = "0.6.1" +version = "0.7.0" authors = ["Vurv78 "] edition = "2021" @@ -28,9 +28,10 @@ log = { version = "0.4.14", optional = true } simplelog = { version = "0.11.0", optional = true } regex = "1.5.4" +winapi = { version = "0.3.9", features = ["wincon", "consoleapi"] } [features] -default = ["runner"] +default = ["runner", "logging"] runner = [] # Disabled by default for now as this breaks autorun. diff --git a/src/detours/mod.rs b/src/detours/mod.rs index be1aff4..2e2088a 100644 --- a/src/detours/mod.rs +++ b/src/detours/mod.rs @@ -37,7 +37,6 @@ lazy_detour! { extern "C" fn luaL_newstate() -> LuaState { let state = LUAL_NEWSTATE_H.call(); - debug!("Got client state through luaL_newstate"); setClientState(state); state } diff --git a/src/lib.rs b/src/lib.rs index a3cad0d..c7e21d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,14 +20,15 @@ mod input; // Console input mod sys; // Configs static SENDER: OnceCell> = OnceCell::new(); -const DLL_PROCESS_ATTACH: u32 = 1; -const DLL_PROCESS_DETACH: u32 = 0; -extern "system" { - fn AllocConsole() -> bool; - fn FreeConsole() -> bool; - fn GetLastError() -> u32; -} +use winapi::{ + shared::minwindef::TRUE, + um::{ + consoleapi::AllocConsole, + errhandlingapi::GetLastError, + wincon::{FreeConsole, GetConsoleWindow}, + }, +}; #[derive(Error, Debug)] enum InitializeError { @@ -49,7 +50,6 @@ enum ExitError { fn init() -> Result<(), InitializeError> { unsafe { - println!("Init!"); logging::init()?; detours::init()?; } @@ -80,43 +80,65 @@ fn init() -> Result<(), InitializeError> { Ok(()) } -fn cleanup() -> Result<(), ExitError> { - unsafe { detours::cleanup()? }; +// Returns if successfully initialized +fn attach() -> bool { + unsafe { + if GetConsoleWindow().is_null() { + if AllocConsole() != TRUE { + // Console didn't exist and couldn't allocate one now, hard error + error!("Failed to allocate console. {}", GetLastError()); + return false; + } + } else { + debug!("Found existing console!"); + } + } - if let Some(sender) = SENDER.get() { - sender.send(()).map_err(|_| ExitError::MPSCFailure)?; + if let Err(why) = init() { + match why { + InitializeError::LogInitError(y) => eprintln!("Failed to initialize logging. [{}]", y), + _ => error!("Failed to initialize Autorun. [{}]", why), + } + false + } else { + true } +} - unsafe { - FreeConsole(); - }; +fn cleanup() { + fn try_cleanup() -> Result<(), ExitError> { + unsafe { detours::cleanup()? }; - Ok(()) + if let Some(sender) = SENDER.get() { + sender.send(()).map_err(|_| ExitError::MPSCFailure)?; + } + + unsafe { + FreeConsole(); + }; + + Ok(()) + } + + if let Err(why) = try_cleanup() { + error!("Failed to inject Autorun. [{}]", why); + } } -// Windows Only. I'm not going to half-ass Linux support (And don't even get me to try and work with OSX..) #[no_mangle] extern "system" fn DllMain(_: *const u8, reason: u32, _: *const u8) -> u32 { + use winapi::um::winnt::{DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH}; + match reason { DLL_PROCESS_ATTACH => { - unsafe { - if !AllocConsole() { - // Assume a console already exists and just log an error. - eprintln!("Failed to allocate console. {}", GetLastError()); - } - } - - if let Err(why) = init() { - error!("Failed to inject Autorun. [{}]", why); - } + attach(); } DLL_PROCESS_DETACH => { - if let Err(why) = cleanup() { - error!("Failed to inject Autorun. [{}]", why); - } + cleanup(); } _ => (), } + 1 } @@ -124,20 +146,12 @@ use rglua::types::LuaState; #[no_mangle] extern "C" fn gmod13_open(state: LuaState) -> i32 { + // DllMain is called prior to this even if Autorun is used as a binary module. + // So only initialize what we haven't already. + use crate::sys::util::initMenuState; - unsafe { - if !AllocConsole() { - // Assume a console already exists and just log an error. - eprintln!("Failed to allocate console. {}", GetLastError()); - } - } - if let Err(why) = init() { - match why { - InitializeError::LogInitError(y) => eprintln!("Failed to initialize logging. [{}]", y), - _ => error!("Failed to initialize Autorun. [{}]", why), - } - } else if let Err(why) = initMenuState(state) { + if let Err(why) = initMenuState(state) { error!("Failed to initialize menu state. [{}]", why); } 0 @@ -145,8 +159,6 @@ extern "C" fn gmod13_open(state: LuaState) -> i32 { #[no_mangle] extern "C" fn gmod13_close(_state: LuaState) -> i32 { - if let Err(why) = cleanup() { - error!("Failed to close Autorun module. [{}]", why); - } + cleanup(); 0 } diff --git a/src/sys/runlua.rs b/src/sys/runlua.rs index 834f48a..ca91608 100644 --- a/src/sys/runlua.rs +++ b/src/sys/runlua.rs @@ -6,6 +6,7 @@ use crate::sys::{ use std::ffi::CString; use rglua::{ + cstr, globals::Lua::{self, GLOBALSINDEX}, lua_shared::*, rstr, @@ -14,7 +15,7 @@ use rglua::{ const NO_LUA_STATE: &str = "Didn't run lua code, lua state is not valid/loaded!"; const INVALID_LOG_LEVEL: *const i8 = - "Invalid log level (Should be 1-5, 1 being Error, 5 being Trace)\0".as_ptr() as *const i8; + cstr!("Invalid log level (Should be 1-5, 1 being Error, 5 being Trace)"); pub fn runLua(realm: Realm, code: String) -> Result<(), &'static str> { // Check if lua state is valid for instant feedback @@ -69,21 +70,9 @@ extern "C" fn sautorun_require(state: LuaState) -> i32 { let raw_path = luaL_checklstring(state, 1, 0); - lua_getfield( - state, - rglua::globals::Lua::GLOBALSINDEX, - "sautorun\0".as_ptr() as *const i8, - ); - lua_getfield( - state, - rglua::globals::Lua::GLOBALSINDEX, - "package\0".as_ptr() as *const i8, - ); - lua_getfield( - state, - rglua::globals::Lua::GLOBALSINDEX, - "loaded\0".as_ptr() as *const i8, - ); + lua_getfield(state, rglua::globals::Lua::GLOBALSINDEX, cstr!("sautorun")); + lua_getfield(state, rglua::globals::Lua::GLOBALSINDEX, cstr!("package")); + lua_getfield(state, rglua::globals::Lua::GLOBALSINDEX, cstr!("loaded")); lua_getfield(state, 2, raw_path); if lua_toboolean(state, -1) != 0 { return 1; @@ -144,39 +133,39 @@ pub fn runLuaEnv( lua_createtable(state, 0, 0); // local t2 = {} lua_pushstring(state, identifier); - lua_setfield(state, -2, "NAME\0".as_ptr() as *const i8); // t2.NAME = ... + lua_setfield(state, -2, cstr!("NAME")); // t2.NAME = ... lua_pushstring(state, dumped_script); - lua_setfield(state, -2, "CODE\0".as_ptr() as *const i8); // t2.CODE = ... + lua_setfield(state, -2, cstr!("CODE")); // t2.CODE = ... if let Ok(ip) = CString::new(ip) { lua_pushstring(state, ip.as_ptr()); } else { lua_pushnil(state); } - lua_setfield(state, -2, "IP\0".as_ptr() as *const i8); + lua_setfield(state, -2, cstr!("IP")); // If this is running before autorun, set SAUTORUN.STARTUP to true. lua_pushboolean(state, startup as i32); - lua_setfield(state, -2, "STARTUP\0".as_ptr() as *const i8); + lua_setfield(state, -2, cstr!("STARTUP")); lua_pushcfunction(state, log); - lua_setfield(state, -2, "log\0".as_ptr() as *const i8); + lua_setfield(state, -2, cstr!("log")); /*lua_createtable( state, 0, 0 ); // local t = {} lua_createtable( state, 0, 0 ); // local t2 = {} - lua_setfield( state, -2, "loaded\0".as_ptr() as *const i8 ); // package.loaded = t2 - lua_setfield( state, -2, "package\0".as_ptr() as *const i8 ); // package = t + lua_setfield( state, -2, cstr!("loaded") ); // package.loaded = t2 + lua_setfield( state, -2, cstr!("package") ); // package = t */ lua_pushcfunction(state, sautorun_require); - lua_setfield(state, -2, "require\0".as_ptr() as *const i8); + lua_setfield(state, -2, cstr!("require")); - lua_setfield(state, -2, "sautorun\0".as_ptr() as *const i8); + lua_setfield(state, -2, cstr!("sautorun")); lua_createtable(state, 0, 0); // Create a metatable to make the env inherit from _G lua_pushvalue(state, GLOBALSINDEX); - lua_setfield(state, -2, "__index\0".as_ptr() as *const i8); + lua_setfield(state, -2, cstr!("__index")); lua_setmetatable(state, -2); lua_setfenv(state, -2); diff --git a/src/sys/util.rs b/src/sys/util.rs index 21ea56d..acd8645 100644 --- a/src/sys/util.rs +++ b/src/sys/util.rs @@ -4,7 +4,7 @@ use std::{ sync::atomic::Ordering, }; -use rglua::{lua_shared::*, rstr, types::LuaState}; +use rglua::{cstr, lua_shared::*, rstr, types::LuaState}; const LUA_OK: i32 = 0; @@ -72,9 +72,7 @@ pub fn initMenuState(state: LuaState) -> Result<(), detour::Error> { error!("MENU_STATE was occupied in gmod13_open. Shouldn't happen."); } - info!("Loaded into menu state."); - - lua_getglobal(state, "JoinServer\0".as_ptr() as *const i8); + lua_getglobal(state, cstr!("JoinServer")); let joinserver_fn = lua_tocfunction(state, -1); lua_pop(state, 1); @@ -135,8 +133,8 @@ pub fn lua_compilestring(state: LuaState, code: &str) -> Result<(), &'static str state, code.as_ptr() as *const i8, code.len(), - "@RunString\0".as_ptr() as *const i8, - "bt\0".as_ptr() as *const i8, + cstr!("@RunString"), + cstr!("bt"), ) != LUA_OK { let err = lua_tolstring(state, -1, 0);