refactor steam_proxy
This commit is contained in:
parent
cdc9c1df1e
commit
caf826b82a
@ -20,6 +20,18 @@ namespace steam_proxy
|
|||||||
{
|
{
|
||||||
utils::binary_resource runner_file(RUNNER, "runner.exe");
|
utils::binary_resource runner_file(RUNNER, "runner.exe");
|
||||||
|
|
||||||
|
utils::nt::library steam_client_module_{};
|
||||||
|
utils::nt::library steam_overlay_module_{};
|
||||||
|
|
||||||
|
steam::interface client_engine_ {};
|
||||||
|
steam::interface client_user_ {};
|
||||||
|
steam::interface client_utils_ {};
|
||||||
|
|
||||||
|
steam::HSteamPipe steam_pipe_ = 0;
|
||||||
|
steam::HSteamUser global_user_ = 0;
|
||||||
|
|
||||||
|
steam::client* steam_client_ {};
|
||||||
|
|
||||||
enum class ownership_state
|
enum class ownership_state
|
||||||
{
|
{
|
||||||
success,
|
success,
|
||||||
@ -27,11 +39,146 @@ namespace steam_proxy
|
|||||||
nosteam,
|
nosteam,
|
||||||
error,
|
error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void* load_client_engine()
|
||||||
|
{
|
||||||
|
if (!steam_client_module_) return nullptr;
|
||||||
|
|
||||||
|
for (auto i = 1; i > 0; ++i)
|
||||||
|
{
|
||||||
|
std::string name = utils::string::va("CLIENTENGINE_INTERFACE_VERSION%03i", i);
|
||||||
|
auto* const temp_client_engine = steam_client_module_
|
||||||
|
.invoke<void*>("CreateInterface", name.data(), nullptr);
|
||||||
|
if (temp_client_engine) return temp_client_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_client()
|
||||||
|
{
|
||||||
|
SetEnvironmentVariableA("SteamAppId", std::to_string(steam::SteamUtils()->GetAppID()).data());
|
||||||
|
|
||||||
|
const std::filesystem::path steam_path = steam::SteamAPI_GetSteamInstallPath();
|
||||||
|
if (steam_path.empty()) return;
|
||||||
|
|
||||||
|
utils::nt::library::load(steam_path / "tier0_s64.dll");
|
||||||
|
utils::nt::library::load(steam_path / "vstdlib_s64.dll");
|
||||||
|
steam_overlay_module_ = utils::nt::library::load(steam_path / "gameoverlayrenderer64.dll");
|
||||||
|
steam_client_module_ = utils::nt::library::load(steam_path / "steamclient64.dll");
|
||||||
|
if (!steam_client_module_) return;
|
||||||
|
|
||||||
|
client_engine_ = load_client_engine();
|
||||||
|
if (!client_engine_) return;
|
||||||
|
|
||||||
|
steam_pipe_ = steam_client_module_.invoke<steam::HSteamPipe>("Steam_CreateSteamPipe");
|
||||||
|
global_user_ = steam_client_module_.invoke<steam::HSteamUser>(
|
||||||
|
"Steam_ConnectToGlobalUser", steam_pipe_);
|
||||||
|
client_user_ = client_engine_.invoke<void*>(8, steam_pipe_, global_user_);
|
||||||
|
// GetIClientUser
|
||||||
|
client_utils_ = client_engine_.invoke<void*>(14, steam_pipe_); // GetIClientUtils
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_cleanup()
|
||||||
|
{
|
||||||
|
client_engine_ = nullptr;
|
||||||
|
client_user_ = nullptr;
|
||||||
|
client_utils_ = nullptr;
|
||||||
|
|
||||||
|
steam_pipe_ = 0;
|
||||||
|
global_user_ = 0;
|
||||||
|
|
||||||
|
steam_client_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool perform_cleanup_if_needed()
|
||||||
|
{
|
||||||
|
if (steam_client_) return true;
|
||||||
|
|
||||||
|
if (steam_client_module_
|
||||||
|
&& steam_pipe_
|
||||||
|
&& global_user_
|
||||||
|
&& steam_client_module_.invoke<bool>("Steam_BConnected", global_user_, steam_pipe_)
|
||||||
|
&& steam_client_module_.invoke<bool>("Steam_BLoggedOn", global_user_, steam_pipe_)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_cleanup();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clean_up_on_error()
|
||||||
|
{
|
||||||
|
scheduler::schedule([]()
|
||||||
|
{
|
||||||
|
if (perform_cleanup_if_needed())
|
||||||
|
{
|
||||||
|
return scheduler::cond_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return scheduler::cond_continue;
|
||||||
|
}, scheduler::main);
|
||||||
|
}
|
||||||
|
|
||||||
|
ownership_state start_mod_unsafe(const std::string& title, size_t app_id)
|
||||||
|
{
|
||||||
|
if (!client_utils_ || !client_user_)
|
||||||
|
{
|
||||||
|
return ownership_state::nosteam;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!client_user_.invoke<bool>("BIsSubscribedApp", app_id))
|
||||||
|
{
|
||||||
|
//app_id = 480; // Spacewar
|
||||||
|
return ownership_state::unowned;
|
||||||
|
}
|
||||||
|
|
||||||
|
client_utils_.invoke<void>("SetAppIDForCurrentPipe", app_id, false);
|
||||||
|
|
||||||
|
char our_directory[MAX_PATH] = { 0 };
|
||||||
|
GetCurrentDirectoryA(sizeof(our_directory), our_directory);
|
||||||
|
|
||||||
|
const auto path = runner_file.get_extracted_file();
|
||||||
|
const std::string cmdline = utils::string::va("\"%s\" -proc %d", path.data(), GetCurrentProcessId());
|
||||||
|
|
||||||
|
steam::game_id game_id;
|
||||||
|
game_id.raw.type = 1; // k_EGameIDTypeGameMod
|
||||||
|
game_id.raw.app_id = app_id & 0xFFFFFF;
|
||||||
|
|
||||||
|
const auto* mod_id = "iw7";
|
||||||
|
game_id.raw.mod_id = *reinterpret_cast<const unsigned int*>(mod_id) | 0x80000000;
|
||||||
|
|
||||||
|
client_user_.invoke<bool>("SpawnProcess", path.data(), cmdline.data(), our_directory,
|
||||||
|
&game_id.bits, title.data(), 0, 0, 0);
|
||||||
|
|
||||||
|
return ownership_state::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
ownership_state start_mod(const std::string& title, const size_t app_id)
|
||||||
|
{
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
return start_mod_unsafe(title, app_id);
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
do_cleanup();
|
||||||
|
return ownership_state::error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
void post_load() override
|
||||||
|
{
|
||||||
|
load_client();
|
||||||
|
perform_cleanup_if_needed();
|
||||||
|
}
|
||||||
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
if (game::environment::is_dedi())
|
if (game::environment::is_dedi())
|
||||||
@ -39,13 +186,10 @@ namespace steam_proxy
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->load_client();
|
|
||||||
this->clean_up_on_error();
|
|
||||||
|
|
||||||
#ifndef DEV_BUILD
|
#ifndef DEV_BUILD
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto res = this->start_mod("\xF0\x9F\x8E\xAE" "IW7-Mod", steam::SteamUtils()->GetAppID());
|
const auto res = start_mod("\xF0\x9F\x8E\xAE" "IW7-Mod", steam::SteamUtils()->GetAppID());
|
||||||
|
|
||||||
switch (res)
|
switch (res)
|
||||||
{
|
{
|
||||||
@ -66,22 +210,29 @@ namespace steam_proxy
|
|||||||
TerminateProcess(GetCurrentProcess(), 1234);
|
TerminateProcess(GetCurrentProcess(), 1234);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
clean_up_on_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pre_destroy() override
|
void pre_destroy() override
|
||||||
{
|
{
|
||||||
if (this->steam_client_module_)
|
if (steam_client_)
|
||||||
{
|
{
|
||||||
if (this->steam_pipe_)
|
if (global_user_)
|
||||||
{
|
{
|
||||||
if (this->global_user_)
|
steam_client_->ReleaseUser(steam_pipe_, global_user_);
|
||||||
{
|
|
||||||
this->steam_client_module_.invoke<void>("Steam_ReleaseUser", this->steam_pipe_,
|
|
||||||
this->global_user_);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->steam_client_module_.invoke<bool>("Steam_BReleaseSteamPipe", this->steam_pipe_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
steam_client_->BReleaseSteamPipe(steam_pipe_);
|
||||||
|
}
|
||||||
|
else if (steam_client_module_ && steam_pipe_)
|
||||||
|
{
|
||||||
|
if (global_user_)
|
||||||
|
{
|
||||||
|
steam_client_module_.invoke<void>("Steam_ReleaseUser", steam_pipe_,
|
||||||
|
global_user_);
|
||||||
|
}
|
||||||
|
|
||||||
|
steam_client_module_.invoke<bool>("Steam_BReleaseSteamPipe", steam_pipe_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,153 +240,23 @@ namespace steam_proxy
|
|||||||
{
|
{
|
||||||
return component_priority::steam_proxy;
|
return component_priority::steam_proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
const utils::nt::library& get_overlay_module() const
|
|
||||||
{
|
|
||||||
return steam_overlay_module_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
utils::nt::library steam_client_module_{};
|
|
||||||
utils::nt::library steam_overlay_module_{};
|
|
||||||
|
|
||||||
steam::interface client_engine_ {};
|
|
||||||
steam::interface client_user_ {};
|
|
||||||
steam::interface client_utils_ {};
|
|
||||||
|
|
||||||
void* steam_pipe_ = nullptr;
|
|
||||||
void* global_user_ = nullptr;
|
|
||||||
|
|
||||||
void* load_client_engine() const
|
|
||||||
{
|
|
||||||
if (!this->steam_client_module_) return nullptr;
|
|
||||||
|
|
||||||
for (auto i = 1; i > 0; ++i)
|
|
||||||
{
|
|
||||||
std::string name = utils::string::va("CLIENTENGINE_INTERFACE_VERSION%03i", i);
|
|
||||||
auto* const client_engine = this->steam_client_module_
|
|
||||||
.invoke<void*>("CreateInterface", name.data(), nullptr);
|
|
||||||
if (client_engine) return client_engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void load_client()
|
|
||||||
{
|
|
||||||
const std::filesystem::path steam_path = steam::SteamAPI_GetSteamInstallPath();
|
|
||||||
if (steam_path.empty()) return;
|
|
||||||
|
|
||||||
utils::nt::library::load(steam_path / "tier0_s64.dll");
|
|
||||||
utils::nt::library::load(steam_path / "vstdlib_s64.dll");
|
|
||||||
this->steam_overlay_module_ = utils::nt::library::load(steam_path / "gameoverlayrenderer64.dll");
|
|
||||||
this->steam_client_module_ = utils::nt::library::load(steam_path / "steamclient64.dll");
|
|
||||||
if (!this->steam_client_module_) return;
|
|
||||||
|
|
||||||
this->client_engine_ = load_client_engine();
|
|
||||||
if (!this->client_engine_) return;
|
|
||||||
|
|
||||||
this->steam_pipe_ = this->steam_client_module_.invoke<void*>("Steam_CreateSteamPipe");
|
|
||||||
this->global_user_ = this->steam_client_module_.invoke<void*>(
|
|
||||||
"Steam_ConnectToGlobalUser", this->steam_pipe_);
|
|
||||||
this->client_user_ = this->client_engine_.invoke<void*>(8, this->steam_pipe_, this->global_user_);
|
|
||||||
// GetIClientUser
|
|
||||||
this->client_utils_ = this->client_engine_.invoke<void*>(14, this->steam_pipe_); // GetIClientUtils
|
|
||||||
}
|
|
||||||
|
|
||||||
ownership_state start_mod(const std::string& title, const size_t app_id)
|
|
||||||
{
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
return this->start_mod_unsafe(title, app_id);
|
|
||||||
}
|
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
{
|
|
||||||
this->do_cleanup();
|
|
||||||
return ownership_state::error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ownership_state start_mod_unsafe(const std::string& title, size_t app_id)
|
|
||||||
{
|
|
||||||
if (!this->client_utils_ || !this->client_user_)
|
|
||||||
{
|
|
||||||
return ownership_state::nosteam;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this->client_user_.invoke<bool>("BIsSubscribedApp", app_id))
|
|
||||||
{
|
|
||||||
//app_id = 480; // Spacewar
|
|
||||||
return ownership_state::unowned;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->client_utils_.invoke<void>("SetAppIDForCurrentPipe", app_id, false);
|
|
||||||
|
|
||||||
char our_directory[MAX_PATH] = { 0 };
|
|
||||||
GetCurrentDirectoryA(sizeof(our_directory), our_directory);
|
|
||||||
|
|
||||||
const auto path = runner_file.get_extracted_file();
|
|
||||||
const std::string cmdline = utils::string::va("\"%s\" -proc %d", path.data(), GetCurrentProcessId());
|
|
||||||
|
|
||||||
steam::game_id game_id;
|
|
||||||
game_id.raw.type = 1; // k_EGameIDTypeGameMod
|
|
||||||
game_id.raw.app_id = app_id & 0xFFFFFF;
|
|
||||||
|
|
||||||
const auto* mod_id = "iw7";
|
|
||||||
game_id.raw.mod_id = *reinterpret_cast<const unsigned int*>(mod_id) | 0x80000000;
|
|
||||||
|
|
||||||
this->client_user_.invoke<bool>("SpawnProcess", path.data(), cmdline.data(), our_directory,
|
|
||||||
&game_id.bits, title.data(), 0, 0, 0);
|
|
||||||
|
|
||||||
return ownership_state::success;
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_cleanup()
|
|
||||||
{
|
|
||||||
this->client_engine_ = nullptr;
|
|
||||||
this->client_user_ = nullptr;
|
|
||||||
this->client_utils_ = nullptr;
|
|
||||||
|
|
||||||
this->steam_pipe_ = nullptr;
|
|
||||||
this->global_user_ = nullptr;
|
|
||||||
|
|
||||||
this->steam_client_module_ = utils::nt::library{ nullptr };
|
|
||||||
}
|
|
||||||
|
|
||||||
void clean_up_on_error()
|
|
||||||
{
|
|
||||||
scheduler::schedule([this]()
|
|
||||||
{
|
|
||||||
if (this->steam_client_module_
|
|
||||||
&& this->steam_pipe_
|
|
||||||
&& this->global_user_
|
|
||||||
&& this->steam_client_module_.invoke<bool>("Steam_BConnected", this->global_user_,
|
|
||||||
this->steam_pipe_)
|
|
||||||
&& this->steam_client_module_.invoke<bool>("Steam_BLoggedOn", this->global_user_, this->steam_pipe_)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return scheduler::cond_continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->client_engine_ = nullptr;
|
|
||||||
this->client_user_ = nullptr;
|
|
||||||
this->client_utils_ = nullptr;
|
|
||||||
|
|
||||||
this->steam_pipe_ = nullptr;
|
|
||||||
this->global_user_ = nullptr;
|
|
||||||
|
|
||||||
this->steam_client_module_ = utils::nt::library{ nullptr };
|
|
||||||
|
|
||||||
return scheduler::cond_end;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const utils::nt::library& get_overlay_module()
|
const utils::nt::library& get_overlay_module()
|
||||||
{
|
{
|
||||||
// TODO: Find a better way to do this
|
return steam_overlay_module_;
|
||||||
return component_loader::get<component>()->get_overlay_module();
|
}
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
if (client_engine_ || !steam_client_module_) return;
|
||||||
|
|
||||||
|
steam_client_ = steam_client_module_.invoke<steam::client*>("CreateInterface", "SteamClient017", nullptr);
|
||||||
|
if (!steam_client_) return;
|
||||||
|
|
||||||
|
steam_pipe_ = steam_client_->CreateSteamPipe();
|
||||||
|
global_user_ = steam_client_->ConnectToGlobalUser(steam_pipe_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_COMPONENT(steam_proxy::component)
|
REGISTER_COMPONENT(steam_proxy::component)
|
@ -4,4 +4,5 @@
|
|||||||
namespace steam_proxy
|
namespace steam_proxy
|
||||||
{
|
{
|
||||||
const utils::nt::library& get_overlay_module();
|
const utils::nt::library& get_overlay_module();
|
||||||
|
void initialize();
|
||||||
}
|
}
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "../component/steam_proxy.hpp"
|
||||||
|
|
||||||
namespace steam
|
namespace steam
|
||||||
{
|
{
|
||||||
uint64_t callbacks::call_id_ = 0;
|
uint64_t callbacks::call_id_ = 0;
|
||||||
@ -120,6 +122,9 @@ namespace steam
|
|||||||
::utils::nt::library::load(steam_path / "vstdlib_s64.dll");
|
::utils::nt::library::load(steam_path / "vstdlib_s64.dll");
|
||||||
::utils::nt::library::load(steam_path / "gameoverlayrenderer64.dll");
|
::utils::nt::library::load(steam_path / "gameoverlayrenderer64.dll");
|
||||||
::utils::nt::library::load(steam_path / "steamclient64.dll");
|
::utils::nt::library::load(steam_path / "steamclient64.dll");
|
||||||
|
|
||||||
|
steam_proxy::initialize();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user