Fix stuff
This commit is contained in:
parent
0fb12bdc32
commit
fbfdc30e25
@ -1,3 +1,3 @@
|
||||
@echo off
|
||||
git submodule update --init --recursive
|
||||
tools\premake5 %* vs2017
|
||||
@echo off
|
||||
git submodule update --init --recursive
|
||||
tools\premake5 %* vs2019
|
262
premake5.lua
262
premake5.lua
@ -1,131 +1,131 @@
|
||||
dependencies = {
|
||||
basePath = "./deps"
|
||||
}
|
||||
|
||||
function dependencies.load()
|
||||
dir = path.join(dependencies.basePath, "premake/*.lua")
|
||||
deps = os.matchfiles(dir)
|
||||
|
||||
for i, dep in pairs(deps) do
|
||||
dep = dep:gsub(".lua", "")
|
||||
require(dep)
|
||||
end
|
||||
end
|
||||
|
||||
function dependencies.imports()
|
||||
for i, proj in pairs(dependencies) do
|
||||
if type(i) == 'number' then
|
||||
proj.import()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function dependencies.projects()
|
||||
for i, proj in pairs(dependencies) do
|
||||
if type(i) == 'number' then
|
||||
proj.project()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newoption {
|
||||
trigger = "copy-to",
|
||||
description = "Optional, copy the EXE to a custom folder after build, define the path here if wanted.",
|
||||
value = "PATH"
|
||||
}
|
||||
|
||||
dependencies.load()
|
||||
|
||||
workspace "open-iw5"
|
||||
startproject "open-iw5"
|
||||
location "./build"
|
||||
objdir "%{wks.location}/obj"
|
||||
targetdir "%{wks.location}/bin/%{cfg.platform}/%{cfg.buildcfg}"
|
||||
|
||||
configurations {
|
||||
"Debug",
|
||||
"Release",
|
||||
}
|
||||
|
||||
architecture "x32"
|
||||
platforms "x32"
|
||||
|
||||
buildoptions "/std:c++latest"
|
||||
systemversion "latest"
|
||||
symbols "On"
|
||||
staticruntime "On"
|
||||
editandcontinue "Off"
|
||||
warnings "Extra"
|
||||
characterset "ASCII"
|
||||
toolset "v142"
|
||||
|
||||
flags {
|
||||
"NoIncrementalLink",
|
||||
"NoMinimalRebuild",
|
||||
"MultiProcessorCompile",
|
||||
"No64BitChecks"
|
||||
}
|
||||
|
||||
configuration "windows"
|
||||
defines {
|
||||
"_WINDOWS",
|
||||
"WIN32",
|
||||
}
|
||||
|
||||
configuration "Release"
|
||||
optimize "Full"
|
||||
|
||||
defines {
|
||||
"NDEBUG",
|
||||
}
|
||||
|
||||
flags {
|
||||
"FatalCompileWarnings",
|
||||
}
|
||||
|
||||
configuration "Debug"
|
||||
optimize "Debug"
|
||||
|
||||
defines {
|
||||
"DEBUG",
|
||||
"_DEBUG",
|
||||
}
|
||||
|
||||
configuration {}
|
||||
|
||||
project "open-iw5"
|
||||
kind "ConsoleApp"
|
||||
language "C++"
|
||||
|
||||
pchheader "std_include.hpp"
|
||||
pchsource "src/std_include.cpp"
|
||||
|
||||
linkoptions "/IGNORE:4254 /DYNAMICBASE:NO /SAFESEH:NO /LARGEADDRESSAWARE"
|
||||
linkoptions "/LAST:.main"
|
||||
|
||||
|
||||
files {
|
||||
"./src/**.rc",
|
||||
"./src/**.hpp",
|
||||
"./src/**.cpp",
|
||||
"./src/resources/**.*"
|
||||
}
|
||||
|
||||
includedirs {
|
||||
"./src"
|
||||
}
|
||||
|
||||
resincludedirs {
|
||||
"$(ProjectDir)src"
|
||||
}
|
||||
|
||||
if _OPTIONS["copy-to"] then
|
||||
postbuildcommands {
|
||||
"copy /y \"$(TargetDir)*.exe\" \"" .. _OPTIONS["copy-to"] .. "\""
|
||||
}
|
||||
end
|
||||
|
||||
dependencies.imports()
|
||||
|
||||
group "Dependencies"
|
||||
dependencies.projects()
|
||||
dependencies = {
|
||||
basePath = "./deps"
|
||||
}
|
||||
|
||||
function dependencies.load()
|
||||
dir = path.join(dependencies.basePath, "premake/*.lua")
|
||||
deps = os.matchfiles(dir)
|
||||
|
||||
for i, dep in pairs(deps) do
|
||||
dep = dep:gsub(".lua", "")
|
||||
require(dep)
|
||||
end
|
||||
end
|
||||
|
||||
function dependencies.imports()
|
||||
for i, proj in pairs(dependencies) do
|
||||
if type(i) == 'number' then
|
||||
proj.import()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function dependencies.projects()
|
||||
for i, proj in pairs(dependencies) do
|
||||
if type(i) == 'number' then
|
||||
proj.project()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newoption {
|
||||
trigger = "copy-to",
|
||||
description = "Optional, copy the EXE to a custom folder after build, define the path here if wanted.",
|
||||
value = "PATH"
|
||||
}
|
||||
|
||||
dependencies.load()
|
||||
|
||||
workspace "open-iw5"
|
||||
startproject "open-iw5"
|
||||
location "./build"
|
||||
objdir "%{wks.location}/obj"
|
||||
targetdir "%{wks.location}/bin/%{cfg.platform}/%{cfg.buildcfg}"
|
||||
|
||||
configurations {
|
||||
"Debug",
|
||||
"Release",
|
||||
}
|
||||
|
||||
architecture "x32"
|
||||
platforms "x32"
|
||||
|
||||
buildoptions "/std:c++latest"
|
||||
systemversion "latest"
|
||||
symbols "On"
|
||||
staticruntime "On"
|
||||
editandcontinue "Off"
|
||||
warnings "Extra"
|
||||
characterset "ASCII"
|
||||
toolset "v142"
|
||||
|
||||
flags {
|
||||
"NoIncrementalLink",
|
||||
"NoMinimalRebuild",
|
||||
"MultiProcessorCompile",
|
||||
"No64BitChecks"
|
||||
}
|
||||
|
||||
configuration "windows"
|
||||
defines {
|
||||
"_WINDOWS",
|
||||
"WIN32",
|
||||
}
|
||||
|
||||
configuration "Release"
|
||||
optimize "Full"
|
||||
|
||||
defines {
|
||||
"NDEBUG",
|
||||
}
|
||||
|
||||
flags {
|
||||
"FatalCompileWarnings",
|
||||
}
|
||||
|
||||
configuration "Debug"
|
||||
optimize "Debug"
|
||||
|
||||
defines {
|
||||
"DEBUG",
|
||||
"_DEBUG",
|
||||
}
|
||||
|
||||
configuration {}
|
||||
|
||||
project "open-iw5"
|
||||
kind "ConsoleApp"
|
||||
language "C++"
|
||||
|
||||
pchheader "std_include.hpp"
|
||||
pchsource "src/std_include.cpp"
|
||||
|
||||
linkoptions "/IGNORE:4254 /DYNAMICBASE:NO /SAFESEH:NO /LARGEADDRESSAWARE"
|
||||
linkoptions "/LAST:.main"
|
||||
|
||||
|
||||
files {
|
||||
"./src/**.rc",
|
||||
"./src/**.hpp",
|
||||
"./src/**.cpp",
|
||||
"./src/resources/**.*"
|
||||
}
|
||||
|
||||
includedirs {
|
||||
"./src"
|
||||
}
|
||||
|
||||
resincludedirs {
|
||||
"$(ProjectDir)src"
|
||||
}
|
||||
|
||||
if _OPTIONS["copy-to"] then
|
||||
postbuildcommands {
|
||||
"copy /y \"$(TargetDir)*.exe\" \"" .. _OPTIONS["copy-to"] .. "\""
|
||||
}
|
||||
end
|
||||
|
||||
dependencies.imports()
|
||||
|
||||
group "Dependencies"
|
||||
dependencies.projects()
|
||||
|
@ -1,61 +1,61 @@
|
||||
#include <std_include.hpp>
|
||||
#include "bdDediAuth.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void bdDediAuth::call_service(i_server* server, const std::string& data)
|
||||
{
|
||||
bit_buffer buffer(data);
|
||||
|
||||
bool more_data;
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.read_bool(&more_data);
|
||||
buffer.set_use_data_types(true);
|
||||
|
||||
uint32_t seed, title_id, ticket_size;
|
||||
buffer.read_uint32(&seed);
|
||||
buffer.read_uint32(&title_id);
|
||||
|
||||
uint8_t ticket[1024];
|
||||
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
|
||||
|
||||
game::native::bdAuthTicket auth_ticket{};
|
||||
std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
|
||||
|
||||
auth_ticket.m_magicNumber = 0x0EFBDADDE;
|
||||
auth_ticket.m_type = 0;
|
||||
auth_ticket.m_titleID = title_id;
|
||||
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
|
||||
auth_ticket.m_licenseID = 4;
|
||||
|
||||
auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY);
|
||||
|
||||
strcpy_s(auth_ticket.m_username, "Open-IW5 Server");
|
||||
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
|
||||
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
|
||||
|
||||
uint8_t lsg_ticket[128];
|
||||
ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
|
||||
std::memcpy(lsg_ticket, key.data(), 24);
|
||||
|
||||
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
|
||||
|
||||
const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
|
||||
auto enc_ticket = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
|
||||
|
||||
bit_buffer response;
|
||||
response.set_use_data_types(false);
|
||||
response.write_bool(false);
|
||||
response.write_uint32(700);
|
||||
response.write_uint32(seed);
|
||||
response.write_bytes(enc_ticket.size(), enc_ticket.data());
|
||||
response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
|
||||
|
||||
auto reply = server->create_message(29);
|
||||
reply->send(&response, false);
|
||||
}
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "bdDediAuth.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void bdDediAuth::call_service(i_server* server, const std::string& data)
|
||||
{
|
||||
bit_buffer buffer(data);
|
||||
|
||||
bool more_data;
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.read_bool(&more_data);
|
||||
buffer.set_use_data_types(true);
|
||||
|
||||
uint32_t seed, title_id, ticket_size;
|
||||
buffer.read_uint32(&seed);
|
||||
buffer.read_uint32(&title_id);
|
||||
|
||||
uint8_t ticket[1024];
|
||||
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
|
||||
|
||||
game::native::bdAuthTicket auth_ticket{};
|
||||
std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
|
||||
|
||||
auth_ticket.m_magicNumber = 0x0EFBDADDE;
|
||||
auth_ticket.m_type = 0;
|
||||
auth_ticket.m_titleID = title_id;
|
||||
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
|
||||
auth_ticket.m_licenseID = 4;
|
||||
|
||||
auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY);
|
||||
|
||||
strcpy_s(auth_ticket.m_username, "Open-IW5 Server");
|
||||
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
|
||||
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
|
||||
|
||||
uint8_t lsg_ticket[128];
|
||||
ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
|
||||
std::memcpy(lsg_ticket, key.data(), 24);
|
||||
|
||||
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
|
||||
|
||||
const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
|
||||
auto enc_ticket = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
|
||||
|
||||
bit_buffer response;
|
||||
response.set_use_data_types(false);
|
||||
response.write_bool(false);
|
||||
response.write_uint32(700);
|
||||
response.write_uint32(seed);
|
||||
response.write_bytes(enc_ticket.size(), enc_ticket.data());
|
||||
response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
|
||||
|
||||
auto reply = server->create_message(29);
|
||||
reply->send(&response, false);
|
||||
}
|
||||
}
|
||||
|
@ -1,71 +1,71 @@
|
||||
#include <std_include.hpp>
|
||||
#include "bdDediRSAAuth.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void bdDediRSAAuth::call_service(i_server* server, const std::string& data)
|
||||
{
|
||||
bit_buffer buffer(data);
|
||||
|
||||
bool more_data;
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.read_bool(&more_data);
|
||||
buffer.set_use_data_types(true);
|
||||
|
||||
uint32_t seed, title_id, ticket_size;
|
||||
buffer.read_uint32(&seed);
|
||||
buffer.read_uint32(&title_id);
|
||||
|
||||
unsigned char rsakey[140];
|
||||
buffer.read_bytes(sizeof(rsakey), rsakey);
|
||||
|
||||
uint8_t ticket[1024];
|
||||
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
|
||||
|
||||
game::native::bdAuthTicket auth_ticket{};
|
||||
std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
|
||||
|
||||
auth_ticket.m_magicNumber = 0x0EFBDADDE;
|
||||
auth_ticket.m_type = 0;
|
||||
auth_ticket.m_titleID = title_id;
|
||||
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
|
||||
|
||||
auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY);
|
||||
|
||||
strcpy_s(auth_ticket.m_username, "Open-IW5 Server");
|
||||
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
|
||||
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
|
||||
|
||||
uint8_t lsg_ticket[128];
|
||||
ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
|
||||
std::memcpy(lsg_ticket, key.data(), 24);
|
||||
|
||||
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
|
||||
|
||||
const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
|
||||
auto enc_ticket = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
|
||||
|
||||
register_hash(&sha1_desc);
|
||||
register_prng(&yarrow_desc);
|
||||
|
||||
std::string encrypted_key = utils::cryptography::rsa::encrypt(std::string(SERVER_CD_KEY, 24),
|
||||
std::string("DW-RSAENC", 10),
|
||||
std::string(PCHAR(rsakey), sizeof(rsakey)));
|
||||
|
||||
bit_buffer response;
|
||||
response.set_use_data_types(false);
|
||||
response.write_bool(false);
|
||||
response.write_uint32(700);
|
||||
response.write_uint32(seed);
|
||||
response.write_bytes(enc_ticket.size(), enc_ticket.data());
|
||||
response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
|
||||
response.write_bytes(encrypted_key.size(), encrypted_key.data());
|
||||
|
||||
auto reply = server->create_message(29);
|
||||
reply->send(&response, false);
|
||||
}
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "bdDediRSAAuth.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void bdDediRSAAuth::call_service(i_server* server, const std::string& data)
|
||||
{
|
||||
bit_buffer buffer(data);
|
||||
|
||||
bool more_data;
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.read_bool(&more_data);
|
||||
buffer.set_use_data_types(true);
|
||||
|
||||
uint32_t seed, title_id, ticket_size;
|
||||
buffer.read_uint32(&seed);
|
||||
buffer.read_uint32(&title_id);
|
||||
|
||||
unsigned char rsakey[140];
|
||||
buffer.read_bytes(sizeof(rsakey), rsakey);
|
||||
|
||||
uint8_t ticket[1024];
|
||||
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
|
||||
|
||||
game::native::bdAuthTicket auth_ticket{};
|
||||
std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
|
||||
|
||||
auth_ticket.m_magicNumber = 0x0EFBDADDE;
|
||||
auth_ticket.m_type = 0;
|
||||
auth_ticket.m_titleID = title_id;
|
||||
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
|
||||
|
||||
auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY);
|
||||
|
||||
strcpy_s(auth_ticket.m_username, "Open-IW5 Server");
|
||||
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
|
||||
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
|
||||
|
||||
uint8_t lsg_ticket[128];
|
||||
ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
|
||||
std::memcpy(lsg_ticket, key.data(), 24);
|
||||
|
||||
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
|
||||
|
||||
const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
|
||||
auto enc_ticket = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
|
||||
|
||||
register_hash(&sha1_desc);
|
||||
register_prng(&yarrow_desc);
|
||||
|
||||
std::string encrypted_key = utils::cryptography::rsa::encrypt(std::string(SERVER_CD_KEY, 24),
|
||||
std::string("DW-RSAENC", 10),
|
||||
std::string(PCHAR(rsakey), sizeof(rsakey)));
|
||||
|
||||
bit_buffer response;
|
||||
response.set_use_data_types(false);
|
||||
response.write_bool(false);
|
||||
response.write_uint32(700);
|
||||
response.write_uint32(seed);
|
||||
response.write_bytes(enc_ticket.size(), enc_ticket.data());
|
||||
response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
|
||||
response.write_bytes(encrypted_key.size(), encrypted_key.data());
|
||||
|
||||
auto reply = server->create_message(29);
|
||||
reply->send(&response, false);
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +1,61 @@
|
||||
#include <std_include.hpp>
|
||||
#include "bdSteamAuth.hpp"
|
||||
#include "game/structs.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void bdSteamAuth::call_service(i_server* server, const std::string& data)
|
||||
{
|
||||
bit_buffer buffer(data);
|
||||
|
||||
bool more_data;
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.read_bool(&more_data);
|
||||
buffer.set_use_data_types(true);
|
||||
|
||||
uint32_t seed, title_id, ticket_size;
|
||||
buffer.read_uint32(&seed);
|
||||
buffer.read_uint32(&title_id);
|
||||
buffer.read_uint32(&ticket_size);
|
||||
|
||||
uint8_t ticket[1024];
|
||||
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
|
||||
|
||||
game::native::bdAuthTicket auth_ticket{};
|
||||
std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
|
||||
|
||||
auth_ticket.m_magicNumber = 0x0EFBDADDE;
|
||||
auth_ticket.m_type = 0;
|
||||
auth_ticket.m_titleID = title_id;
|
||||
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
|
||||
|
||||
auto key = utils::cryptography::tiger::compute("Open-IW5");
|
||||
|
||||
strcpy_s(auth_ticket.m_username, "Open-IW5 User");
|
||||
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
|
||||
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
|
||||
|
||||
uint8_t lsg_ticket[128];
|
||||
ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
|
||||
std::memcpy(lsg_ticket, key.data(), 24);
|
||||
|
||||
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
|
||||
|
||||
const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
|
||||
auto enc_ticket = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
|
||||
|
||||
bit_buffer response;
|
||||
response.set_use_data_types(false);
|
||||
response.write_bool(false);
|
||||
response.write_uint32(700);
|
||||
response.write_uint32(seed);
|
||||
response.write_bytes(enc_ticket.size(), enc_ticket.data());
|
||||
response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
|
||||
|
||||
auto reply = server->create_message(29);
|
||||
reply->send(&response, false);
|
||||
}
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "bdSteamAuth.hpp"
|
||||
#include "game/structs.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void bdSteamAuth::call_service(i_server* server, const std::string& data)
|
||||
{
|
||||
bit_buffer buffer(data);
|
||||
|
||||
bool more_data;
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.read_bool(&more_data);
|
||||
buffer.set_use_data_types(true);
|
||||
|
||||
uint32_t seed, title_id, ticket_size;
|
||||
buffer.read_uint32(&seed);
|
||||
buffer.read_uint32(&title_id);
|
||||
buffer.read_uint32(&ticket_size);
|
||||
|
||||
uint8_t ticket[1024];
|
||||
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
|
||||
|
||||
game::native::bdAuthTicket auth_ticket{};
|
||||
std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
|
||||
|
||||
auth_ticket.m_magicNumber = 0x0EFBDADDE;
|
||||
auth_ticket.m_type = 0;
|
||||
auth_ticket.m_titleID = title_id;
|
||||
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
|
||||
|
||||
auto key = utils::cryptography::tiger::compute("Open-IW5");
|
||||
|
||||
strcpy_s(auth_ticket.m_username, "Open-IW5 User");
|
||||
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
|
||||
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
|
||||
|
||||
uint8_t lsg_ticket[128];
|
||||
ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
|
||||
std::memcpy(lsg_ticket, key.data(), 24);
|
||||
|
||||
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
|
||||
|
||||
const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
|
||||
auto enc_ticket = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
|
||||
|
||||
bit_buffer response;
|
||||
response.set_use_data_types(false);
|
||||
response.write_bool(false);
|
||||
response.write_uint32(700);
|
||||
response.write_uint32(seed);
|
||||
response.write_bytes(enc_ticket.size(), enc_ticket.data());
|
||||
response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
|
||||
|
||||
auto reply = server->create_message(29);
|
||||
reply->send(&response, false);
|
||||
}
|
||||
}
|
||||
|
@ -1,374 +1,374 @@
|
||||
#include <std_include.hpp>
|
||||
#include "game.hpp"
|
||||
|
||||
namespace game
|
||||
{
|
||||
namespace native
|
||||
{
|
||||
Cmd_AddCommand_t Cmd_AddCommand;
|
||||
|
||||
Com_Error_t Com_Error;
|
||||
|
||||
DB_LoadXAssets_t DB_LoadXAssets;
|
||||
|
||||
Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
||||
|
||||
G_RunFrame_t G_RunFrame;
|
||||
|
||||
MSG_ReadData_t MSG_ReadData;
|
||||
|
||||
MT_AllocIndex_t MT_AllocIndex;
|
||||
|
||||
RemoveRefToValue_t RemoveRefToValue;
|
||||
|
||||
SL_GetStringOfSize_t SL_GetStringOfSize;
|
||||
|
||||
Sys_ShowConsole_t Sys_ShowConsole;
|
||||
|
||||
VM_Notify_t VM_Notify;
|
||||
|
||||
decltype(longjmp)* _longjmp;
|
||||
|
||||
int* cmd_args;
|
||||
int* cmd_argc;
|
||||
const char*** cmd_argv;
|
||||
|
||||
short* scrVarGlob;
|
||||
char** scrMemTreePub;
|
||||
char* scrMemTreeGlob;
|
||||
|
||||
scrVmPub_t* scr_VmPub;
|
||||
|
||||
scr_call_t* scr_instanceFunctions;
|
||||
scr_call_t* scr_globalFunctions;
|
||||
|
||||
unsigned int* levelEntityId;
|
||||
|
||||
int* g_script_error_level;
|
||||
jmp_buf* g_script_error;
|
||||
|
||||
scr_classStruct_t* g_classMap;
|
||||
|
||||
void AddRefToValue(VariableValue* value)
|
||||
{
|
||||
if (value->type == SCRIPT_OBJECT)
|
||||
{
|
||||
++scrVarGlob[4 * value->u.entityId];
|
||||
}
|
||||
else if ((value->type & ~1) == SCRIPT_STRING)
|
||||
{
|
||||
static const auto size = is_sp() ? 16 : 12;
|
||||
const auto ref_count = reinterpret_cast<unsigned volatile *>(*scrMemTreePub + size * value
|
||||
->u.stringValue);
|
||||
InterlockedIncrement(ref_count);
|
||||
}
|
||||
else if (value->type == SCRIPT_VECTOR)
|
||||
{
|
||||
if (!*PBYTE(value->u.vectorValue - 1))
|
||||
{
|
||||
++*PWORD(value->u.vectorValue - 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) unsigned int conbuf_append_text_dedicated(const char* message)
|
||||
{
|
||||
static DWORD func = 0x53C790;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov ecx, message
|
||||
call func
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
void Conbuf_AppendText(const char* message)
|
||||
{
|
||||
if(is_dedi())
|
||||
{
|
||||
conbuf_append_text_dedicated(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
reinterpret_cast<void(*)(const char*)>(SELECT_VALUE(0x4C84E0, 0x5CF610, 0))(message);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) unsigned int find_variable_dedicated(unsigned int parentId, unsigned int name)
|
||||
{
|
||||
static DWORD func = 0x4E7ED0;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, name
|
||||
mov ecx, parentId
|
||||
call func
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int FindVariable(const unsigned int parentId, const unsigned int name)
|
||||
{
|
||||
if (is_dedi())
|
||||
{
|
||||
return find_variable_dedicated(parentId, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<unsigned int(*)(unsigned int, unsigned int)> //
|
||||
(SELECT_VALUE(0x4C4E70, 0x5651F0, 0x0))(parentId, name);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) VariableValue get_entity_field_value_dedicated(unsigned int classnum, int entnum, int _offset)
|
||||
{
|
||||
static DWORD func = 0x4F1400;
|
||||
|
||||
__asm
|
||||
{
|
||||
push _offset
|
||||
push entnum
|
||||
mov ecx, classnum
|
||||
call func
|
||||
add esp, 8h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
VariableValue GetEntityFieldValue(const unsigned int classnum, const int entnum, const int offset)
|
||||
{
|
||||
if (is_dedi())
|
||||
{
|
||||
return get_entity_field_value_dedicated(classnum, entnum, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<VariableValue(*)(unsigned int, int, int)> //
|
||||
(SELECT_VALUE(0x530E30, 0x56AF20, 0x0))(classnum, entnum, offset);
|
||||
}
|
||||
}
|
||||
|
||||
void* MT_Alloc(const int numBytes, const int type)
|
||||
{
|
||||
return scrMemTreeGlob + 12 * size_t(MT_AllocIndex(numBytes, type));
|
||||
}
|
||||
|
||||
const float* Scr_AllocVector(const float* v)
|
||||
{
|
||||
const auto mem = static_cast<DWORD*>(MT_Alloc(16, 2));
|
||||
*mem = 0;
|
||||
|
||||
const auto array = reinterpret_cast<float*>(mem + 1);
|
||||
array[0] = v[0];
|
||||
array[1] = v[1];
|
||||
array[2] = v[2];
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
void Scr_ClearOutParams()
|
||||
{
|
||||
const auto num_params = scr_VmPub->outparamcount;
|
||||
for (unsigned int i = num_params; i > 0; --i)
|
||||
{
|
||||
const auto value = scr_VmPub->top[i - 1];
|
||||
RemoveRefToValue(value.type, value.u);
|
||||
}
|
||||
|
||||
scr_VmPub->top -= num_params;
|
||||
}
|
||||
|
||||
scr_entref_t Scr_GetEntityIdRef(const unsigned int id)
|
||||
{
|
||||
static auto class_array = reinterpret_cast<DWORD*>(SELECT_VALUE(0x19AFC84, 0x1E72184, 0x1D3C804));
|
||||
static auto ent_array = reinterpret_cast<WORD*>(SELECT_VALUE(0x19AFC82, 0x1E72182, 0x1D3C802));
|
||||
|
||||
scr_entref_t result{};
|
||||
result.raw.classnum = static_cast<unsigned short>(class_array[2 * id]) >> 8;
|
||||
result.raw.entnum = ent_array[4 * id];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
scr_call_t Scr_GetFunc(const unsigned int index)
|
||||
{
|
||||
if (index > 0x1C7)
|
||||
{
|
||||
return scr_instanceFunctions[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return scr_globalFunctions[index];
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void scr_notify_id_multiplayer(unsigned int id, unsigned int stringValue,
|
||||
unsigned int paramcount)
|
||||
{
|
||||
static DWORD func = 0x56B5E0;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, paramcount
|
||||
push stringValue
|
||||
push id
|
||||
call func
|
||||
add esp, 8h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void scr_notify_id_singleplayer(unsigned int id, unsigned int stringValue,
|
||||
unsigned int paramcount)
|
||||
{
|
||||
static DWORD func = 0x610980;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, paramcount
|
||||
push stringValue
|
||||
push id
|
||||
call func
|
||||
add esp, 8h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
void Scr_NotifyId(unsigned int id, unsigned int stringValue, unsigned int paramcount)
|
||||
{
|
||||
if (is_mp())
|
||||
{
|
||||
return scr_notify_id_multiplayer(id, stringValue, paramcount);
|
||||
}
|
||||
else if (is_sp())
|
||||
{
|
||||
return scr_notify_id_singleplayer(id, stringValue, paramcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<void(*)(unsigned int, unsigned int, unsigned int)>(0x4EFAA0)(id, stringValue, paramcount);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) int scr_set_object_field_dedicated(unsigned int classnum, int entnum, int _offset)
|
||||
{
|
||||
static DWORD func = 0x4B15C0;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov ecx, _offset
|
||||
mov eax, entnum
|
||||
push classnum
|
||||
call func
|
||||
add esp, 4h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
int Scr_SetObjectField(const unsigned int classnum, const int entnum, const int offset)
|
||||
{
|
||||
if (is_dedi())
|
||||
{
|
||||
return scr_set_object_field_dedicated(classnum, entnum, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<int(*)(unsigned int, int, int)> //
|
||||
(SELECT_VALUE(0x42CAD0, 0x52BCC0, 0x0))(classnum, entnum, offset);
|
||||
}
|
||||
}
|
||||
|
||||
const char* SL_ConvertToString(const unsigned int stringValue)
|
||||
{
|
||||
if (!stringValue) return nullptr;
|
||||
|
||||
static const auto size = is_sp() ? 16 : 12;
|
||||
return *scrMemTreePub + size * stringValue + 4;
|
||||
}
|
||||
|
||||
unsigned int SL_GetString(const char* str, const unsigned int user)
|
||||
{
|
||||
return SL_GetStringOfSize(str, user, strlen(str) + 1, 7);
|
||||
}
|
||||
}
|
||||
|
||||
launcher::mode mode = launcher::mode::none;
|
||||
|
||||
launcher::mode get_mode()
|
||||
{
|
||||
if(mode == launcher::mode::none)
|
||||
{
|
||||
throw std::runtime_error("Launcher mode not valid. Something must be wrong.");
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
bool is_mp()
|
||||
{
|
||||
return get_mode() == launcher::mode::multiplayer;
|
||||
}
|
||||
|
||||
bool is_sp()
|
||||
{
|
||||
return get_mode() == launcher::mode::singleplayer;
|
||||
}
|
||||
|
||||
bool is_dedi()
|
||||
{
|
||||
return get_mode() == launcher::mode::server;
|
||||
}
|
||||
|
||||
void initialize(const launcher::mode _mode)
|
||||
{
|
||||
mode = _mode;
|
||||
|
||||
native::Cmd_AddCommand = native::Cmd_AddCommand_t(SELECT_VALUE(0x558820, 0x545DF0, 0));
|
||||
|
||||
native::Com_Error = native::Com_Error_t(SELECT_VALUE(0x425540, 0x555450, 0x4D93F0));
|
||||
|
||||
native::DB_LoadXAssets = native::DB_LoadXAssets_t(SELECT_VALUE(0x48A8E0, 0x4CD020, 0x44F770));
|
||||
|
||||
native::Dvar_SetFromStringByName = native::Dvar_SetFromStringByName_t(SELECT_VALUE(0x4DD090, 0x5BF740, 0x518DF0));
|
||||
|
||||
native::G_RunFrame = native::G_RunFrame_t(SELECT_VALUE(0x52EAA0, 0x50CB70, 0x48AD60));
|
||||
|
||||
native::MSG_ReadData = native::MSG_ReadData_t(SELECT_VALUE(0, 0x5592A0, 0));
|
||||
|
||||
native::MT_AllocIndex = native::MT_AllocIndex_t(SELECT_VALUE(0x4B9610, 0x562080, 0x4E6C30));
|
||||
|
||||
native::RemoveRefToValue = native::RemoveRefToValue_t(SELECT_VALUE(0x477EA0, 0x565730, 0x4E8A40));
|
||||
|
||||
native::SL_GetStringOfSize = native::SL_GetStringOfSize_t(SELECT_VALUE(0x4E13F0, 0x564650, 0x4E7490));
|
||||
|
||||
native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0));
|
||||
|
||||
native::VM_Notify = native::VM_Notify_t(SELECT_VALUE(0x610200, 0x569720, 0x4EF450));
|
||||
|
||||
native::_longjmp = reinterpret_cast<decltype(longjmp)*>(SELECT_VALUE(0x73AC20, 0x7363BC, 0x655558));
|
||||
|
||||
native::cmd_args = reinterpret_cast<int*>(SELECT_VALUE(0x1750750, 0x1C978D0, 0x1B455F8));
|
||||
native::cmd_argc = reinterpret_cast<int*>(SELECT_VALUE(0x1750794, 0x1C97914, 0x1B4563C));
|
||||
native::cmd_argv = reinterpret_cast<const char***>(SELECT_VALUE(0x17507B4, 0x1C97934, 0x1B4565C));
|
||||
|
||||
native::scrVarGlob = reinterpret_cast<short*>(SELECT_VALUE(0x19AFC80, 0x1E72180, 0x1D3C800));
|
||||
native::scrMemTreePub = reinterpret_cast<char**>(SELECT_VALUE(0x196FB00, 0x1E32000, 0x1C152A4));
|
||||
native::scrMemTreeGlob = reinterpret_cast<char*>(SELECT_VALUE(0x186DA00, 0x1D6FF00, 0x1C16600));
|
||||
|
||||
native::scr_VmPub = reinterpret_cast<native::scrVmPub_t*>(SELECT_VALUE(0x1BF2580, 0x20B4A80, 0x1F5B080));
|
||||
|
||||
native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x184CDB0, 0x1D4F258,
|
||||
0x1BF59C8));
|
||||
native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x186C68C, 0x1D6EB34,
|
||||
0x1C152A4
|
||||
));
|
||||
|
||||
native::g_script_error_level = reinterpret_cast<int*>(SELECT_VALUE(0x1BEFCFC, 0x20B21FC, 0x1F5B058));
|
||||
native::g_script_error = reinterpret_cast<jmp_buf*>(SELECT_VALUE(0x1BF1D18, 0x20B4218, 0x1F5A818));
|
||||
|
||||
native::g_classMap = reinterpret_cast<native::scr_classStruct_t*>(SELECT_VALUE(0x92D140, 0x8B4300, 0x7C0408));
|
||||
|
||||
native::levelEntityId = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BCBCA4, 0x208E1A4, 0x1CD873C));
|
||||
}
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "game.hpp"
|
||||
|
||||
namespace game
|
||||
{
|
||||
namespace native
|
||||
{
|
||||
Cmd_AddCommand_t Cmd_AddCommand;
|
||||
|
||||
Com_Error_t Com_Error;
|
||||
|
||||
DB_LoadXAssets_t DB_LoadXAssets;
|
||||
|
||||
Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
||||
|
||||
G_RunFrame_t G_RunFrame;
|
||||
|
||||
MSG_ReadData_t MSG_ReadData;
|
||||
|
||||
MT_AllocIndex_t MT_AllocIndex;
|
||||
|
||||
RemoveRefToValue_t RemoveRefToValue;
|
||||
|
||||
SL_GetStringOfSize_t SL_GetStringOfSize;
|
||||
|
||||
Sys_ShowConsole_t Sys_ShowConsole;
|
||||
|
||||
VM_Notify_t VM_Notify;
|
||||
|
||||
decltype(longjmp)* _longjmp;
|
||||
|
||||
int* cmd_args;
|
||||
int* cmd_argc;
|
||||
const char*** cmd_argv;
|
||||
|
||||
short* scrVarGlob;
|
||||
char** scrMemTreePub;
|
||||
char* scrMemTreeGlob;
|
||||
|
||||
scrVmPub_t* scr_VmPub;
|
||||
|
||||
scr_call_t* scr_instanceFunctions;
|
||||
scr_call_t* scr_globalFunctions;
|
||||
|
||||
unsigned int* levelEntityId;
|
||||
|
||||
int* g_script_error_level;
|
||||
jmp_buf* g_script_error;
|
||||
|
||||
scr_classStruct_t* g_classMap;
|
||||
|
||||
void AddRefToValue(VariableValue* value)
|
||||
{
|
||||
if (value->type == SCRIPT_OBJECT)
|
||||
{
|
||||
++scrVarGlob[4 * value->u.entityId];
|
||||
}
|
||||
else if ((value->type & ~1) == SCRIPT_STRING)
|
||||
{
|
||||
static const auto size = is_sp() ? 16 : 12;
|
||||
const auto ref_count = reinterpret_cast<unsigned volatile *>(*scrMemTreePub + size * value
|
||||
->u.stringValue);
|
||||
InterlockedIncrement(ref_count);
|
||||
}
|
||||
else if (value->type == SCRIPT_VECTOR)
|
||||
{
|
||||
if (!*PBYTE(value->u.vectorValue - 1))
|
||||
{
|
||||
++*PWORD(value->u.vectorValue - 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) unsigned int conbuf_append_text_dedicated(const char* message)
|
||||
{
|
||||
static DWORD func = 0x53C790;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov ecx, message
|
||||
call func
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
void Conbuf_AppendText(const char* message)
|
||||
{
|
||||
if(is_dedi())
|
||||
{
|
||||
conbuf_append_text_dedicated(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
reinterpret_cast<void(*)(const char*)>(SELECT_VALUE(0x4C84E0, 0x5CF610, 0))(message);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) unsigned int find_variable_dedicated(unsigned int parentId, unsigned int name)
|
||||
{
|
||||
static DWORD func = 0x4E7ED0;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, name
|
||||
mov ecx, parentId
|
||||
call func
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int FindVariable(const unsigned int parentId, const unsigned int name)
|
||||
{
|
||||
if (is_dedi())
|
||||
{
|
||||
return find_variable_dedicated(parentId, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<unsigned int(*)(unsigned int, unsigned int)> //
|
||||
(SELECT_VALUE(0x4C4E70, 0x5651F0, 0x0))(parentId, name);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) VariableValue get_entity_field_value_dedicated(unsigned int classnum, int entnum, int _offset)
|
||||
{
|
||||
static DWORD func = 0x4F1400;
|
||||
|
||||
__asm
|
||||
{
|
||||
push _offset
|
||||
push entnum
|
||||
mov ecx, classnum
|
||||
call func
|
||||
add esp, 8h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
VariableValue GetEntityFieldValue(const unsigned int classnum, const int entnum, const int offset)
|
||||
{
|
||||
if (is_dedi())
|
||||
{
|
||||
return get_entity_field_value_dedicated(classnum, entnum, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<VariableValue(*)(unsigned int, int, int)> //
|
||||
(SELECT_VALUE(0x530E30, 0x56AF20, 0x0))(classnum, entnum, offset);
|
||||
}
|
||||
}
|
||||
|
||||
void* MT_Alloc(const int numBytes, const int type)
|
||||
{
|
||||
return scrMemTreeGlob + 12 * size_t(MT_AllocIndex(numBytes, type));
|
||||
}
|
||||
|
||||
const float* Scr_AllocVector(const float* v)
|
||||
{
|
||||
const auto mem = static_cast<DWORD*>(MT_Alloc(16, 2));
|
||||
*mem = 0;
|
||||
|
||||
const auto array = reinterpret_cast<float*>(mem + 1);
|
||||
array[0] = v[0];
|
||||
array[1] = v[1];
|
||||
array[2] = v[2];
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
void Scr_ClearOutParams()
|
||||
{
|
||||
const auto num_params = scr_VmPub->outparamcount;
|
||||
for (unsigned int i = num_params; i > 0; --i)
|
||||
{
|
||||
const auto value = scr_VmPub->top[i - 1];
|
||||
RemoveRefToValue(value.type, value.u);
|
||||
}
|
||||
|
||||
scr_VmPub->top -= num_params;
|
||||
}
|
||||
|
||||
scr_entref_t Scr_GetEntityIdRef(const unsigned int id)
|
||||
{
|
||||
static auto class_array = reinterpret_cast<DWORD*>(SELECT_VALUE(0x19AFC84, 0x1E72184, 0x1D3C804));
|
||||
static auto ent_array = reinterpret_cast<WORD*>(SELECT_VALUE(0x19AFC82, 0x1E72182, 0x1D3C802));
|
||||
|
||||
scr_entref_t result{};
|
||||
result.raw.classnum = static_cast<unsigned short>(class_array[2 * id]) >> 8;
|
||||
result.raw.entnum = ent_array[4 * id];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
scr_call_t Scr_GetFunc(const unsigned int index)
|
||||
{
|
||||
if (index > 0x1C7)
|
||||
{
|
||||
return scr_instanceFunctions[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return scr_globalFunctions[index];
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void scr_notify_id_multiplayer(unsigned int id, unsigned int stringValue,
|
||||
unsigned int paramcount)
|
||||
{
|
||||
static DWORD func = 0x56B5E0;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, paramcount
|
||||
push stringValue
|
||||
push id
|
||||
call func
|
||||
add esp, 8h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void scr_notify_id_singleplayer(unsigned int id, unsigned int stringValue,
|
||||
unsigned int paramcount)
|
||||
{
|
||||
static DWORD func = 0x610980;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, paramcount
|
||||
push stringValue
|
||||
push id
|
||||
call func
|
||||
add esp, 8h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
void Scr_NotifyId(unsigned int id, unsigned int stringValue, unsigned int paramcount)
|
||||
{
|
||||
if (is_mp())
|
||||
{
|
||||
return scr_notify_id_multiplayer(id, stringValue, paramcount);
|
||||
}
|
||||
else if (is_sp())
|
||||
{
|
||||
return scr_notify_id_singleplayer(id, stringValue, paramcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<void(*)(unsigned int, unsigned int, unsigned int)>(0x4EFAA0)(id, stringValue, paramcount);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) int scr_set_object_field_dedicated(unsigned int classnum, int entnum, int _offset)
|
||||
{
|
||||
static DWORD func = 0x4B15C0;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov ecx, _offset
|
||||
mov eax, entnum
|
||||
push classnum
|
||||
call func
|
||||
add esp, 4h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
int Scr_SetObjectField(const unsigned int classnum, const int entnum, const int offset)
|
||||
{
|
||||
if (is_dedi())
|
||||
{
|
||||
return scr_set_object_field_dedicated(classnum, entnum, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<int(*)(unsigned int, int, int)> //
|
||||
(SELECT_VALUE(0x42CAD0, 0x52BCC0, 0x0))(classnum, entnum, offset);
|
||||
}
|
||||
}
|
||||
|
||||
const char* SL_ConvertToString(const unsigned int stringValue)
|
||||
{
|
||||
if (!stringValue) return nullptr;
|
||||
|
||||
static const auto size = is_sp() ? 16 : 12;
|
||||
return *scrMemTreePub + size * stringValue + 4;
|
||||
}
|
||||
|
||||
unsigned int SL_GetString(const char* str, const unsigned int user)
|
||||
{
|
||||
return SL_GetStringOfSize(str, user, strlen(str) + 1, 7);
|
||||
}
|
||||
}
|
||||
|
||||
launcher::mode mode = launcher::mode::none;
|
||||
|
||||
launcher::mode get_mode()
|
||||
{
|
||||
if(mode == launcher::mode::none)
|
||||
{
|
||||
throw std::runtime_error("Launcher mode not valid. Something must be wrong.");
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
bool is_mp()
|
||||
{
|
||||
return get_mode() == launcher::mode::multiplayer;
|
||||
}
|
||||
|
||||
bool is_sp()
|
||||
{
|
||||
return get_mode() == launcher::mode::singleplayer;
|
||||
}
|
||||
|
||||
bool is_dedi()
|
||||
{
|
||||
return get_mode() == launcher::mode::server;
|
||||
}
|
||||
|
||||
void initialize(const launcher::mode _mode)
|
||||
{
|
||||
mode = _mode;
|
||||
|
||||
native::Cmd_AddCommand = native::Cmd_AddCommand_t(SELECT_VALUE(0x558820, 0x545DF0, 0));
|
||||
|
||||
native::Com_Error = native::Com_Error_t(SELECT_VALUE(0x425540, 0x555450, 0x4D93F0));
|
||||
|
||||
native::DB_LoadXAssets = native::DB_LoadXAssets_t(SELECT_VALUE(0x48A8E0, 0x4CD020, 0x44F770));
|
||||
|
||||
native::Dvar_SetFromStringByName = native::Dvar_SetFromStringByName_t(SELECT_VALUE(0x4DD090, 0x5BF740, 0x518DF0));
|
||||
|
||||
native::G_RunFrame = native::G_RunFrame_t(SELECT_VALUE(0x52EAA0, 0x50CB70, 0x48AD60));
|
||||
|
||||
native::MSG_ReadData = native::MSG_ReadData_t(SELECT_VALUE(0, 0x5592A0, 0));
|
||||
|
||||
native::MT_AllocIndex = native::MT_AllocIndex_t(SELECT_VALUE(0x4B9610, 0x562080, 0x4E6C30));
|
||||
|
||||
native::RemoveRefToValue = native::RemoveRefToValue_t(SELECT_VALUE(0x477EA0, 0x565730, 0x4E8A40));
|
||||
|
||||
native::SL_GetStringOfSize = native::SL_GetStringOfSize_t(SELECT_VALUE(0x4E13F0, 0x564650, 0x4E7490));
|
||||
|
||||
native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0));
|
||||
|
||||
native::VM_Notify = native::VM_Notify_t(SELECT_VALUE(0x610200, 0x569720, 0x4EF450));
|
||||
|
||||
native::_longjmp = reinterpret_cast<decltype(longjmp)*>(SELECT_VALUE(0x73AC20, 0x7363BC, 0x655558));
|
||||
|
||||
native::cmd_args = reinterpret_cast<int*>(SELECT_VALUE(0x1750750, 0x1C978D0, 0x1B455F8));
|
||||
native::cmd_argc = reinterpret_cast<int*>(SELECT_VALUE(0x1750794, 0x1C97914, 0x1B4563C));
|
||||
native::cmd_argv = reinterpret_cast<const char***>(SELECT_VALUE(0x17507B4, 0x1C97934, 0x1B4565C));
|
||||
|
||||
native::scrVarGlob = reinterpret_cast<short*>(SELECT_VALUE(0x19AFC80, 0x1E72180, 0x1D3C800));
|
||||
native::scrMemTreePub = reinterpret_cast<char**>(SELECT_VALUE(0x196FB00, 0x1E32000, 0x1C152A4));
|
||||
native::scrMemTreeGlob = reinterpret_cast<char*>(SELECT_VALUE(0x186DA00, 0x1D6FF00, 0x1C16600));
|
||||
|
||||
native::scr_VmPub = reinterpret_cast<native::scrVmPub_t*>(SELECT_VALUE(0x1BF2580, 0x20B4A80, 0x1F5B080));
|
||||
|
||||
native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x184CDB0, 0x1D4F258,
|
||||
0x1BF59C8));
|
||||
native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x186C68C, 0x1D6EB34,
|
||||
0x1C152A4
|
||||
));
|
||||
|
||||
native::g_script_error_level = reinterpret_cast<int*>(SELECT_VALUE(0x1BEFCFC, 0x20B21FC, 0x1F5B058));
|
||||
native::g_script_error = reinterpret_cast<jmp_buf*>(SELECT_VALUE(0x1BF1D18, 0x20B4218, 0x1F5A818));
|
||||
|
||||
native::g_classMap = reinterpret_cast<native::scr_classStruct_t*>(SELECT_VALUE(0x92D140, 0x8B4300, 0x7C0408));
|
||||
|
||||
native::levelEntityId = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BCBCA4, 0x208E1A4, 0x1CD873C));
|
||||
}
|
||||
}
|
||||
|
@ -1,95 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#include "structs.hpp"
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
#define SELECT_VALUE(sp, mp, dedi) (game::is_sp() ? (sp) : (game::is_mp() ? (mp) : (dedi)))
|
||||
|
||||
#define SERVER_CD_KEY "Open-IW5-CD-Key"
|
||||
|
||||
namespace game
|
||||
{
|
||||
namespace native
|
||||
{
|
||||
typedef void (*Cmd_AddCommand_t)(const char* cmdName, void (*function)(), cmd_function_t* allocedCmd);
|
||||
extern Cmd_AddCommand_t Cmd_AddCommand;
|
||||
|
||||
typedef void (*Com_Error_t)(int code, const char* fmt, ...);
|
||||
extern Com_Error_t Com_Error;
|
||||
|
||||
typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync);
|
||||
extern DB_LoadXAssets_t DB_LoadXAssets;
|
||||
|
||||
typedef void (*Dvar_SetFromStringByName_t)(const char *dvarName, const char *string);
|
||||
extern Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
||||
|
||||
typedef int (*G_RunFrame_t)(int, int);
|
||||
extern G_RunFrame_t G_RunFrame;
|
||||
|
||||
typedef void (*MSG_ReadData_t)(msg_t* msg, void* data, int len);
|
||||
extern MSG_ReadData_t MSG_ReadData;
|
||||
|
||||
typedef void* (*MT_AllocIndex_t)(int numBytes, int type);
|
||||
extern MT_AllocIndex_t MT_AllocIndex;
|
||||
|
||||
typedef void (*RemoveRefToValue_t)(scriptType_e type, VariableUnion u);
|
||||
extern RemoveRefToValue_t RemoveRefToValue;
|
||||
|
||||
typedef unsigned int (*SL_GetStringOfSize_t)(const char* str, unsigned int user, unsigned int len, int type);
|
||||
extern SL_GetStringOfSize_t SL_GetStringOfSize;
|
||||
|
||||
typedef void (*Sys_ShowConsole_t)();
|
||||
extern Sys_ShowConsole_t Sys_ShowConsole;
|
||||
|
||||
typedef void (*VM_Notify_t)(unsigned int notifyListOwnerId, unsigned int stringValue, VariableValue* top);
|
||||
extern VM_Notify_t VM_Notify;
|
||||
|
||||
extern decltype(longjmp)* _longjmp;
|
||||
|
||||
extern int* cmd_args;
|
||||
extern int* cmd_argc;
|
||||
extern const char*** cmd_argv;
|
||||
|
||||
extern short* scrVarGlob;
|
||||
extern char** scrMemTreePub;
|
||||
extern char* scrMemTreeGlob;
|
||||
|
||||
extern scrVmPub_t* scr_VmPub;
|
||||
|
||||
extern scr_call_t* scr_instanceFunctions;
|
||||
extern scr_call_t* scr_globalFunctions;
|
||||
|
||||
extern unsigned int* levelEntityId;
|
||||
|
||||
extern int* g_script_error_level;
|
||||
extern jmp_buf* g_script_error;
|
||||
|
||||
extern scr_classStruct_t* g_classMap;
|
||||
|
||||
void AddRefToValue(VariableValue* value);
|
||||
|
||||
void Conbuf_AppendText(const char* message);
|
||||
|
||||
unsigned int FindVariable(unsigned int parentId, unsigned int name);
|
||||
|
||||
VariableValue GetEntityFieldValue(unsigned int classnum, int entnum, int offset);
|
||||
|
||||
void* MT_Alloc(int numBytes, int type);
|
||||
|
||||
const float* Scr_AllocVector(const float* v);
|
||||
void Scr_ClearOutParams();
|
||||
scr_entref_t Scr_GetEntityIdRef(unsigned int id);
|
||||
scr_call_t Scr_GetFunc(unsigned int index);
|
||||
void Scr_NotifyId(unsigned int id, unsigned int stringValue, unsigned int paramcount);
|
||||
int Scr_SetObjectField(unsigned int classnum, int entnum, int offset);
|
||||
|
||||
const char* SL_ConvertToString(unsigned int stringValue);
|
||||
unsigned int SL_GetString(const char* str, unsigned int user);
|
||||
}
|
||||
|
||||
bool is_mp();
|
||||
bool is_sp();
|
||||
bool is_dedi();
|
||||
|
||||
void initialize(launcher::mode mode);
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "structs.hpp"
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
#define SELECT_VALUE(sp, mp, dedi) (game::is_sp() ? (sp) : (game::is_mp() ? (mp) : (dedi)))
|
||||
|
||||
#define SERVER_CD_KEY "Open-IW5-CD-Key"
|
||||
|
||||
namespace game
|
||||
{
|
||||
namespace native
|
||||
{
|
||||
typedef void (*Cmd_AddCommand_t)(const char* cmdName, void (*function)(), cmd_function_t* allocedCmd);
|
||||
extern Cmd_AddCommand_t Cmd_AddCommand;
|
||||
|
||||
typedef void (*Com_Error_t)(int code, const char* fmt, ...);
|
||||
extern Com_Error_t Com_Error;
|
||||
|
||||
typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync);
|
||||
extern DB_LoadXAssets_t DB_LoadXAssets;
|
||||
|
||||
typedef void (*Dvar_SetFromStringByName_t)(const char *dvarName, const char *string);
|
||||
extern Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
|
||||
|
||||
typedef int (*G_RunFrame_t)(int, int);
|
||||
extern G_RunFrame_t G_RunFrame;
|
||||
|
||||
typedef void (*MSG_ReadData_t)(msg_t* msg, void* data, int len);
|
||||
extern MSG_ReadData_t MSG_ReadData;
|
||||
|
||||
typedef void* (*MT_AllocIndex_t)(int numBytes, int type);
|
||||
extern MT_AllocIndex_t MT_AllocIndex;
|
||||
|
||||
typedef void (*RemoveRefToValue_t)(scriptType_e type, VariableUnion u);
|
||||
extern RemoveRefToValue_t RemoveRefToValue;
|
||||
|
||||
typedef unsigned int (*SL_GetStringOfSize_t)(const char* str, unsigned int user, unsigned int len, int type);
|
||||
extern SL_GetStringOfSize_t SL_GetStringOfSize;
|
||||
|
||||
typedef void (*Sys_ShowConsole_t)();
|
||||
extern Sys_ShowConsole_t Sys_ShowConsole;
|
||||
|
||||
typedef void (*VM_Notify_t)(unsigned int notifyListOwnerId, unsigned int stringValue, VariableValue* top);
|
||||
extern VM_Notify_t VM_Notify;
|
||||
|
||||
extern decltype(longjmp)* _longjmp;
|
||||
|
||||
extern int* cmd_args;
|
||||
extern int* cmd_argc;
|
||||
extern const char*** cmd_argv;
|
||||
|
||||
extern short* scrVarGlob;
|
||||
extern char** scrMemTreePub;
|
||||
extern char* scrMemTreeGlob;
|
||||
|
||||
extern scrVmPub_t* scr_VmPub;
|
||||
|
||||
extern scr_call_t* scr_instanceFunctions;
|
||||
extern scr_call_t* scr_globalFunctions;
|
||||
|
||||
extern unsigned int* levelEntityId;
|
||||
|
||||
extern int* g_script_error_level;
|
||||
extern jmp_buf* g_script_error;
|
||||
|
||||
extern scr_classStruct_t* g_classMap;
|
||||
|
||||
void AddRefToValue(VariableValue* value);
|
||||
|
||||
void Conbuf_AppendText(const char* message);
|
||||
|
||||
unsigned int FindVariable(unsigned int parentId, unsigned int name);
|
||||
|
||||
VariableValue GetEntityFieldValue(unsigned int classnum, int entnum, int offset);
|
||||
|
||||
void* MT_Alloc(int numBytes, int type);
|
||||
|
||||
const float* Scr_AllocVector(const float* v);
|
||||
void Scr_ClearOutParams();
|
||||
scr_entref_t Scr_GetEntityIdRef(unsigned int id);
|
||||
scr_call_t Scr_GetFunc(unsigned int index);
|
||||
void Scr_NotifyId(unsigned int id, unsigned int stringValue, unsigned int paramcount);
|
||||
int Scr_SetObjectField(unsigned int classnum, int entnum, int offset);
|
||||
|
||||
const char* SL_ConvertToString(unsigned int stringValue);
|
||||
unsigned int SL_GetString(const char* str, unsigned int user);
|
||||
}
|
||||
|
||||
bool is_mp();
|
||||
bool is_sp();
|
||||
bool is_dedi();
|
||||
|
||||
void initialize(launcher::mode mode);
|
||||
}
|
||||
|
@ -1,115 +1,115 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
|
||||
doc_host_ui_handler::doc_host_ui_handler(html_frame* frame): frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
||||
{
|
||||
auto client_site = this->frame_->get_client_site();
|
||||
if (client_site)
|
||||
{
|
||||
return client_site->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG doc_host_ui_handler::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG doc_host_ui_handler::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::ShowContextMenu(DWORD /*dwID*/, POINT* /*ppt*/, IUnknown* /*pcmdtReserved*/,
|
||||
IDispatch* /*pdispReserved*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::ShowUI(DWORD /*dwID*/, IOleInPlaceActiveObject* /*pActiveObject*/,
|
||||
IOleCommandTarget* /*pCommandTarget*/,
|
||||
IOleInPlaceFrame* /*pFrame*/, IOleInPlaceUIWindow* /*pDoc*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::HideUI()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::UpdateUI()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::EnableModeless(BOOL /*fEnable*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::OnDocWindowActivate(BOOL /*fActivate*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::OnFrameWindowActivate(BOOL /*fActivate*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::ResizeBorder(LPCRECT /*prcBorder*/, IOleInPlaceUIWindow* /*pUIWindow*/,
|
||||
BOOL /*fRameWindow*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::TranslateAcceleratorA(LPMSG /*lpMsg*/, const GUID* pguidCmdGroup, DWORD /*nCmdID*/)
|
||||
{
|
||||
pguidCmdGroup = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetOptionKeyPath(LPOLESTR* /*pchKey*/, DWORD /*dw*/)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetDropTarget(IDropTarget* /*pDropTarget*/, IDropTarget** /*ppDropTarget*/)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetExternal(IDispatch** ppDispatch)
|
||||
{
|
||||
*ppDispatch = this->frame_->get_html_dispatch();
|
||||
return (*ppDispatch) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::FilterDataObject(IDataObject* /*pDO*/, IDataObject** ppDORet)
|
||||
{
|
||||
*ppDORet = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE doc_host_ui_handler::TranslateUrl(DWORD /*dwTranslate*/, OLECHAR __RPC_FAR* /*pchURLIn*/,
|
||||
OLECHAR __RPC_FAR* __RPC_FAR* ppchURLOut)
|
||||
{
|
||||
*ppchURLOut = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo)
|
||||
{
|
||||
pInfo->cbSize = sizeof(DOCHOSTUIINFO);
|
||||
pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_DPI_AWARE | DOCHOSTUIFLAG_SCROLL_NO;
|
||||
pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
|
||||
doc_host_ui_handler::doc_host_ui_handler(html_frame* frame): frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
||||
{
|
||||
auto client_site = this->frame_->get_client_site();
|
||||
if (client_site)
|
||||
{
|
||||
return client_site->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG doc_host_ui_handler::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG doc_host_ui_handler::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::ShowContextMenu(DWORD /*dwID*/, POINT* /*ppt*/, IUnknown* /*pcmdtReserved*/,
|
||||
IDispatch* /*pdispReserved*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::ShowUI(DWORD /*dwID*/, IOleInPlaceActiveObject* /*pActiveObject*/,
|
||||
IOleCommandTarget* /*pCommandTarget*/,
|
||||
IOleInPlaceFrame* /*pFrame*/, IOleInPlaceUIWindow* /*pDoc*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::HideUI()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::UpdateUI()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::EnableModeless(BOOL /*fEnable*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::OnDocWindowActivate(BOOL /*fActivate*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::OnFrameWindowActivate(BOOL /*fActivate*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::ResizeBorder(LPCRECT /*prcBorder*/, IOleInPlaceUIWindow* /*pUIWindow*/,
|
||||
BOOL /*fRameWindow*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::TranslateAcceleratorA(LPMSG /*lpMsg*/, const GUID* pguidCmdGroup, DWORD /*nCmdID*/)
|
||||
{
|
||||
pguidCmdGroup = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetOptionKeyPath(LPOLESTR* /*pchKey*/, DWORD /*dw*/)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetDropTarget(IDropTarget* /*pDropTarget*/, IDropTarget** /*ppDropTarget*/)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetExternal(IDispatch** ppDispatch)
|
||||
{
|
||||
*ppDispatch = this->frame_->get_html_dispatch();
|
||||
return (*ppDispatch) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::FilterDataObject(IDataObject* /*pDO*/, IDataObject** ppDORet)
|
||||
{
|
||||
*ppDORet = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE doc_host_ui_handler::TranslateUrl(DWORD /*dwTranslate*/, OLECHAR __RPC_FAR* /*pchURLIn*/,
|
||||
OLECHAR __RPC_FAR* __RPC_FAR* ppchURLOut)
|
||||
{
|
||||
*ppchURLOut = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo)
|
||||
{
|
||||
pInfo->cbSize = sizeof(DOCHOSTUIINFO);
|
||||
pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_DPI_AWARE | DOCHOSTUIFLAG_SCROLL_NO;
|
||||
pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -1,47 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class doc_host_ui_handler final : public IDocHostUIHandler
|
||||
{
|
||||
public:
|
||||
doc_host_ui_handler(html_frame* frame);
|
||||
virtual ~doc_host_ui_handler() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IDocHostUIHandler interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE ShowContextMenu(
|
||||
DWORD dwID,
|
||||
POINT __RPC_FAR * ppt,
|
||||
IUnknown __RPC_FAR * pcmdtReserved,
|
||||
IDispatch __RPC_FAR * pdispReserved) override;
|
||||
HRESULT STDMETHODCALLTYPE ShowUI(
|
||||
DWORD dwID,
|
||||
IOleInPlaceActiveObject __RPC_FAR * pActiveObject,
|
||||
IOleCommandTarget __RPC_FAR * pCommandTarget,
|
||||
IOleInPlaceFrame __RPC_FAR * pFrame,
|
||||
IOleInPlaceUIWindow __RPC_FAR * pDoc) override;
|
||||
HRESULT STDMETHODCALLTYPE GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo) override;
|
||||
HRESULT STDMETHODCALLTYPE HideUI() override;
|
||||
HRESULT STDMETHODCALLTYPE UpdateUI() override;
|
||||
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override;
|
||||
HRESULT STDMETHODCALLTYPE OnDocWindowActivate(BOOL fActivate) override;
|
||||
HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(BOOL fActivate) override;
|
||||
HRESULT STDMETHODCALLTYPE ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR * pUIWindow,
|
||||
BOOL fRameWindow) override;
|
||||
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpMsg, const GUID __RPC_FAR * pguidCmdGroup, DWORD nCmdID)
|
||||
override;
|
||||
HRESULT STDMETHODCALLTYPE GetOptionKeyPath(LPOLESTR __RPC_FAR * pchKey, DWORD dw) override;
|
||||
HRESULT STDMETHODCALLTYPE GetDropTarget(IDropTarget __RPC_FAR * pDropTarget,
|
||||
IDropTarget __RPC_FAR *__RPC_FAR * ppDropTarget) override;
|
||||
HRESULT STDMETHODCALLTYPE GetExternal(IDispatch __RPC_FAR *__RPC_FAR * ppDispatch) override;
|
||||
HRESULT STDMETHODCALLTYPE TranslateUrl(DWORD dwTranslate, OLECHAR __RPC_FAR * pchURLIn,
|
||||
OLECHAR __RPC_FAR *__RPC_FAR * ppchURLOut) override;
|
||||
HRESULT STDMETHODCALLTYPE FilterDataObject(IDataObject __RPC_FAR * pDO, IDataObject __RPC_FAR *__RPC_FAR * ppDORet)
|
||||
override;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class doc_host_ui_handler final : public IDocHostUIHandler
|
||||
{
|
||||
public:
|
||||
doc_host_ui_handler(html_frame* frame);
|
||||
virtual ~doc_host_ui_handler() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IDocHostUIHandler interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE ShowContextMenu(
|
||||
DWORD dwID,
|
||||
POINT __RPC_FAR * ppt,
|
||||
IUnknown __RPC_FAR * pcmdtReserved,
|
||||
IDispatch __RPC_FAR * pdispReserved) override;
|
||||
HRESULT STDMETHODCALLTYPE ShowUI(
|
||||
DWORD dwID,
|
||||
IOleInPlaceActiveObject __RPC_FAR * pActiveObject,
|
||||
IOleCommandTarget __RPC_FAR * pCommandTarget,
|
||||
IOleInPlaceFrame __RPC_FAR * pFrame,
|
||||
IOleInPlaceUIWindow __RPC_FAR * pDoc) override;
|
||||
HRESULT STDMETHODCALLTYPE GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo) override;
|
||||
HRESULT STDMETHODCALLTYPE HideUI() override;
|
||||
HRESULT STDMETHODCALLTYPE UpdateUI() override;
|
||||
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override;
|
||||
HRESULT STDMETHODCALLTYPE OnDocWindowActivate(BOOL fActivate) override;
|
||||
HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(BOOL fActivate) override;
|
||||
HRESULT STDMETHODCALLTYPE ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR * pUIWindow,
|
||||
BOOL fRameWindow) override;
|
||||
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpMsg, const GUID __RPC_FAR * pguidCmdGroup, DWORD nCmdID)
|
||||
override;
|
||||
HRESULT STDMETHODCALLTYPE GetOptionKeyPath(LPOLESTR __RPC_FAR * pchKey, DWORD dw) override;
|
||||
HRESULT STDMETHODCALLTYPE GetDropTarget(IDropTarget __RPC_FAR * pDropTarget,
|
||||
IDropTarget __RPC_FAR *__RPC_FAR * ppDropTarget) override;
|
||||
HRESULT STDMETHODCALLTYPE GetExternal(IDispatch __RPC_FAR *__RPC_FAR * ppDispatch) override;
|
||||
HRESULT STDMETHODCALLTYPE TranslateUrl(DWORD dwTranslate, OLECHAR __RPC_FAR * pchURLIn,
|
||||
OLECHAR __RPC_FAR *__RPC_FAR * ppchURLOut) override;
|
||||
HRESULT STDMETHODCALLTYPE FilterDataObject(IDataObject __RPC_FAR * pDO, IDataObject __RPC_FAR *__RPC_FAR * ppDORet)
|
||||
override;
|
||||
};
|
||||
|
@ -1,48 +1,48 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_argument.hpp"
|
||||
|
||||
html_argument::html_argument(VARIANT* val) : value_(val)
|
||||
{
|
||||
}
|
||||
|
||||
bool html_argument::is_empty() const
|
||||
{
|
||||
return this->value_ == nullptr || this->value_->vt == VT_EMPTY;
|
||||
}
|
||||
|
||||
bool html_argument::is_string() const
|
||||
{
|
||||
if (this->is_empty()) return false;
|
||||
return this->value_->vt == VT_BSTR;
|
||||
}
|
||||
|
||||
bool html_argument::is_number() const
|
||||
{
|
||||
if (this->is_empty()) return false;
|
||||
return this->value_->vt == VT_I4;
|
||||
}
|
||||
|
||||
bool html_argument::is_bool() const
|
||||
{
|
||||
if (this->is_empty()) return false;
|
||||
return this->value_->vt == VT_BOOL;
|
||||
}
|
||||
|
||||
std::string html_argument::get_string() const
|
||||
{
|
||||
if (!this->is_string()) return {};
|
||||
std::wstring wide_string(this->value_->bstrVal);
|
||||
return std::string(wide_string.begin(), wide_string.end());
|
||||
}
|
||||
|
||||
int html_argument::get_number() const
|
||||
{
|
||||
if (!this->is_number()) return 0;
|
||||
return this->value_->intVal;
|
||||
}
|
||||
|
||||
bool html_argument::get_bool() const
|
||||
{
|
||||
if(!this->is_bool()) return false;
|
||||
return this->value_->boolVal != FALSE;
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "html_argument.hpp"
|
||||
|
||||
html_argument::html_argument(VARIANT* val) : value_(val)
|
||||
{
|
||||
}
|
||||
|
||||
bool html_argument::is_empty() const
|
||||
{
|
||||
return this->value_ == nullptr || this->value_->vt == VT_EMPTY;
|
||||
}
|
||||
|
||||
bool html_argument::is_string() const
|
||||
{
|
||||
if (this->is_empty()) return false;
|
||||
return this->value_->vt == VT_BSTR;
|
||||
}
|
||||
|
||||
bool html_argument::is_number() const
|
||||
{
|
||||
if (this->is_empty()) return false;
|
||||
return this->value_->vt == VT_I4;
|
||||
}
|
||||
|
||||
bool html_argument::is_bool() const
|
||||
{
|
||||
if (this->is_empty()) return false;
|
||||
return this->value_->vt == VT_BOOL;
|
||||
}
|
||||
|
||||
std::string html_argument::get_string() const
|
||||
{
|
||||
if (!this->is_string()) return {};
|
||||
std::wstring wide_string(this->value_->bstrVal);
|
||||
return std::string(wide_string.begin(), wide_string.end());
|
||||
}
|
||||
|
||||
int html_argument::get_number() const
|
||||
{
|
||||
if (!this->is_number()) return 0;
|
||||
return this->value_->intVal;
|
||||
}
|
||||
|
||||
bool html_argument::get_bool() const
|
||||
{
|
||||
if(!this->is_bool()) return false;
|
||||
return this->value_->boolVal != FALSE;
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
class html_argument final
|
||||
{
|
||||
public:
|
||||
html_argument(VARIANT* val);
|
||||
|
||||
bool is_empty() const;
|
||||
|
||||
bool is_string() const;
|
||||
bool is_number() const;
|
||||
bool is_bool() const;
|
||||
|
||||
std::string get_string() const;
|
||||
int get_number() const;
|
||||
bool get_bool() const;
|
||||
|
||||
private:
|
||||
VARIANT* value_;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
class html_argument final
|
||||
{
|
||||
public:
|
||||
html_argument(VARIANT* val);
|
||||
|
||||
bool is_empty() const;
|
||||
|
||||
bool is_string() const;
|
||||
bool is_number() const;
|
||||
bool is_bool() const;
|
||||
|
||||
std::string get_string() const;
|
||||
int get_number() const;
|
||||
bool get_bool() const;
|
||||
|
||||
private:
|
||||
VARIANT* value_;
|
||||
};
|
||||
|
@ -1,61 +1,61 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
|
||||
html_dispatch::html_dispatch(html_frame* frame) : frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::QueryInterface(const IID& riid, LPVOID* ppvObj)
|
||||
{
|
||||
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) ||
|
||||
!memcmp(&riid, &IID_IDispatch, sizeof(GUID)))
|
||||
{
|
||||
*ppvObj = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppvObj = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG html_dispatch::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG html_dispatch::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::GetTypeInfoCount(UINT* pctinfo)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::GetIDsOfNames(const IID& riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
|
||||
{
|
||||
for (unsigned int i = 0; i < cNames; ++i)
|
||||
{
|
||||
std::wstring wide_name(rgszNames[i]);
|
||||
std::string name(wide_name.begin(), wide_name.end());
|
||||
|
||||
rgDispId[i] = this->frame_->get_callback_id(name);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::Invoke(DISPID dispIdMember, const IID& riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
|
||||
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
|
||||
{
|
||||
html_frame::callback_params params(pDispParams, pVarResult);
|
||||
this->frame_->invoke_callback(dispIdMember, ¶ms);
|
||||
return S_OK;
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
|
||||
html_dispatch::html_dispatch(html_frame* frame) : frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::QueryInterface(const IID& riid, LPVOID* ppvObj)
|
||||
{
|
||||
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) ||
|
||||
!memcmp(&riid, &IID_IDispatch, sizeof(GUID)))
|
||||
{
|
||||
*ppvObj = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppvObj = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG html_dispatch::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG html_dispatch::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::GetTypeInfoCount(UINT* pctinfo)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::GetIDsOfNames(const IID& riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
|
||||
{
|
||||
for (unsigned int i = 0; i < cNames; ++i)
|
||||
{
|
||||
std::wstring wide_name(rgszNames[i]);
|
||||
std::string name(wide_name.begin(), wide_name.end());
|
||||
|
||||
rgDispId[i] = this->frame_->get_callback_id(name);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::Invoke(DISPID dispIdMember, const IID& riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
|
||||
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
|
||||
{
|
||||
html_frame::callback_params params(pDispParams, pVarResult);
|
||||
this->frame_->invoke_callback(dispIdMember, ¶ms);
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class html_dispatch final : public IDispatch
|
||||
{
|
||||
public:
|
||||
html_dispatch(html_frame* frame);
|
||||
virtual ~html_dispatch() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IDispatch interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override;
|
||||
HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override;
|
||||
HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
|
||||
override;
|
||||
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
|
||||
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class html_dispatch final : public IDispatch
|
||||
{
|
||||
public:
|
||||
html_dispatch(html_frame* frame);
|
||||
virtual ~html_dispatch() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IDispatch interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override;
|
||||
HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override;
|
||||
HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
|
||||
override;
|
||||
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
|
||||
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
|
||||
};
|
||||
|
@ -1,262 +1,262 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
|
||||
std::atomic<int> html_frame::frame_count_ = 0;
|
||||
|
||||
html_frame::callback_params::callback_params(DISPPARAMS* params, VARIANT* res) : result(res)
|
||||
{
|
||||
for (auto i = params->cArgs; i > 0; --i)
|
||||
{
|
||||
auto param = ¶ms->rgvarg[i - 1];
|
||||
this->arguments.emplace_back(param);
|
||||
}
|
||||
}
|
||||
|
||||
html_frame::html_frame() : in_place_frame_(this), in_place_site_(this), ui_handler_(this), client_site_(this),
|
||||
html_dispatch_(this)
|
||||
{
|
||||
if (frame_count_++ == 0 && OleInitialize(nullptr) != S_OK)
|
||||
{
|
||||
throw std::runtime_error("Unable to initialize the OLE library");
|
||||
}
|
||||
|
||||
set_browser_feature("FEATURE_BROWSER_EMULATION", 11000);
|
||||
set_browser_feature("FEATURE_GPU_RENDERING", 1);
|
||||
}
|
||||
|
||||
html_frame::~html_frame()
|
||||
{
|
||||
if (--frame_count_ <= 0)
|
||||
{
|
||||
frame_count_ = 0;
|
||||
OleUninitialize();
|
||||
}
|
||||
}
|
||||
|
||||
void html_frame::object_deleter(IUnknown* object)
|
||||
{
|
||||
if (object)
|
||||
{
|
||||
object->Release();
|
||||
}
|
||||
}
|
||||
|
||||
HWND html_frame::get_window() const
|
||||
{
|
||||
return this->window_;
|
||||
}
|
||||
|
||||
std::shared_ptr<IOleObject> html_frame::get_browser_object() const
|
||||
{
|
||||
return this->browser_object_;
|
||||
}
|
||||
|
||||
ole_in_place_frame* html_frame::get_in_place_frame()
|
||||
{
|
||||
return &this->in_place_frame_;
|
||||
}
|
||||
|
||||
ole_in_place_site* html_frame::get_in_place_site()
|
||||
{
|
||||
return &this->in_place_site_;
|
||||
}
|
||||
|
||||
doc_host_ui_handler* html_frame::get_ui_handler()
|
||||
{
|
||||
return &this->ui_handler_;
|
||||
}
|
||||
|
||||
ole_client_site* html_frame::get_client_site()
|
||||
{
|
||||
return &this->client_site_;
|
||||
}
|
||||
|
||||
html_dispatch* html_frame::get_html_dispatch()
|
||||
{
|
||||
return &this->html_dispatch_;
|
||||
}
|
||||
|
||||
std::shared_ptr<IWebBrowser2> html_frame::get_web_browser() const
|
||||
{
|
||||
if (!this->browser_object_) return {};
|
||||
|
||||
IWebBrowser2* web_browser = nullptr;
|
||||
if (this->browser_object_->QueryInterface(IID_IWebBrowser2, reinterpret_cast<void**>(&web_browser)) || !web_browser)
|
||||
return {};
|
||||
|
||||
return std::shared_ptr<IWebBrowser2>(web_browser, object_deleter);
|
||||
}
|
||||
|
||||
std::shared_ptr<IDispatch> html_frame::get_dispatch() const
|
||||
{
|
||||
const auto web_browser = this->get_web_browser();
|
||||
if (!web_browser) return {};
|
||||
|
||||
IDispatch* dispatch = nullptr;
|
||||
if (web_browser->get_Document(&dispatch) || !dispatch) return {};
|
||||
|
||||
return std::shared_ptr<IDispatch>(dispatch, object_deleter);
|
||||
}
|
||||
|
||||
std::shared_ptr<IHTMLDocument2> html_frame::get_document() const
|
||||
{
|
||||
const auto dispatch = this->get_dispatch();
|
||||
if (!dispatch) return {};
|
||||
|
||||
IHTMLDocument2* document = nullptr;
|
||||
if (dispatch->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void**>(&document)) || !document) return {};
|
||||
|
||||
return std::shared_ptr<IHTMLDocument2>(document, object_deleter);
|
||||
}
|
||||
|
||||
void html_frame::initialize(const HWND window)
|
||||
{
|
||||
if (this->window_) return;
|
||||
this->window_ = window;
|
||||
|
||||
this->create_browser();
|
||||
this->initialize_browser();
|
||||
}
|
||||
|
||||
void html_frame::create_browser()
|
||||
{
|
||||
LPCLASSFACTORY class_factory = nullptr;
|
||||
if (CoGetClassObject(CLSID_WebBrowser, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, nullptr, IID_IClassFactory,
|
||||
reinterpret_cast<void **>(&class_factory)) || !class_factory)
|
||||
{
|
||||
throw std::runtime_error("Unable to get the class factory");
|
||||
}
|
||||
|
||||
IOleObject* browser_object = nullptr;
|
||||
class_factory->CreateInstance(nullptr, IID_IOleObject, reinterpret_cast<void**>(&browser_object));
|
||||
class_factory->Release();
|
||||
|
||||
if (!browser_object)
|
||||
{
|
||||
throw std::runtime_error("Unable to create browser object");
|
||||
}
|
||||
|
||||
this->browser_object_ = std::shared_ptr<IOleObject>(browser_object, [](IOleObject* browser_object)
|
||||
{
|
||||
if (browser_object)
|
||||
{
|
||||
browser_object->Close(OLECLOSE_NOSAVE);
|
||||
object_deleter(browser_object);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void html_frame::initialize_browser()
|
||||
{
|
||||
this->browser_object_->SetClientSite(this->get_client_site());
|
||||
this->browser_object_->SetHostNames(L"Hostname", nullptr);
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(this->get_window(), &rect);
|
||||
OleSetContainedObject(this->browser_object_.get(), TRUE);
|
||||
|
||||
this->browser_object_->DoVerb(OLEIVERB_SHOW, nullptr, this->get_client_site(), -1, this->get_window(), &rect);
|
||||
this->resize(rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
void html_frame::set_browser_feature(const std::string& feature, DWORD value)
|
||||
{
|
||||
const auto registry_path = R"(SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\)" + feature;
|
||||
|
||||
HKEY key = nullptr;
|
||||
if (RegOpenKeyExA(
|
||||
HKEY_CURRENT_USER, registry_path.data(), 0,
|
||||
KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
const utils::nt::module self;
|
||||
const auto name = self.get_name();
|
||||
RegSetValueExA(key, name.data(), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
|
||||
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
void html_frame::resize(const DWORD width, const DWORD height) const
|
||||
{
|
||||
auto web_browser = this->get_web_browser();
|
||||
if (web_browser)
|
||||
{
|
||||
web_browser->put_Left(0);
|
||||
web_browser->put_Top(0);
|
||||
web_browser->put_Width(width);
|
||||
web_browser->put_Height(height);
|
||||
}
|
||||
}
|
||||
|
||||
bool html_frame::load_url(const std::string& url) const
|
||||
{
|
||||
auto web_browser = this->get_web_browser();
|
||||
if (!web_browser) return false;
|
||||
|
||||
std::wstring wide_url(url.begin(), url.end());
|
||||
|
||||
VARIANT my_url;
|
||||
VariantInit(&my_url);
|
||||
my_url.vt = VT_BSTR;
|
||||
my_url.bstrVal = SysAllocString(wide_url.data());
|
||||
|
||||
const auto _ = gsl::finally([&my_url]() { VariantClear(&my_url); });
|
||||
if (!my_url.bstrVal) return false;
|
||||
|
||||
return SUCCEEDED(web_browser->Navigate2(&my_url, nullptr, nullptr, nullptr, nullptr));
|
||||
}
|
||||
|
||||
bool html_frame::load_html(const std::string& html) const
|
||||
{
|
||||
if (!this->load_url("about:blank")) return false;
|
||||
|
||||
const auto document = this->get_document();
|
||||
if (!document) return false;
|
||||
|
||||
SAFEARRAYBOUND safe_array_bound = {1, 0};
|
||||
auto safe_array = SafeArrayCreate(VT_VARIANT, 1, &safe_array_bound);
|
||||
if (!safe_array) return false;
|
||||
|
||||
const auto _ = gsl::finally([safe_array]() { SafeArrayDestroy(safe_array); });
|
||||
|
||||
VARIANT* variant = nullptr;
|
||||
if (SafeArrayAccessData(safe_array, reinterpret_cast<void**>(&variant)) || !variant) return false;
|
||||
|
||||
std::wstring wide_html(html.begin(), html.end());
|
||||
|
||||
variant->vt = VT_BSTR;
|
||||
variant->bstrVal = SysAllocString(wide_html.data());
|
||||
if (!variant->bstrVal) return false;
|
||||
|
||||
document->write(safe_array);
|
||||
document->close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int html_frame::get_callback_id(const std::string& name)
|
||||
{
|
||||
for (auto i = 0u; i < this->callbacks_.size(); ++i)
|
||||
{
|
||||
if (this->callbacks_[i].first == name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void html_frame::invoke_callback(const int id, callback_params* params)
|
||||
{
|
||||
if (id >= 0 && static_cast<unsigned int>(id) < this->callbacks_.size())
|
||||
{
|
||||
this->callbacks_[id].second(params);
|
||||
}
|
||||
}
|
||||
|
||||
void html_frame::register_callback(const std::string& name, const std::function<void(callback_params*)>& callback)
|
||||
{
|
||||
this->callbacks_.emplace_back(name, callback);
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
|
||||
std::atomic<int> html_frame::frame_count_ = 0;
|
||||
|
||||
html_frame::callback_params::callback_params(DISPPARAMS* params, VARIANT* res) : result(res)
|
||||
{
|
||||
for (auto i = params->cArgs; i > 0; --i)
|
||||
{
|
||||
auto param = ¶ms->rgvarg[i - 1];
|
||||
this->arguments.emplace_back(param);
|
||||
}
|
||||
}
|
||||
|
||||
html_frame::html_frame() : in_place_frame_(this), in_place_site_(this), ui_handler_(this), client_site_(this),
|
||||
html_dispatch_(this)
|
||||
{
|
||||
if (frame_count_++ == 0 && OleInitialize(nullptr) != S_OK)
|
||||
{
|
||||
throw std::runtime_error("Unable to initialize the OLE library");
|
||||
}
|
||||
|
||||
set_browser_feature("FEATURE_BROWSER_EMULATION", 11000);
|
||||
set_browser_feature("FEATURE_GPU_RENDERING", 1);
|
||||
}
|
||||
|
||||
html_frame::~html_frame()
|
||||
{
|
||||
if (--frame_count_ <= 0)
|
||||
{
|
||||
frame_count_ = 0;
|
||||
OleUninitialize();
|
||||
}
|
||||
}
|
||||
|
||||
void html_frame::object_deleter(IUnknown* object)
|
||||
{
|
||||
if (object)
|
||||
{
|
||||
object->Release();
|
||||
}
|
||||
}
|
||||
|
||||
HWND html_frame::get_window() const
|
||||
{
|
||||
return this->window_;
|
||||
}
|
||||
|
||||
std::shared_ptr<IOleObject> html_frame::get_browser_object() const
|
||||
{
|
||||
return this->browser_object_;
|
||||
}
|
||||
|
||||
ole_in_place_frame* html_frame::get_in_place_frame()
|
||||
{
|
||||
return &this->in_place_frame_;
|
||||
}
|
||||
|
||||
ole_in_place_site* html_frame::get_in_place_site()
|
||||
{
|
||||
return &this->in_place_site_;
|
||||
}
|
||||
|
||||
doc_host_ui_handler* html_frame::get_ui_handler()
|
||||
{
|
||||
return &this->ui_handler_;
|
||||
}
|
||||
|
||||
ole_client_site* html_frame::get_client_site()
|
||||
{
|
||||
return &this->client_site_;
|
||||
}
|
||||
|
||||
html_dispatch* html_frame::get_html_dispatch()
|
||||
{
|
||||
return &this->html_dispatch_;
|
||||
}
|
||||
|
||||
std::shared_ptr<IWebBrowser2> html_frame::get_web_browser() const
|
||||
{
|
||||
if (!this->browser_object_) return {};
|
||||
|
||||
IWebBrowser2* web_browser = nullptr;
|
||||
if (this->browser_object_->QueryInterface(IID_IWebBrowser2, reinterpret_cast<void**>(&web_browser)) || !web_browser)
|
||||
return {};
|
||||
|
||||
return std::shared_ptr<IWebBrowser2>(web_browser, object_deleter);
|
||||
}
|
||||
|
||||
std::shared_ptr<IDispatch> html_frame::get_dispatch() const
|
||||
{
|
||||
const auto web_browser = this->get_web_browser();
|
||||
if (!web_browser) return {};
|
||||
|
||||
IDispatch* dispatch = nullptr;
|
||||
if (web_browser->get_Document(&dispatch) || !dispatch) return {};
|
||||
|
||||
return std::shared_ptr<IDispatch>(dispatch, object_deleter);
|
||||
}
|
||||
|
||||
std::shared_ptr<IHTMLDocument2> html_frame::get_document() const
|
||||
{
|
||||
const auto dispatch = this->get_dispatch();
|
||||
if (!dispatch) return {};
|
||||
|
||||
IHTMLDocument2* document = nullptr;
|
||||
if (dispatch->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void**>(&document)) || !document) return {};
|
||||
|
||||
return std::shared_ptr<IHTMLDocument2>(document, object_deleter);
|
||||
}
|
||||
|
||||
void html_frame::initialize(const HWND window)
|
||||
{
|
||||
if (this->window_) return;
|
||||
this->window_ = window;
|
||||
|
||||
this->create_browser();
|
||||
this->initialize_browser();
|
||||
}
|
||||
|
||||
void html_frame::create_browser()
|
||||
{
|
||||
LPCLASSFACTORY class_factory = nullptr;
|
||||
if (CoGetClassObject(CLSID_WebBrowser, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, nullptr, IID_IClassFactory,
|
||||
reinterpret_cast<void **>(&class_factory)) || !class_factory)
|
||||
{
|
||||
throw std::runtime_error("Unable to get the class factory");
|
||||
}
|
||||
|
||||
IOleObject* browser_object = nullptr;
|
||||
class_factory->CreateInstance(nullptr, IID_IOleObject, reinterpret_cast<void**>(&browser_object));
|
||||
class_factory->Release();
|
||||
|
||||
if (!browser_object)
|
||||
{
|
||||
throw std::runtime_error("Unable to create browser object");
|
||||
}
|
||||
|
||||
this->browser_object_ = std::shared_ptr<IOleObject>(browser_object, [](IOleObject* browser_object)
|
||||
{
|
||||
if (browser_object)
|
||||
{
|
||||
browser_object->Close(OLECLOSE_NOSAVE);
|
||||
object_deleter(browser_object);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void html_frame::initialize_browser()
|
||||
{
|
||||
this->browser_object_->SetClientSite(this->get_client_site());
|
||||
this->browser_object_->SetHostNames(L"Hostname", nullptr);
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(this->get_window(), &rect);
|
||||
OleSetContainedObject(this->browser_object_.get(), TRUE);
|
||||
|
||||
this->browser_object_->DoVerb(OLEIVERB_SHOW, nullptr, this->get_client_site(), -1, this->get_window(), &rect);
|
||||
this->resize(rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
void html_frame::set_browser_feature(const std::string& feature, DWORD value)
|
||||
{
|
||||
const auto registry_path = R"(SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\)" + feature;
|
||||
|
||||
HKEY key = nullptr;
|
||||
if (RegOpenKeyExA(
|
||||
HKEY_CURRENT_USER, registry_path.data(), 0,
|
||||
KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
const utils::nt::module self;
|
||||
const auto name = self.get_name();
|
||||
RegSetValueExA(key, name.data(), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
|
||||
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
void html_frame::resize(const DWORD width, const DWORD height) const
|
||||
{
|
||||
auto web_browser = this->get_web_browser();
|
||||
if (web_browser)
|
||||
{
|
||||
web_browser->put_Left(0);
|
||||
web_browser->put_Top(0);
|
||||
web_browser->put_Width(width);
|
||||
web_browser->put_Height(height);
|
||||
}
|
||||
}
|
||||
|
||||
bool html_frame::load_url(const std::string& url) const
|
||||
{
|
||||
auto web_browser = this->get_web_browser();
|
||||
if (!web_browser) return false;
|
||||
|
||||
std::wstring wide_url(url.begin(), url.end());
|
||||
|
||||
VARIANT my_url;
|
||||
VariantInit(&my_url);
|
||||
my_url.vt = VT_BSTR;
|
||||
my_url.bstrVal = SysAllocString(wide_url.data());
|
||||
|
||||
const auto _ = gsl::finally([&my_url]() { VariantClear(&my_url); });
|
||||
if (!my_url.bstrVal) return false;
|
||||
|
||||
return SUCCEEDED(web_browser->Navigate2(&my_url, nullptr, nullptr, nullptr, nullptr));
|
||||
}
|
||||
|
||||
bool html_frame::load_html(const std::string& html) const
|
||||
{
|
||||
if (!this->load_url("about:blank")) return false;
|
||||
|
||||
const auto document = this->get_document();
|
||||
if (!document) return false;
|
||||
|
||||
SAFEARRAYBOUND safe_array_bound = {1, 0};
|
||||
auto safe_array = SafeArrayCreate(VT_VARIANT, 1, &safe_array_bound);
|
||||
if (!safe_array) return false;
|
||||
|
||||
const auto _ = gsl::finally([safe_array]() { SafeArrayDestroy(safe_array); });
|
||||
|
||||
VARIANT* variant = nullptr;
|
||||
if (SafeArrayAccessData(safe_array, reinterpret_cast<void**>(&variant)) || !variant) return false;
|
||||
|
||||
std::wstring wide_html(html.begin(), html.end());
|
||||
|
||||
variant->vt = VT_BSTR;
|
||||
variant->bstrVal = SysAllocString(wide_html.data());
|
||||
if (!variant->bstrVal) return false;
|
||||
|
||||
document->write(safe_array);
|
||||
document->close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int html_frame::get_callback_id(const std::string& name)
|
||||
{
|
||||
for (auto i = 0u; i < this->callbacks_.size(); ++i)
|
||||
{
|
||||
if (this->callbacks_[i].first == name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void html_frame::invoke_callback(const int id, callback_params* params)
|
||||
{
|
||||
if (id >= 0 && static_cast<unsigned int>(id) < this->callbacks_.size())
|
||||
{
|
||||
this->callbacks_[id].second(params);
|
||||
}
|
||||
}
|
||||
|
||||
void html_frame::register_callback(const std::string& name, const std::function<void(callback_params*)>& callback)
|
||||
{
|
||||
this->callbacks_.emplace_back(name, callback);
|
||||
}
|
||||
|
@ -1,67 +1,67 @@
|
||||
#pragma once
|
||||
#include "ole_in_place_frame.hpp"
|
||||
#include "ole_in_place_site.hpp"
|
||||
#include "doc_host_ui_handler.hpp"
|
||||
#include "ole_client_site.hpp"
|
||||
#include "html_dispatch.hpp"
|
||||
#include "html_argument.hpp"
|
||||
|
||||
class html_frame
|
||||
{
|
||||
public:
|
||||
class callback_params final
|
||||
{
|
||||
public:
|
||||
callback_params(DISPPARAMS* params, VARIANT* res);
|
||||
|
||||
std::vector<html_argument> arguments;
|
||||
html_argument result;
|
||||
};
|
||||
|
||||
html_frame();
|
||||
virtual ~html_frame();
|
||||
|
||||
void initialize(HWND window);
|
||||
|
||||
void resize(DWORD width, DWORD height) const;
|
||||
bool load_url(const std::string& url) const;
|
||||
bool load_html(const std::string& html) const;
|
||||
|
||||
HWND get_window() const;
|
||||
|
||||
std::shared_ptr<IOleObject> get_browser_object() const;
|
||||
std::shared_ptr<IWebBrowser2> get_web_browser() const;
|
||||
std::shared_ptr<IDispatch> get_dispatch() const;
|
||||
std::shared_ptr<IHTMLDocument2> get_document() const;
|
||||
|
||||
ole_in_place_frame* get_in_place_frame();
|
||||
ole_in_place_site* get_in_place_site();
|
||||
doc_host_ui_handler* get_ui_handler();
|
||||
ole_client_site* get_client_site();
|
||||
html_dispatch* get_html_dispatch();
|
||||
|
||||
int get_callback_id(const std::string& name);
|
||||
void invoke_callback(int id, callback_params* params);
|
||||
|
||||
void register_callback(const std::string& name, const std::function<void(callback_params*)>& callback);
|
||||
|
||||
private:
|
||||
HWND window_ = nullptr;
|
||||
std::shared_ptr<IOleObject> browser_object_;
|
||||
|
||||
ole_in_place_frame in_place_frame_;
|
||||
ole_in_place_site in_place_site_;
|
||||
doc_host_ui_handler ui_handler_;
|
||||
ole_client_site client_site_;
|
||||
html_dispatch html_dispatch_;
|
||||
|
||||
std::vector<std::pair<std::string, std::function<void(callback_params*)>>> callbacks_;
|
||||
|
||||
void create_browser();
|
||||
void initialize_browser();
|
||||
|
||||
static void set_browser_feature(const std::string& feature, DWORD value);
|
||||
static void object_deleter(IUnknown* object);
|
||||
|
||||
static std::atomic<int> frame_count_;
|
||||
};
|
||||
#pragma once
|
||||
#include "ole_in_place_frame.hpp"
|
||||
#include "ole_in_place_site.hpp"
|
||||
#include "doc_host_ui_handler.hpp"
|
||||
#include "ole_client_site.hpp"
|
||||
#include "html_dispatch.hpp"
|
||||
#include "html_argument.hpp"
|
||||
|
||||
class html_frame
|
||||
{
|
||||
public:
|
||||
class callback_params final
|
||||
{
|
||||
public:
|
||||
callback_params(DISPPARAMS* params, VARIANT* res);
|
||||
|
||||
std::vector<html_argument> arguments;
|
||||
html_argument result;
|
||||
};
|
||||
|
||||
html_frame();
|
||||
virtual ~html_frame();
|
||||
|
||||
void initialize(HWND window);
|
||||
|
||||
void resize(DWORD width, DWORD height) const;
|
||||
bool load_url(const std::string& url) const;
|
||||
bool load_html(const std::string& html) const;
|
||||
|
||||
HWND get_window() const;
|
||||
|
||||
std::shared_ptr<IOleObject> get_browser_object() const;
|
||||
std::shared_ptr<IWebBrowser2> get_web_browser() const;
|
||||
std::shared_ptr<IDispatch> get_dispatch() const;
|
||||
std::shared_ptr<IHTMLDocument2> get_document() const;
|
||||
|
||||
ole_in_place_frame* get_in_place_frame();
|
||||
ole_in_place_site* get_in_place_site();
|
||||
doc_host_ui_handler* get_ui_handler();
|
||||
ole_client_site* get_client_site();
|
||||
html_dispatch* get_html_dispatch();
|
||||
|
||||
int get_callback_id(const std::string& name);
|
||||
void invoke_callback(int id, callback_params* params);
|
||||
|
||||
void register_callback(const std::string& name, const std::function<void(callback_params*)>& callback);
|
||||
|
||||
private:
|
||||
HWND window_ = nullptr;
|
||||
std::shared_ptr<IOleObject> browser_object_;
|
||||
|
||||
ole_in_place_frame in_place_frame_;
|
||||
ole_in_place_site in_place_site_;
|
||||
doc_host_ui_handler ui_handler_;
|
||||
ole_client_site client_site_;
|
||||
html_dispatch html_dispatch_;
|
||||
|
||||
std::vector<std::pair<std::string, std::function<void(callback_params*)>>> callbacks_;
|
||||
|
||||
void create_browser();
|
||||
void initialize_browser();
|
||||
|
||||
static void set_browser_feature(const std::string& feature, DWORD value);
|
||||
static void object_deleter(IUnknown* object);
|
||||
|
||||
static std::atomic<int> frame_count_;
|
||||
};
|
||||
|
@ -1,29 +1,29 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_window.hpp"
|
||||
|
||||
window* html_window::get_window()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
html_frame* html_window::get_html_frame()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
LRESULT html_window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
||||
{
|
||||
if (message == WM_SIZE)
|
||||
{
|
||||
this->resize(LOWORD(l_param), HIWORD(l_param));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (message == WM_CREATE)
|
||||
{
|
||||
this->initialize(*this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return window::processor(message, w_param, l_param);
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "html_window.hpp"
|
||||
|
||||
window* html_window::get_window()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
html_frame* html_window::get_html_frame()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
LRESULT html_window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
||||
{
|
||||
if (message == WM_SIZE)
|
||||
{
|
||||
this->resize(LOWORD(l_param), HIWORD(l_param));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (message == WM_CREATE)
|
||||
{
|
||||
this->initialize(*this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return window::processor(message, w_param, l_param);
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
#pragma once
|
||||
#include "../window.hpp"
|
||||
#include "html_frame.hpp"
|
||||
|
||||
class html_window final : public window, public html_frame
|
||||
{
|
||||
public:
|
||||
~html_window() = default;
|
||||
|
||||
window* get_window();
|
||||
html_frame* get_html_frame();
|
||||
|
||||
private:
|
||||
LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param) override;
|
||||
};
|
||||
#pragma once
|
||||
#include "../window.hpp"
|
||||
#include "html_frame.hpp"
|
||||
|
||||
class html_window final : public window, public html_frame
|
||||
{
|
||||
public:
|
||||
~html_window() = default;
|
||||
|
||||
window* get_window();
|
||||
html_frame* get_html_frame();
|
||||
|
||||
private:
|
||||
LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param) override;
|
||||
};
|
||||
|
@ -1,77 +1,77 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
|
||||
ole_client_site::ole_client_site(html_frame* frame): frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::QueryInterface(REFIID riid, LPVOID* ppvObject)
|
||||
{
|
||||
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) ||
|
||||
!memcmp(&riid, &IID_IOleClientSite, sizeof(GUID)))
|
||||
{
|
||||
*ppvObject = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!memcmp(&riid, &IID_IOleInPlaceSite, sizeof(GUID)))
|
||||
{
|
||||
auto in_place_site = this->frame_->get_in_place_site();
|
||||
in_place_site->AddRef();
|
||||
*ppvObject = in_place_site;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!memcmp(&riid, &IID_IDocHostUIHandler, sizeof(GUID)))
|
||||
{
|
||||
auto ui_handler = this->frame_->get_ui_handler();
|
||||
ui_handler->AddRef();
|
||||
*ppvObject = ui_handler;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppvObject = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG ole_client_site::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG ole_client_site::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::SaveObject()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::GetMoniker(DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker** /*ppmk*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::GetContainer(LPOLECONTAINER* ppContainer)
|
||||
{
|
||||
*ppContainer = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::ShowObject()
|
||||
{
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::OnShowWindow(BOOL /*fShow*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::RequestNewObjectLayout()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
|
||||
ole_client_site::ole_client_site(html_frame* frame): frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::QueryInterface(REFIID riid, LPVOID* ppvObject)
|
||||
{
|
||||
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) ||
|
||||
!memcmp(&riid, &IID_IOleClientSite, sizeof(GUID)))
|
||||
{
|
||||
*ppvObject = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!memcmp(&riid, &IID_IOleInPlaceSite, sizeof(GUID)))
|
||||
{
|
||||
auto in_place_site = this->frame_->get_in_place_site();
|
||||
in_place_site->AddRef();
|
||||
*ppvObject = in_place_site;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!memcmp(&riid, &IID_IDocHostUIHandler, sizeof(GUID)))
|
||||
{
|
||||
auto ui_handler = this->frame_->get_ui_handler();
|
||||
ui_handler->AddRef();
|
||||
*ppvObject = ui_handler;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppvObject = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG ole_client_site::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG ole_client_site::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::SaveObject()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::GetMoniker(DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker** /*ppmk*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::GetContainer(LPOLECONTAINER* ppContainer)
|
||||
{
|
||||
*ppContainer = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::ShowObject()
|
||||
{
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::OnShowWindow(BOOL /*fShow*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::RequestNewObjectLayout()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class ole_client_site final : public IOleClientSite
|
||||
{
|
||||
public:
|
||||
ole_client_site(html_frame* frame);
|
||||
virtual ~ole_client_site() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public:
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObject) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE SaveObject() override;
|
||||
HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk) override;
|
||||
HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER FAR* ppContainer) override;
|
||||
HRESULT STDMETHODCALLTYPE ShowObject() override;
|
||||
HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL fShow) override;
|
||||
HRESULT STDMETHODCALLTYPE RequestNewObjectLayout() override;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class ole_client_site final : public IOleClientSite
|
||||
{
|
||||
public:
|
||||
ole_client_site(html_frame* frame);
|
||||
virtual ~ole_client_site() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public:
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObject) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE SaveObject() override;
|
||||
HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk) override;
|
||||
HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER FAR* ppContainer) override;
|
||||
HRESULT STDMETHODCALLTYPE ShowObject() override;
|
||||
HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL fShow) override;
|
||||
HRESULT STDMETHODCALLTYPE RequestNewObjectLayout() override;
|
||||
};
|
||||
|
@ -1,82 +1,82 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
|
||||
ole_in_place_frame::ole_in_place_frame(html_frame* frame): frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::QueryInterface(REFIID /*riid*/, LPVOID* /*ppvObj*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_frame::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_frame::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::GetWindow(HWND* lphwnd)
|
||||
{
|
||||
*lphwnd = this->frame_->get_window();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::ContextSensitiveHelp(BOOL /*fEnterMode*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::GetBorder(LPRECT /*lprectBorder*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::RequestBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetActiveObject(IOleInPlaceActiveObject* /*pActiveObject*/, LPCOLESTR /*pszObjName*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetMenu(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::RemoveMenus(HMENU /*hmenuShared*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetStatusText(LPCOLESTR /*pszStatusText*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::EnableModeless(BOOL /*fEnable*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::TranslateAcceleratorA(LPMSG /*lpmsg*/, WORD /*wID*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
|
||||
ole_in_place_frame::ole_in_place_frame(html_frame* frame): frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::QueryInterface(REFIID /*riid*/, LPVOID* /*ppvObj*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_frame::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_frame::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::GetWindow(HWND* lphwnd)
|
||||
{
|
||||
*lphwnd = this->frame_->get_window();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::ContextSensitiveHelp(BOOL /*fEnterMode*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::GetBorder(LPRECT /*lprectBorder*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::RequestBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetActiveObject(IOleInPlaceActiveObject* /*pActiveObject*/, LPCOLESTR /*pszObjName*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetMenu(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::RemoveMenus(HMENU /*hmenuShared*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetStatusText(LPCOLESTR /*pszStatusText*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::EnableModeless(BOOL /*fEnable*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::TranslateAcceleratorA(LPMSG /*lpmsg*/, WORD /*wID*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -1,30 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class ole_in_place_frame final : public IOleInPlaceFrame
|
||||
{
|
||||
public:
|
||||
ole_in_place_frame(html_frame* frame);
|
||||
virtual ~ole_in_place_frame() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IOleInPlaceFrame interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override;
|
||||
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
|
||||
HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder) override;
|
||||
HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) override;
|
||||
HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS pborderwidths) override;
|
||||
HRESULT STDMETHODCALLTYPE SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR pszObjName) override;
|
||||
HRESULT STDMETHODCALLTYPE InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override;
|
||||
HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) override;
|
||||
HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenuShared) override;
|
||||
HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR pszStatusText) override;
|
||||
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override;
|
||||
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD wID) override;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class ole_in_place_frame final : public IOleInPlaceFrame
|
||||
{
|
||||
public:
|
||||
ole_in_place_frame(html_frame* frame);
|
||||
virtual ~ole_in_place_frame() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IOleInPlaceFrame interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override;
|
||||
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
|
||||
HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder) override;
|
||||
HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) override;
|
||||
HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS pborderwidths) override;
|
||||
HRESULT STDMETHODCALLTYPE SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR pszObjName) override;
|
||||
HRESULT STDMETHODCALLTYPE InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override;
|
||||
HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) override;
|
||||
HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenuShared) override;
|
||||
HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR pszStatusText) override;
|
||||
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override;
|
||||
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD wID) override;
|
||||
};
|
||||
|
@ -1,105 +1,105 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
|
||||
ole_in_place_site::ole_in_place_site(html_frame* frame) : frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
|
||||
{
|
||||
auto client_site = this->frame_->get_client_site();
|
||||
if (client_site)
|
||||
{
|
||||
return client_site->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_site::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_site::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::GetWindow(HWND* lphwnd)
|
||||
{
|
||||
*lphwnd = this->frame_->get_window();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::ContextSensitiveHelp(BOOL /*fEnterMode*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::CanInPlaceActivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnInPlaceActivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnUIActivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::GetWindowContext(LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc,
|
||||
LPRECT /*lprcPosRect*/, LPRECT /*lprcClipRect*/,
|
||||
LPOLEINPLACEFRAMEINFO lpFrameInfo)
|
||||
{
|
||||
*lplpFrame = this->frame_->get_in_place_frame();
|
||||
*lplpDoc = nullptr;
|
||||
|
||||
lpFrameInfo->fMDIApp = FALSE;
|
||||
lpFrameInfo->hwndFrame = this->frame_->get_window();
|
||||
lpFrameInfo->haccel = nullptr;
|
||||
lpFrameInfo->cAccelEntries = 0;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::Scroll(SIZE /*scrollExtent*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnUIDeactivate(BOOL /*fUndoable*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnInPlaceDeactivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::DiscardUndoState()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::DeactivateAndUndo()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnPosRectChange(LPCRECT lprcPosRect)
|
||||
{
|
||||
IOleInPlaceObject* in_place = nullptr;
|
||||
if (!this->frame_->get_browser_object()->QueryInterface(IID_IOleInPlaceObject, reinterpret_cast<void**>(&in_place)))
|
||||
{
|
||||
in_place->SetObjectRects(lprcPosRect, lprcPosRect);
|
||||
in_place->Release();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
|
||||
ole_in_place_site::ole_in_place_site(html_frame* frame) : frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
|
||||
{
|
||||
auto client_site = this->frame_->get_client_site();
|
||||
if (client_site)
|
||||
{
|
||||
return client_site->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_site::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_site::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::GetWindow(HWND* lphwnd)
|
||||
{
|
||||
*lphwnd = this->frame_->get_window();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::ContextSensitiveHelp(BOOL /*fEnterMode*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::CanInPlaceActivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnInPlaceActivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnUIActivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::GetWindowContext(LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc,
|
||||
LPRECT /*lprcPosRect*/, LPRECT /*lprcClipRect*/,
|
||||
LPOLEINPLACEFRAMEINFO lpFrameInfo)
|
||||
{
|
||||
*lplpFrame = this->frame_->get_in_place_frame();
|
||||
*lplpDoc = nullptr;
|
||||
|
||||
lpFrameInfo->fMDIApp = FALSE;
|
||||
lpFrameInfo->hwndFrame = this->frame_->get_window();
|
||||
lpFrameInfo->haccel = nullptr;
|
||||
lpFrameInfo->cAccelEntries = 0;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::Scroll(SIZE /*scrollExtent*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnUIDeactivate(BOOL /*fUndoable*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnInPlaceDeactivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::DiscardUndoState()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::DeactivateAndUndo()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnPosRectChange(LPCRECT lprcPosRect)
|
||||
{
|
||||
IOleInPlaceObject* in_place = nullptr;
|
||||
if (!this->frame_->get_browser_object()->QueryInterface(IID_IOleInPlaceObject, reinterpret_cast<void**>(&in_place)))
|
||||
{
|
||||
in_place->SetObjectRects(lprcPosRect, lprcPosRect);
|
||||
in_place->Release();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -1,32 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class ole_in_place_site final : public IOleInPlaceSite
|
||||
{
|
||||
public:
|
||||
ole_in_place_site(html_frame* frame);
|
||||
virtual ~ole_in_place_site() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IOleInPlaceSite interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override;
|
||||
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
|
||||
HRESULT STDMETHODCALLTYPE CanInPlaceActivate() override;
|
||||
HRESULT STDMETHODCALLTYPE OnInPlaceActivate() override;
|
||||
HRESULT STDMETHODCALLTYPE OnUIActivate() override;
|
||||
HRESULT STDMETHODCALLTYPE GetWindowContext(LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc,
|
||||
LPRECT lprcPosRect, LPRECT lprcClipRect,
|
||||
LPOLEINPLACEFRAMEINFO lpFrameInfo) override;
|
||||
HRESULT STDMETHODCALLTYPE Scroll(SIZE scrollExtent) override;
|
||||
HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL fUndoable) override;
|
||||
HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate() override;
|
||||
HRESULT STDMETHODCALLTYPE DiscardUndoState() override;
|
||||
HRESULT STDMETHODCALLTYPE DeactivateAndUndo() override;
|
||||
HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect) override;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class ole_in_place_site final : public IOleInPlaceSite
|
||||
{
|
||||
public:
|
||||
ole_in_place_site(html_frame* frame);
|
||||
virtual ~ole_in_place_site() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IOleInPlaceSite interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override;
|
||||
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
|
||||
HRESULT STDMETHODCALLTYPE CanInPlaceActivate() override;
|
||||
HRESULT STDMETHODCALLTYPE OnInPlaceActivate() override;
|
||||
HRESULT STDMETHODCALLTYPE OnUIActivate() override;
|
||||
HRESULT STDMETHODCALLTYPE GetWindowContext(LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc,
|
||||
LPRECT lprcPosRect, LPRECT lprcClipRect,
|
||||
LPOLEINPLACEFRAMEINFO lpFrameInfo) override;
|
||||
HRESULT STDMETHODCALLTYPE Scroll(SIZE scrollExtent) override;
|
||||
HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL fUndoable) override;
|
||||
HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate() override;
|
||||
HRESULT STDMETHODCALLTYPE DiscardUndoState() override;
|
||||
HRESULT STDMETHODCALLTYPE DeactivateAndUndo() override;
|
||||
HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect) override;
|
||||
};
|
||||
|
@ -1,88 +1,88 @@
|
||||
#include <std_include.hpp>
|
||||
#include "launcher.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
|
||||
launcher::launcher()
|
||||
{
|
||||
this->create_settings_menu();
|
||||
this->create_main_menu();
|
||||
}
|
||||
|
||||
void launcher::create_main_menu()
|
||||
{
|
||||
this->main_window_.register_callback("selectMode", [this](html_frame::callback_params* params)
|
||||
{
|
||||
if (params->arguments.empty()) return;
|
||||
|
||||
const auto param = params->arguments[0];
|
||||
if (!param.is_number()) return;
|
||||
|
||||
const auto number = param.get_number();
|
||||
if (number == singleplayer || number == multiplayer)
|
||||
{
|
||||
this->select_mode(static_cast<mode>(number));
|
||||
}
|
||||
});
|
||||
|
||||
this->main_window_.register_callback("showSettings", [this](html_frame::callback_params*)
|
||||
{
|
||||
this->settings_window_.show();
|
||||
});
|
||||
|
||||
this->main_window_.set_callback(
|
||||
[](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT
|
||||
{
|
||||
if (message == WM_CLOSE)
|
||||
{
|
||||
window::close_all();
|
||||
}
|
||||
|
||||
return DefWindowProcA(*window, message, w_param, l_param);
|
||||
});
|
||||
|
||||
this->main_window_.create("Open-IW5", 615, 300);
|
||||
this->main_window_.load_html(load_content(MENU_MAIN));
|
||||
this->main_window_.show();
|
||||
}
|
||||
|
||||
void launcher::create_settings_menu()
|
||||
{
|
||||
this->settings_window_.set_callback(
|
||||
[](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT
|
||||
{
|
||||
if (message == WM_CLOSE)
|
||||
{
|
||||
window->hide();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return DefWindowProcA(*window, message, w_param, l_param);
|
||||
});
|
||||
|
||||
this->settings_window_.create("Open-IW5 Settings", 400, 200, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU);
|
||||
this->settings_window_.load_html(load_content(MENU_SETTINGS));
|
||||
}
|
||||
|
||||
launcher::mode launcher::run() const
|
||||
{
|
||||
window::run();
|
||||
return this->mode_;
|
||||
}
|
||||
|
||||
void launcher::select_mode(const mode mode)
|
||||
{
|
||||
this->mode_ = mode;
|
||||
this->settings_window_.close();
|
||||
this->main_window_.close();
|
||||
}
|
||||
|
||||
std::string launcher::load_content(const int res)
|
||||
{
|
||||
const auto resource = FindResource(utils::nt::module(), MAKEINTRESOURCE(res), RT_RCDATA);
|
||||
if (!resource) return {};
|
||||
|
||||
const auto handle = LoadResource(nullptr, resource);
|
||||
if (!handle) return {};
|
||||
|
||||
return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, resource));
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "launcher.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
|
||||
launcher::launcher()
|
||||
{
|
||||
this->create_settings_menu();
|
||||
this->create_main_menu();
|
||||
}
|
||||
|
||||
void launcher::create_main_menu()
|
||||
{
|
||||
this->main_window_.register_callback("selectMode", [this](html_frame::callback_params* params)
|
||||
{
|
||||
if (params->arguments.empty()) return;
|
||||
|
||||
const auto param = params->arguments[0];
|
||||
if (!param.is_number()) return;
|
||||
|
||||
const auto number = param.get_number();
|
||||
if (number == singleplayer || number == multiplayer)
|
||||
{
|
||||
this->select_mode(static_cast<mode>(number));
|
||||
}
|
||||
});
|
||||
|
||||
this->main_window_.register_callback("showSettings", [this](html_frame::callback_params*)
|
||||
{
|
||||
this->settings_window_.show();
|
||||
});
|
||||
|
||||
this->main_window_.set_callback(
|
||||
[](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT
|
||||
{
|
||||
if (message == WM_CLOSE)
|
||||
{
|
||||
window::close_all();
|
||||
}
|
||||
|
||||
return DefWindowProcA(*window, message, w_param, l_param);
|
||||
});
|
||||
|
||||
this->main_window_.create("Open-IW5", 615, 300);
|
||||
this->main_window_.load_html(load_content(MENU_MAIN));
|
||||
this->main_window_.show();
|
||||
}
|
||||
|
||||
void launcher::create_settings_menu()
|
||||
{
|
||||
this->settings_window_.set_callback(
|
||||
[](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT
|
||||
{
|
||||
if (message == WM_CLOSE)
|
||||
{
|
||||
window->hide();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return DefWindowProcA(*window, message, w_param, l_param);
|
||||
});
|
||||
|
||||
this->settings_window_.create("Open-IW5 Settings", 400, 200, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU);
|
||||
this->settings_window_.load_html(load_content(MENU_SETTINGS));
|
||||
}
|
||||
|
||||
launcher::mode launcher::run() const
|
||||
{
|
||||
window::run();
|
||||
return this->mode_;
|
||||
}
|
||||
|
||||
void launcher::select_mode(const mode mode)
|
||||
{
|
||||
this->mode_ = mode;
|
||||
this->settings_window_.close();
|
||||
this->main_window_.close();
|
||||
}
|
||||
|
||||
std::string launcher::load_content(const int res)
|
||||
{
|
||||
const auto resource = FindResource(utils::nt::module(), MAKEINTRESOURCE(res), RT_RCDATA);
|
||||
if (!resource) return {};
|
||||
|
||||
const auto handle = LoadResource(nullptr, resource);
|
||||
if (!handle) return {};
|
||||
|
||||
return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, resource));
|
||||
}
|
||||
|
@ -1,31 +1,31 @@
|
||||
#pragma once
|
||||
#include "html/html_window.hpp"
|
||||
|
||||
class launcher final
|
||||
{
|
||||
public:
|
||||
enum mode
|
||||
{
|
||||
none,
|
||||
singleplayer,
|
||||
multiplayer,
|
||||
server,
|
||||
};
|
||||
|
||||
launcher();
|
||||
|
||||
mode run() const;
|
||||
|
||||
private:
|
||||
mode mode_ = none;
|
||||
|
||||
html_window main_window_;
|
||||
html_window settings_window_;
|
||||
|
||||
void select_mode(mode mode);
|
||||
|
||||
void create_main_menu();
|
||||
void create_settings_menu();
|
||||
|
||||
static std::string load_content(int res);
|
||||
};
|
||||
#pragma once
|
||||
#include "html/html_window.hpp"
|
||||
|
||||
class launcher final
|
||||
{
|
||||
public:
|
||||
enum mode
|
||||
{
|
||||
none,
|
||||
singleplayer,
|
||||
multiplayer,
|
||||
server,
|
||||
};
|
||||
|
||||
launcher();
|
||||
|
||||
mode run() const;
|
||||
|
||||
private:
|
||||
mode mode_ = none;
|
||||
|
||||
html_window main_window_;
|
||||
html_window settings_window_;
|
||||
|
||||
void select_mode(mode mode);
|
||||
|
||||
void create_main_menu();
|
||||
void create_settings_menu();
|
||||
|
||||
static std::string load_content(int res);
|
||||
};
|
||||
|
@ -1,180 +1,180 @@
|
||||
#include <std_include.hpp>
|
||||
#include "window.hpp"
|
||||
|
||||
std::mutex window::mutex_;
|
||||
std::vector<window*> window::windows_;
|
||||
|
||||
window::window()
|
||||
{
|
||||
ZeroMemory(&this->wc_, sizeof(this->wc_));
|
||||
|
||||
this->classname_ = "window-base-" + std::to_string(time(nullptr));
|
||||
|
||||
this->wc_.cbSize = sizeof(this->wc_);
|
||||
this->wc_.style = CS_HREDRAW | CS_VREDRAW;
|
||||
this->wc_.lpfnWndProc = static_processor;
|
||||
this->wc_.hInstance = GetModuleHandle(nullptr);
|
||||
this->wc_.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
this->wc_.hIcon = LoadIcon(this->wc_.hInstance, MAKEINTRESOURCE(102));
|
||||
this->wc_.hIconSm = this->wc_.hIcon;
|
||||
this->wc_.hbrBackground = HBRUSH(COLOR_WINDOW);
|
||||
this->wc_.lpszClassName = this->classname_.data();
|
||||
RegisterClassEx(&this->wc_);
|
||||
}
|
||||
|
||||
void window::create(const std::string& title, const int width, const int height, const long flags)
|
||||
{
|
||||
{
|
||||
std::lock_guard _(mutex_);
|
||||
windows_.push_back(this);
|
||||
}
|
||||
|
||||
const auto x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
|
||||
const auto y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
|
||||
|
||||
this->handle_ = CreateWindowExA(NULL, this->wc_.lpszClassName, title.data(), flags, x, y, width, height, nullptr,
|
||||
nullptr, this->wc_.hInstance, this);
|
||||
}
|
||||
|
||||
window::~window()
|
||||
{
|
||||
this->close();
|
||||
UnregisterClass(this->wc_.lpszClassName, this->wc_.hInstance);
|
||||
}
|
||||
|
||||
void window::close()
|
||||
{
|
||||
if (!this->handle_) return;
|
||||
|
||||
SendMessageA(this->handle_, WM_KILL_WINDOW, NULL, NULL);
|
||||
this->handle_ = nullptr;
|
||||
}
|
||||
|
||||
void window::run()
|
||||
{
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, nullptr, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void window::close_all()
|
||||
{
|
||||
std::unique_lock lock(mutex_);
|
||||
auto window_list = windows_;
|
||||
lock.unlock();
|
||||
|
||||
const auto current_thread_id = GetCurrentThreadId();
|
||||
for (auto& window : window_list)
|
||||
{
|
||||
const auto thread_id = GetWindowThreadProcessId(*window, nullptr);
|
||||
|
||||
if (thread_id == current_thread_id)
|
||||
{
|
||||
window->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void window::remove_window(const window* window)
|
||||
{
|
||||
std::lock_guard _(mutex_);
|
||||
|
||||
for (auto i = windows_.begin(); i != windows_.end(); ++i)
|
||||
{
|
||||
if (*i == window)
|
||||
{
|
||||
windows_.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int window::get_window_count()
|
||||
{
|
||||
std::lock_guard _(mutex_);
|
||||
|
||||
auto count = 0;
|
||||
const auto current_thread_id = GetCurrentThreadId();
|
||||
|
||||
for (const auto& window : windows_)
|
||||
{
|
||||
const auto thread_id = GetWindowThreadProcessId(*window, nullptr);
|
||||
|
||||
if (thread_id == current_thread_id)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void window::show() const
|
||||
{
|
||||
ShowWindow(this->handle_, SW_SHOW);
|
||||
UpdateWindow(this->handle_);
|
||||
}
|
||||
|
||||
void window::hide() const
|
||||
{
|
||||
ShowWindow(this->handle_, SW_HIDE);
|
||||
UpdateWindow(this->handle_);
|
||||
}
|
||||
|
||||
void window::set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback)
|
||||
{
|
||||
this->callback_ = callback;
|
||||
}
|
||||
|
||||
LRESULT window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
||||
{
|
||||
if (message == WM_DESTROY)
|
||||
{
|
||||
remove_window(this);
|
||||
|
||||
if (get_window_count() == 0)
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (message == WM_KILL_WINDOW)
|
||||
{
|
||||
DestroyWindow(*this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->callback_)
|
||||
{
|
||||
return this->callback_(this, message, w_param, l_param);
|
||||
}
|
||||
|
||||
return DefWindowProc(*this, message, w_param, l_param);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK window::static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param)
|
||||
{
|
||||
if (message == WM_CREATE)
|
||||
{
|
||||
auto data = reinterpret_cast<LPCREATESTRUCT>(l_param);
|
||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, LONG_PTR(data->lpCreateParams));
|
||||
|
||||
reinterpret_cast<window*>(data->lpCreateParams)->handle_ = hwnd;
|
||||
}
|
||||
|
||||
const auto self = reinterpret_cast<window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (self) return self->processor(message, w_param, l_param);
|
||||
|
||||
return DefWindowProc(hwnd, message, w_param, l_param);
|
||||
}
|
||||
|
||||
|
||||
window::operator HWND() const
|
||||
{
|
||||
return this->handle_;
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "window.hpp"
|
||||
|
||||
std::mutex window::mutex_;
|
||||
std::vector<window*> window::windows_;
|
||||
|
||||
window::window()
|
||||
{
|
||||
ZeroMemory(&this->wc_, sizeof(this->wc_));
|
||||
|
||||
this->classname_ = "window-base-" + std::to_string(time(nullptr));
|
||||
|
||||
this->wc_.cbSize = sizeof(this->wc_);
|
||||
this->wc_.style = CS_HREDRAW | CS_VREDRAW;
|
||||
this->wc_.lpfnWndProc = static_processor;
|
||||
this->wc_.hInstance = GetModuleHandle(nullptr);
|
||||
this->wc_.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
this->wc_.hIcon = LoadIcon(this->wc_.hInstance, MAKEINTRESOURCE(102));
|
||||
this->wc_.hIconSm = this->wc_.hIcon;
|
||||
this->wc_.hbrBackground = HBRUSH(COLOR_WINDOW);
|
||||
this->wc_.lpszClassName = this->classname_.data();
|
||||
RegisterClassEx(&this->wc_);
|
||||
}
|
||||
|
||||
void window::create(const std::string& title, const int width, const int height, const long flags)
|
||||
{
|
||||
{
|
||||
std::lock_guard _(mutex_);
|
||||
windows_.push_back(this);
|
||||
}
|
||||
|
||||
const auto x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
|
||||
const auto y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
|
||||
|
||||
this->handle_ = CreateWindowExA(NULL, this->wc_.lpszClassName, title.data(), flags, x, y, width, height, nullptr,
|
||||
nullptr, this->wc_.hInstance, this);
|
||||
}
|
||||
|
||||
window::~window()
|
||||
{
|
||||
this->close();
|
||||
UnregisterClass(this->wc_.lpszClassName, this->wc_.hInstance);
|
||||
}
|
||||
|
||||
void window::close()
|
||||
{
|
||||
if (!this->handle_) return;
|
||||
|
||||
SendMessageA(this->handle_, WM_KILL_WINDOW, NULL, NULL);
|
||||
this->handle_ = nullptr;
|
||||
}
|
||||
|
||||
void window::run()
|
||||
{
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, nullptr, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void window::close_all()
|
||||
{
|
||||
std::unique_lock lock(mutex_);
|
||||
auto window_list = windows_;
|
||||
lock.unlock();
|
||||
|
||||
const auto current_thread_id = GetCurrentThreadId();
|
||||
for (auto& window : window_list)
|
||||
{
|
||||
const auto thread_id = GetWindowThreadProcessId(*window, nullptr);
|
||||
|
||||
if (thread_id == current_thread_id)
|
||||
{
|
||||
window->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void window::remove_window(const window* window)
|
||||
{
|
||||
std::lock_guard _(mutex_);
|
||||
|
||||
for (auto i = windows_.begin(); i != windows_.end(); ++i)
|
||||
{
|
||||
if (*i == window)
|
||||
{
|
||||
windows_.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int window::get_window_count()
|
||||
{
|
||||
std::lock_guard _(mutex_);
|
||||
|
||||
auto count = 0;
|
||||
const auto current_thread_id = GetCurrentThreadId();
|
||||
|
||||
for (const auto& window : windows_)
|
||||
{
|
||||
const auto thread_id = GetWindowThreadProcessId(*window, nullptr);
|
||||
|
||||
if (thread_id == current_thread_id)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void window::show() const
|
||||
{
|
||||
ShowWindow(this->handle_, SW_SHOW);
|
||||
UpdateWindow(this->handle_);
|
||||
}
|
||||
|
||||
void window::hide() const
|
||||
{
|
||||
ShowWindow(this->handle_, SW_HIDE);
|
||||
UpdateWindow(this->handle_);
|
||||
}
|
||||
|
||||
void window::set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback)
|
||||
{
|
||||
this->callback_ = callback;
|
||||
}
|
||||
|
||||
LRESULT window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
||||
{
|
||||
if (message == WM_DESTROY)
|
||||
{
|
||||
remove_window(this);
|
||||
|
||||
if (get_window_count() == 0)
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (message == WM_KILL_WINDOW)
|
||||
{
|
||||
DestroyWindow(*this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->callback_)
|
||||
{
|
||||
return this->callback_(this, message, w_param, l_param);
|
||||
}
|
||||
|
||||
return DefWindowProc(*this, message, w_param, l_param);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK window::static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param)
|
||||
{
|
||||
if (message == WM_CREATE)
|
||||
{
|
||||
auto data = reinterpret_cast<LPCREATESTRUCT>(l_param);
|
||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, LONG_PTR(data->lpCreateParams));
|
||||
|
||||
reinterpret_cast<window*>(data->lpCreateParams)->handle_ = hwnd;
|
||||
}
|
||||
|
||||
const auto self = reinterpret_cast<window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (self) return self->processor(message, w_param, l_param);
|
||||
|
||||
return DefWindowProc(hwnd, message, w_param, l_param);
|
||||
}
|
||||
|
||||
|
||||
window::operator HWND() const
|
||||
{
|
||||
return this->handle_;
|
||||
}
|
||||
|
@ -1,42 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#define WM_KILL_WINDOW (WM_USER+0)
|
||||
|
||||
class window
|
||||
{
|
||||
public:
|
||||
window();
|
||||
virtual ~window();
|
||||
|
||||
void create(const std::string& title, int width, int height,
|
||||
long flags = (WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX)));
|
||||
|
||||
void close();
|
||||
|
||||
void show() const;
|
||||
void hide() const;
|
||||
|
||||
void set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback);
|
||||
|
||||
operator HWND() const;
|
||||
|
||||
static void run();
|
||||
static void close_all();
|
||||
|
||||
protected:
|
||||
virtual LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param);
|
||||
|
||||
private:
|
||||
WNDCLASSEX wc_{};
|
||||
HWND handle_ = nullptr;
|
||||
std::string classname_;
|
||||
std::function<LRESULT(window*, UINT, WPARAM, LPARAM)> callback_;
|
||||
|
||||
static LRESULT CALLBACK static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param);
|
||||
|
||||
static std::mutex mutex_;
|
||||
static std::vector<window*> windows_;
|
||||
|
||||
static void remove_window(const window* window);
|
||||
static int get_window_count();
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#define WM_KILL_WINDOW (WM_USER+0)
|
||||
|
||||
class window
|
||||
{
|
||||
public:
|
||||
window();
|
||||
virtual ~window();
|
||||
|
||||
void create(const std::string& title, int width, int height,
|
||||
long flags = (WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX)));
|
||||
|
||||
void close();
|
||||
|
||||
void show() const;
|
||||
void hide() const;
|
||||
|
||||
void set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback);
|
||||
|
||||
operator HWND() const;
|
||||
|
||||
static void run();
|
||||
static void close_all();
|
||||
|
||||
protected:
|
||||
virtual LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param);
|
||||
|
||||
private:
|
||||
WNDCLASSEX wc_{};
|
||||
HWND handle_ = nullptr;
|
||||
std::string classname_;
|
||||
std::function<LRESULT(window*, UINT, WPARAM, LPARAM)> callback_;
|
||||
|
||||
static LRESULT CALLBACK static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param);
|
||||
|
||||
static std::mutex mutex_;
|
||||
static std::vector<window*> windows_;
|
||||
|
||||
static void remove_window(const window* window);
|
||||
static int get_window_count();
|
||||
};
|
||||
|
@ -1,121 +1,121 @@
|
||||
#include <std_include.hpp>
|
||||
#include "binary_loader.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
#include "utils/io.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/compression.hpp"
|
||||
|
||||
#define DEDI_HASH "F271C305117B79242E254E9F64BD5AA2993CAC8E57975243EBD44CD576418D20"
|
||||
|
||||
namespace binary_loader
|
||||
{
|
||||
std::string load_resource(const int id)
|
||||
{
|
||||
const auto res = FindResource(::utils::nt::module(), MAKEINTRESOURCE(id), RT_RCDATA);
|
||||
if (!res) return {};
|
||||
|
||||
const auto handle = LoadResource(nullptr, res);
|
||||
if (!handle) return {};
|
||||
|
||||
return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res));
|
||||
}
|
||||
|
||||
std::string load_delta(const launcher::mode mode)
|
||||
{
|
||||
if (mode == launcher::mode::singleplayer)
|
||||
{
|
||||
return load_resource(BINARY_SP);
|
||||
}
|
||||
|
||||
if (mode == launcher::mode::multiplayer)
|
||||
{
|
||||
return load_resource(BINARY_MP);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string load_base(const bool verify = true)
|
||||
{
|
||||
std::string data;
|
||||
if (!utils::io::read_file("iw5mp_server.exe", &data))
|
||||
{
|
||||
throw std::runtime_error("Unable to load iw5mp_server.exe");
|
||||
}
|
||||
|
||||
if (verify && utils::cryptography::sha256::compute(data, true) != DEDI_HASH)
|
||||
{
|
||||
throw std::runtime_error("Your iw5mp_server.exe is incompatible with this client.");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void create_for_file(const std::string& file, const std::string& base)
|
||||
{
|
||||
std::string data;
|
||||
if (!utils::io::read_file(file, &data))
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("Unable to load file %s!", file.data()));
|
||||
}
|
||||
|
||||
const auto new_data = reinterpret_cast<const unsigned char*>(data.data());
|
||||
const auto old_data = reinterpret_cast<const unsigned char*>(base.data());
|
||||
|
||||
std::vector<unsigned char> diff;
|
||||
create_diff(new_data, new_data + data.size(), old_data, old_data + base.size(), diff);
|
||||
|
||||
const unsigned long long size = data.size();
|
||||
|
||||
std::string result(reinterpret_cast<char*>(diff.data()), diff.size());
|
||||
result.append(reinterpret_cast<const char*>(&size), sizeof(size));
|
||||
result = utils::compression::zlib::compress(result);
|
||||
|
||||
utils::io::write_file(file + ".diff", result);
|
||||
}
|
||||
|
||||
void create()
|
||||
{
|
||||
const auto base = load_base(false);
|
||||
|
||||
utils::io::write_file("hash.txt", utils::cryptography::sha256::compute(base, true));
|
||||
|
||||
create_for_file("iw5sp.exe", base);
|
||||
create_for_file("iw5mp.exe", base);
|
||||
}
|
||||
|
||||
std::string build_binary(const std::string& base, const std::string& diff)
|
||||
{
|
||||
const auto* size = reinterpret_cast<const unsigned long long*>(diff.data() + diff.size() - sizeof(unsigned long
|
||||
long));
|
||||
|
||||
std::string binary;
|
||||
binary.resize(size_t(*size));
|
||||
|
||||
const auto new_data = reinterpret_cast<unsigned char*>(binary.data());
|
||||
const auto old_data = reinterpret_cast<const unsigned char*>(base.data());
|
||||
const auto diff_data = reinterpret_cast<const unsigned char*>(diff.data());
|
||||
|
||||
if (patch(new_data, new_data + binary.size(), old_data, old_data + base.size(), diff_data,
|
||||
diff_data + diff.size() - sizeof(*size)) == hpatch_FALSE || binary.empty())
|
||||
{
|
||||
throw std::runtime_error("Unable to create binary from patch!");
|
||||
}
|
||||
|
||||
return binary;
|
||||
}
|
||||
|
||||
std::string load(const launcher::mode mode)
|
||||
{
|
||||
auto base = load_base();
|
||||
if (mode == launcher::mode::server)
|
||||
{
|
||||
return base;
|
||||
}
|
||||
|
||||
auto delta = load_delta(mode);
|
||||
delta = utils::compression::zlib::decompress(delta);
|
||||
return build_binary(base, delta);
|
||||
}
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "binary_loader.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
#include "utils/io.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/compression.hpp"
|
||||
|
||||
#define DEDI_HASH "F271C305117B79242E254E9F64BD5AA2993CAC8E57975243EBD44CD576418D20"
|
||||
|
||||
namespace binary_loader
|
||||
{
|
||||
std::string load_resource(const int id)
|
||||
{
|
||||
const auto res = FindResource(::utils::nt::module(), MAKEINTRESOURCE(id), RT_RCDATA);
|
||||
if (!res) return {};
|
||||
|
||||
const auto handle = LoadResource(nullptr, res);
|
||||
if (!handle) return {};
|
||||
|
||||
return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res));
|
||||
}
|
||||
|
||||
std::string load_delta(const launcher::mode mode)
|
||||
{
|
||||
if (mode == launcher::mode::singleplayer)
|
||||
{
|
||||
return load_resource(BINARY_SP);
|
||||
}
|
||||
|
||||
if (mode == launcher::mode::multiplayer)
|
||||
{
|
||||
return load_resource(BINARY_MP);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string load_base(const bool verify = true)
|
||||
{
|
||||
std::string data;
|
||||
if (!utils::io::read_file("iw5mp_server.exe", &data))
|
||||
{
|
||||
throw std::runtime_error("Unable to load iw5mp_server.exe");
|
||||
}
|
||||
|
||||
if (verify && utils::cryptography::sha256::compute(data, true) != DEDI_HASH)
|
||||
{
|
||||
throw std::runtime_error("Your iw5mp_server.exe is incompatible with this client.");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void create_for_file(const std::string& file, const std::string& base)
|
||||
{
|
||||
std::string data;
|
||||
if (!utils::io::read_file(file, &data))
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("Unable to load file %s!", file.data()));
|
||||
}
|
||||
|
||||
const auto new_data = reinterpret_cast<const unsigned char*>(data.data());
|
||||
const auto old_data = reinterpret_cast<const unsigned char*>(base.data());
|
||||
|
||||
std::vector<unsigned char> diff;
|
||||
create_diff(new_data, new_data + data.size(), old_data, old_data + base.size(), diff);
|
||||
|
||||
const unsigned long long size = data.size();
|
||||
|
||||
std::string result(reinterpret_cast<char*>(diff.data()), diff.size());
|
||||
result.append(reinterpret_cast<const char*>(&size), sizeof(size));
|
||||
result = utils::compression::zlib::compress(result);
|
||||
|
||||
utils::io::write_file(file + ".diff", result);
|
||||
}
|
||||
|
||||
void create()
|
||||
{
|
||||
const auto base = load_base(false);
|
||||
|
||||
utils::io::write_file("hash.txt", utils::cryptography::sha256::compute(base, true));
|
||||
|
||||
create_for_file("iw5sp.exe", base);
|
||||
create_for_file("iw5mp.exe", base);
|
||||
}
|
||||
|
||||
std::string build_binary(const std::string& base, const std::string& diff)
|
||||
{
|
||||
const auto* size = reinterpret_cast<const unsigned long long*>(diff.data() + diff.size() - sizeof(unsigned long
|
||||
long));
|
||||
|
||||
std::string binary;
|
||||
binary.resize(size_t(*size));
|
||||
|
||||
const auto new_data = reinterpret_cast<unsigned char*>(binary.data());
|
||||
const auto old_data = reinterpret_cast<const unsigned char*>(base.data());
|
||||
const auto diff_data = reinterpret_cast<const unsigned char*>(diff.data());
|
||||
|
||||
if (patch(new_data, new_data + binary.size(), old_data, old_data + base.size(), diff_data,
|
||||
diff_data + diff.size() - sizeof(*size)) == hpatch_FALSE || binary.empty())
|
||||
{
|
||||
throw std::runtime_error("Unable to create binary from patch!");
|
||||
}
|
||||
|
||||
return binary;
|
||||
}
|
||||
|
||||
std::string load(const launcher::mode mode)
|
||||
{
|
||||
auto base = load_base();
|
||||
if (mode == launcher::mode::server)
|
||||
{
|
||||
return base;
|
||||
}
|
||||
|
||||
auto delta = load_delta(mode);
|
||||
delta = utils::compression::zlib::decompress(delta);
|
||||
return build_binary(base, delta);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
namespace binary_loader
|
||||
{
|
||||
void create();
|
||||
std::string load(launcher::mode mode);
|
||||
}
|
||||
#pragma once
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
namespace binary_loader
|
||||
{
|
||||
void create();
|
||||
std::string load(launcher::mode mode);
|
||||
}
|
||||
|
@ -1,165 +1,165 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader.hpp"
|
||||
#include "binary_loader.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
loader::loader(const launcher::mode mode) : mode_(mode)
|
||||
{
|
||||
}
|
||||
|
||||
FARPROC loader::load(const utils::nt::module& module) const
|
||||
{
|
||||
const auto buffer = binary_loader::load(this->mode_);
|
||||
if (buffer.empty()) return nullptr;
|
||||
|
||||
utils::nt::module source(HMODULE(buffer.data()));
|
||||
if (!source) return nullptr;
|
||||
|
||||
this->load_sections(module, source);
|
||||
this->load_imports(module, source);
|
||||
|
||||
if (source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
|
||||
{
|
||||
const auto target_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + module
|
||||
.get_optional_header()
|
||||
->
|
||||
DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
const auto source_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + source
|
||||
.get_optional_header()
|
||||
->
|
||||
DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
|
||||
const auto tls_size = source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData;
|
||||
const auto tls_index = *reinterpret_cast<DWORD*>(target_tls->AddressOfIndex);
|
||||
*reinterpret_cast<DWORD*>(source_tls->AddressOfIndex) = tls_index;
|
||||
|
||||
if (tls_size > TLS_PAYLOAD_SIZE)
|
||||
{
|
||||
throw std::runtime_error(utils::string::va(
|
||||
"TLS data is of size 0x%X, but we have only reserved 0x%X bytes!", tls_size, TLS_PAYLOAD_SIZE));
|
||||
}
|
||||
|
||||
DWORD old_protect;
|
||||
VirtualProtect(PVOID(target_tls->StartAddressOfRawData),
|
||||
source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData, PAGE_READWRITE,
|
||||
&old_protect);
|
||||
|
||||
const auto tls_base = *reinterpret_cast<LPVOID*>(__readfsdword(0x2C) + 4 * tls_index);
|
||||
std::memmove(tls_base, PVOID(source_tls->StartAddressOfRawData), tls_size);
|
||||
std::memmove(PVOID(target_tls->StartAddressOfRawData), PVOID(source_tls->StartAddressOfRawData), tls_size);
|
||||
}
|
||||
|
||||
DWORD oldProtect;
|
||||
VirtualProtect(module.get_nt_headers(), 0x1000, PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||
|
||||
module.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] = source
|
||||
.get_optional_header()->DataDirectory[
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
std::memmove(module.get_nt_headers(), source.get_nt_headers(),
|
||||
sizeof(IMAGE_NT_HEADERS) + (source.get_nt_headers()->FileHeader.NumberOfSections * (sizeof(
|
||||
IMAGE_SECTION_HEADER))));
|
||||
|
||||
return FARPROC(module.get_ptr() + source.get_relative_entry_point());
|
||||
}
|
||||
|
||||
void loader::set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver)
|
||||
{
|
||||
this->import_resolver_ = resolver;
|
||||
}
|
||||
|
||||
void loader::load_section(const utils::nt::module& target, const utils::nt::module& source,
|
||||
IMAGE_SECTION_HEADER* section)
|
||||
{
|
||||
void* target_ptr = target.get_ptr() + section->VirtualAddress;
|
||||
const void* source_ptr = source.get_ptr() + section->PointerToRawData;
|
||||
|
||||
if (PBYTE(target_ptr) >= (target.get_ptr() + BINARY_PAYLOAD_SIZE))
|
||||
{
|
||||
throw std::runtime_error("Section exceeds the binary payload size, please increase it!");
|
||||
}
|
||||
|
||||
if (section->SizeOfRawData > 0)
|
||||
{
|
||||
const auto size_of_data = std::min(section->SizeOfRawData, section->Misc.VirtualSize);
|
||||
std::memmove(target_ptr, source_ptr, size_of_data);
|
||||
|
||||
DWORD old_protect;
|
||||
VirtualProtect(target_ptr, size_of_data, PAGE_EXECUTE_READWRITE, &old_protect);
|
||||
}
|
||||
}
|
||||
|
||||
void loader::load_sections(const utils::nt::module& target, const utils::nt::module& source) const
|
||||
{
|
||||
for (auto& section : source.get_section_headers())
|
||||
{
|
||||
this->load_section(target, source, section);
|
||||
}
|
||||
}
|
||||
|
||||
void loader::load_imports(const utils::nt::module& target, const utils::nt::module& source) const
|
||||
{
|
||||
const auto import_directory = &source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
|
||||
auto descriptor = PIMAGE_IMPORT_DESCRIPTOR(target.get_ptr() + import_directory->VirtualAddress);
|
||||
|
||||
while (descriptor->Name)
|
||||
{
|
||||
std::string name = LPSTR(target.get_ptr() + descriptor->Name);
|
||||
|
||||
auto name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->OriginalFirstThunk);
|
||||
auto address_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||
|
||||
if (!descriptor->OriginalFirstThunk)
|
||||
{
|
||||
name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||
}
|
||||
|
||||
while (*name_table_entry)
|
||||
{
|
||||
FARPROC function = nullptr;
|
||||
std::string function_name;
|
||||
|
||||
// is this an ordinal-only import?
|
||||
if (IMAGE_SNAP_BY_ORDINAL(*name_table_entry))
|
||||
{
|
||||
auto module = utils::nt::module::load(name);
|
||||
if (module)
|
||||
{
|
||||
function = GetProcAddress(module, MAKEINTRESOURCEA(IMAGE_ORDINAL(*name_table_entry)));
|
||||
}
|
||||
|
||||
function_name = "#" + std::to_string(IMAGE_ORDINAL(*name_table_entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto import = PIMAGE_IMPORT_BY_NAME(target.get_ptr() + *name_table_entry);
|
||||
function_name = import->Name;
|
||||
|
||||
if (this->import_resolver_) function = this->import_resolver_(name, function_name);
|
||||
if (!function)
|
||||
{
|
||||
auto module = utils::nt::module::load(name);
|
||||
if (module)
|
||||
{
|
||||
function = GetProcAddress(module, function_name.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function)
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("Unable to load import '%s' from module '%s'",
|
||||
function_name.data(), name.data()));
|
||||
}
|
||||
|
||||
*address_table_entry = reinterpret_cast<uintptr_t>(function);
|
||||
|
||||
name_table_entry++;
|
||||
address_table_entry++;
|
||||
}
|
||||
|
||||
descriptor++;
|
||||
}
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "loader.hpp"
|
||||
#include "binary_loader.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
loader::loader(const launcher::mode mode) : mode_(mode)
|
||||
{
|
||||
}
|
||||
|
||||
FARPROC loader::load(const utils::nt::module& module) const
|
||||
{
|
||||
const auto buffer = binary_loader::load(this->mode_);
|
||||
if (buffer.empty()) return nullptr;
|
||||
|
||||
utils::nt::module source(HMODULE(buffer.data()));
|
||||
if (!source) return nullptr;
|
||||
|
||||
this->load_sections(module, source);
|
||||
this->load_imports(module, source);
|
||||
|
||||
if (source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
|
||||
{
|
||||
const auto target_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + module
|
||||
.get_optional_header()
|
||||
->
|
||||
DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
const auto source_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + source
|
||||
.get_optional_header()
|
||||
->
|
||||
DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
|
||||
const auto tls_size = source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData;
|
||||
const auto tls_index = *reinterpret_cast<DWORD*>(target_tls->AddressOfIndex);
|
||||
*reinterpret_cast<DWORD*>(source_tls->AddressOfIndex) = tls_index;
|
||||
|
||||
if (tls_size > TLS_PAYLOAD_SIZE)
|
||||
{
|
||||
throw std::runtime_error(utils::string::va(
|
||||
"TLS data is of size 0x%X, but we have only reserved 0x%X bytes!", tls_size, TLS_PAYLOAD_SIZE));
|
||||
}
|
||||
|
||||
DWORD old_protect;
|
||||
VirtualProtect(PVOID(target_tls->StartAddressOfRawData),
|
||||
source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData, PAGE_READWRITE,
|
||||
&old_protect);
|
||||
|
||||
const auto tls_base = *reinterpret_cast<LPVOID*>(__readfsdword(0x2C) + 4 * tls_index);
|
||||
std::memmove(tls_base, PVOID(source_tls->StartAddressOfRawData), tls_size);
|
||||
std::memmove(PVOID(target_tls->StartAddressOfRawData), PVOID(source_tls->StartAddressOfRawData), tls_size);
|
||||
}
|
||||
|
||||
DWORD oldProtect;
|
||||
VirtualProtect(module.get_nt_headers(), 0x1000, PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||
|
||||
module.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] = source
|
||||
.get_optional_header()->DataDirectory[
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
std::memmove(module.get_nt_headers(), source.get_nt_headers(),
|
||||
sizeof(IMAGE_NT_HEADERS) + (source.get_nt_headers()->FileHeader.NumberOfSections * (sizeof(
|
||||
IMAGE_SECTION_HEADER))));
|
||||
|
||||
return FARPROC(module.get_ptr() + source.get_relative_entry_point());
|
||||
}
|
||||
|
||||
void loader::set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver)
|
||||
{
|
||||
this->import_resolver_ = resolver;
|
||||
}
|
||||
|
||||
void loader::load_section(const utils::nt::module& target, const utils::nt::module& source,
|
||||
IMAGE_SECTION_HEADER* section)
|
||||
{
|
||||
void* target_ptr = target.get_ptr() + section->VirtualAddress;
|
||||
const void* source_ptr = source.get_ptr() + section->PointerToRawData;
|
||||
|
||||
if (PBYTE(target_ptr) >= (target.get_ptr() + BINARY_PAYLOAD_SIZE))
|
||||
{
|
||||
throw std::runtime_error("Section exceeds the binary payload size, please increase it!");
|
||||
}
|
||||
|
||||
if (section->SizeOfRawData > 0)
|
||||
{
|
||||
const auto size_of_data = std::min(section->SizeOfRawData, section->Misc.VirtualSize);
|
||||
std::memmove(target_ptr, source_ptr, size_of_data);
|
||||
|
||||
DWORD old_protect;
|
||||
VirtualProtect(target_ptr, size_of_data, PAGE_EXECUTE_READWRITE, &old_protect);
|
||||
}
|
||||
}
|
||||
|
||||
void loader::load_sections(const utils::nt::module& target, const utils::nt::module& source) const
|
||||
{
|
||||
for (auto& section : source.get_section_headers())
|
||||
{
|
||||
this->load_section(target, source, section);
|
||||
}
|
||||
}
|
||||
|
||||
void loader::load_imports(const utils::nt::module& target, const utils::nt::module& source) const
|
||||
{
|
||||
const auto import_directory = &source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
|
||||
auto descriptor = PIMAGE_IMPORT_DESCRIPTOR(target.get_ptr() + import_directory->VirtualAddress);
|
||||
|
||||
while (descriptor->Name)
|
||||
{
|
||||
std::string name = LPSTR(target.get_ptr() + descriptor->Name);
|
||||
|
||||
auto name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->OriginalFirstThunk);
|
||||
auto address_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||
|
||||
if (!descriptor->OriginalFirstThunk)
|
||||
{
|
||||
name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||
}
|
||||
|
||||
while (*name_table_entry)
|
||||
{
|
||||
FARPROC function = nullptr;
|
||||
std::string function_name;
|
||||
|
||||
// is this an ordinal-only import?
|
||||
if (IMAGE_SNAP_BY_ORDINAL(*name_table_entry))
|
||||
{
|
||||
auto module = utils::nt::module::load(name);
|
||||
if (module)
|
||||
{
|
||||
function = GetProcAddress(module, MAKEINTRESOURCEA(IMAGE_ORDINAL(*name_table_entry)));
|
||||
}
|
||||
|
||||
function_name = "#" + std::to_string(IMAGE_ORDINAL(*name_table_entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto import = PIMAGE_IMPORT_BY_NAME(target.get_ptr() + *name_table_entry);
|
||||
function_name = import->Name;
|
||||
|
||||
if (this->import_resolver_) function = this->import_resolver_(name, function_name);
|
||||
if (!function)
|
||||
{
|
||||
auto module = utils::nt::module::load(name);
|
||||
if (module)
|
||||
{
|
||||
function = GetProcAddress(module, function_name.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function)
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("Unable to load import '%s' from module '%s'",
|
||||
function_name.data(), name.data()));
|
||||
}
|
||||
|
||||
*address_table_entry = reinterpret_cast<uintptr_t>(function);
|
||||
|
||||
name_table_entry++;
|
||||
address_table_entry++;
|
||||
}
|
||||
|
||||
descriptor++;
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,22 @@
|
||||
#pragma once
|
||||
#include "utils/nt.hpp"
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
class loader final
|
||||
{
|
||||
public:
|
||||
explicit loader(launcher::mode mode);
|
||||
|
||||
FARPROC load(const utils::nt::module& module) const;
|
||||
|
||||
void set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver);
|
||||
|
||||
private:
|
||||
launcher::mode mode_;
|
||||
std::function<FARPROC(const std::string&, const std::string&)> import_resolver_;
|
||||
|
||||
static void load_section(const utils::nt::module& target, const utils::nt::module& source,
|
||||
IMAGE_SECTION_HEADER* section);
|
||||
void load_sections(const utils::nt::module& target, const utils::nt::module& source) const;
|
||||
void load_imports(const utils::nt::module& target, const utils::nt::module& source) const;
|
||||
};
|
||||
#pragma once
|
||||
#include "utils/nt.hpp"
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
class loader final
|
||||
{
|
||||
public:
|
||||
explicit loader(launcher::mode mode);
|
||||
|
||||
FARPROC load(const utils::nt::module& module) const;
|
||||
|
||||
void set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver);
|
||||
|
||||
private:
|
||||
launcher::mode mode_;
|
||||
std::function<FARPROC(const std::string&, const std::string&)> import_resolver_;
|
||||
|
||||
static void load_section(const utils::nt::module& target, const utils::nt::module& source,
|
||||
IMAGE_SECTION_HEADER* section);
|
||||
void load_sections(const utils::nt::module& target, const utils::nt::module& source) const;
|
||||
void load_imports(const utils::nt::module& target, const utils::nt::module& source) const;
|
||||
};
|
||||
|
@ -1,100 +1,100 @@
|
||||
#include <std_include.hpp>
|
||||
#include "module_loader.hpp"
|
||||
|
||||
std::vector<std::unique_ptr<module>>* module_loader::modules_ = nullptr;
|
||||
|
||||
void module_loader::register_module(std::unique_ptr<module>&& module_)
|
||||
{
|
||||
if (!modules_)
|
||||
{
|
||||
modules_ = new std::vector<std::unique_ptr<module>>();
|
||||
atexit(destroy_modules);
|
||||
}
|
||||
|
||||
modules_->push_back(std::move(module_));
|
||||
}
|
||||
|
||||
bool module_loader::post_start()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return true;
|
||||
handled = true;
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->post_start();
|
||||
}
|
||||
}
|
||||
catch(premature_shutdown_trigger&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool module_loader::post_load()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return true;
|
||||
handled = true;
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->post_load();
|
||||
}
|
||||
}
|
||||
catch (premature_shutdown_trigger&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void module_loader::pre_destroy()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return;
|
||||
handled = true;
|
||||
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->pre_destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void* module_loader::load_import(const std::string& module, const std::string& function)
|
||||
{
|
||||
void* function_ptr = nullptr;
|
||||
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
const auto module_function_ptr = module_->load_import(module, function);
|
||||
if(module_function_ptr)
|
||||
{
|
||||
function_ptr = module_function_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return function_ptr;
|
||||
}
|
||||
|
||||
void module_loader::destroy_modules()
|
||||
{
|
||||
pre_destroy();
|
||||
|
||||
if (!modules_) return;
|
||||
|
||||
delete modules_;
|
||||
modules_ = nullptr;
|
||||
}
|
||||
|
||||
void module_loader::trigger_premature_shutdown()
|
||||
{
|
||||
throw premature_shutdown_trigger();
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "module_loader.hpp"
|
||||
|
||||
std::vector<std::unique_ptr<module>>* module_loader::modules_ = nullptr;
|
||||
|
||||
void module_loader::register_module(std::unique_ptr<module>&& module_)
|
||||
{
|
||||
if (!modules_)
|
||||
{
|
||||
modules_ = new std::vector<std::unique_ptr<module>>();
|
||||
atexit(destroy_modules);
|
||||
}
|
||||
|
||||
modules_->push_back(std::move(module_));
|
||||
}
|
||||
|
||||
bool module_loader::post_start()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return true;
|
||||
handled = true;
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->post_start();
|
||||
}
|
||||
}
|
||||
catch(premature_shutdown_trigger&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool module_loader::post_load()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return true;
|
||||
handled = true;
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->post_load();
|
||||
}
|
||||
}
|
||||
catch (premature_shutdown_trigger&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void module_loader::pre_destroy()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return;
|
||||
handled = true;
|
||||
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->pre_destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void* module_loader::load_import(const std::string& module, const std::string& function)
|
||||
{
|
||||
void* function_ptr = nullptr;
|
||||
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
const auto module_function_ptr = module_->load_import(module, function);
|
||||
if(module_function_ptr)
|
||||
{
|
||||
function_ptr = module_function_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return function_ptr;
|
||||
}
|
||||
|
||||
void module_loader::destroy_modules()
|
||||
{
|
||||
pre_destroy();
|
||||
|
||||
if (!modules_) return;
|
||||
|
||||
delete modules_;
|
||||
modules_ = nullptr;
|
||||
}
|
||||
|
||||
void module_loader::trigger_premature_shutdown()
|
||||
{
|
||||
throw premature_shutdown_trigger();
|
||||
}
|
||||
|
264
src/main.cpp
264
src/main.cpp
@ -1,132 +1,132 @@
|
||||
#include <std_include.hpp>
|
||||
#include "launcher/launcher.hpp"
|
||||
#include "loader/loader.hpp"
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "loader/binary_loader.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/flags.hpp"
|
||||
|
||||
//#define GENERATE_DIFFS
|
||||
|
||||
DECLSPEC_NORETURN void WINAPI exit_hook(const int code)
|
||||
{
|
||||
module_loader::pre_destroy();
|
||||
exit(code);
|
||||
}
|
||||
|
||||
void verify_tls()
|
||||
{
|
||||
utils::nt::module self;
|
||||
const auto self_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(self.get_ptr() + self
|
||||
.get_optional_header()
|
||||
->
|
||||
DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
|
||||
const auto ref = DWORD(&tls_data);
|
||||
const auto tls_index = *reinterpret_cast<DWORD*>(self_tls->AddressOfIndex);
|
||||
const auto tls_vector = *reinterpret_cast<DWORD*>(__readfsdword(0x2C) + 4 * tls_index);
|
||||
const auto offset = ref - tls_vector;
|
||||
|
||||
if (offset != 0 && offset != 8) // Actually 8 is bad, but I think msvc places custom stuff before
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("TLS payload is at offset 0x%X, but should be at 0!",
|
||||
offset));
|
||||
}
|
||||
}
|
||||
|
||||
launcher::mode detect_mode_from_arguments()
|
||||
{
|
||||
if (utils::flags::has_flag("dedicated"))
|
||||
{
|
||||
return launcher::mode::server;
|
||||
}
|
||||
|
||||
if (utils::flags::has_flag("multiplayer"))
|
||||
{
|
||||
return launcher::mode::multiplayer;
|
||||
}
|
||||
|
||||
if (utils::flags::has_flag("singleplayer"))
|
||||
{
|
||||
return launcher::mode::singleplayer;
|
||||
}
|
||||
|
||||
return launcher::mode::none;
|
||||
}
|
||||
|
||||
FARPROC load_binary(const launcher::mode mode)
|
||||
{
|
||||
loader loader(mode);
|
||||
utils::nt::module self;
|
||||
|
||||
loader.set_import_resolver([self](const std::string& module, const std::string& function) -> FARPROC
|
||||
{
|
||||
if (module == "steam_api.dll")
|
||||
{
|
||||
return self.get_proc<FARPROC>(function);
|
||||
}
|
||||
else if (function == "ExitProcess")
|
||||
{
|
||||
return FARPROC(exit_hook);
|
||||
}
|
||||
|
||||
return FARPROC(module_loader::load_import(module, function));
|
||||
});
|
||||
|
||||
return loader.load(self);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FARPROC entry_point;
|
||||
|
||||
{
|
||||
auto premature_shutdown = true;
|
||||
const auto _ = gsl::finally([&premature_shutdown]()
|
||||
{
|
||||
if (premature_shutdown)
|
||||
{
|
||||
module_loader::pre_destroy();
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
#ifdef GENERATE_DIFFS
|
||||
binary_loader::create();
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
verify_tls();
|
||||
if (!module_loader::post_start()) return 0;
|
||||
|
||||
auto mode = detect_mode_from_arguments();
|
||||
if (mode == launcher::mode::none)
|
||||
{
|
||||
launcher launcher;
|
||||
mode = launcher.run();
|
||||
if (mode == launcher::mode::none) return 0;
|
||||
}
|
||||
|
||||
entry_point = load_binary(mode);
|
||||
if (!entry_point)
|
||||
{
|
||||
throw std::runtime_error("Unable to load binary into memory");
|
||||
}
|
||||
|
||||
game::initialize(mode);
|
||||
if (!module_loader::post_load()) return 0;
|
||||
|
||||
premature_shutdown = false;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return entry_point();
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "launcher/launcher.hpp"
|
||||
#include "loader/loader.hpp"
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "loader/binary_loader.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/flags.hpp"
|
||||
|
||||
//#define GENERATE_DIFFS
|
||||
|
||||
DECLSPEC_NORETURN void WINAPI exit_hook(const int code)
|
||||
{
|
||||
module_loader::pre_destroy();
|
||||
exit(code);
|
||||
}
|
||||
|
||||
void verify_tls()
|
||||
{
|
||||
utils::nt::module self;
|
||||
const auto self_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(self.get_ptr() + self
|
||||
.get_optional_header()
|
||||
->
|
||||
DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
|
||||
const auto ref = DWORD(&tls_data);
|
||||
const auto tls_index = *reinterpret_cast<DWORD*>(self_tls->AddressOfIndex);
|
||||
const auto tls_vector = *reinterpret_cast<DWORD*>(__readfsdword(0x2C) + 4 * tls_index);
|
||||
const auto offset = ref - tls_vector;
|
||||
|
||||
if (offset != 0 && offset != 8) // Actually 8 is bad, but I think msvc places custom stuff before
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("TLS payload is at offset 0x%X, but should be at 0!",
|
||||
offset));
|
||||
}
|
||||
}
|
||||
|
||||
launcher::mode detect_mode_from_arguments()
|
||||
{
|
||||
if (utils::flags::has_flag("dedicated"))
|
||||
{
|
||||
return launcher::mode::server;
|
||||
}
|
||||
|
||||
if (utils::flags::has_flag("multiplayer"))
|
||||
{
|
||||
return launcher::mode::multiplayer;
|
||||
}
|
||||
|
||||
if (utils::flags::has_flag("singleplayer"))
|
||||
{
|
||||
return launcher::mode::singleplayer;
|
||||
}
|
||||
|
||||
return launcher::mode::none;
|
||||
}
|
||||
|
||||
FARPROC load_binary(const launcher::mode mode)
|
||||
{
|
||||
loader loader(mode);
|
||||
utils::nt::module self;
|
||||
|
||||
loader.set_import_resolver([self](const std::string& module, const std::string& function) -> FARPROC
|
||||
{
|
||||
if (module == "steam_api.dll")
|
||||
{
|
||||
return self.get_proc<FARPROC>(function);
|
||||
}
|
||||
else if (function == "ExitProcess")
|
||||
{
|
||||
return FARPROC(exit_hook);
|
||||
}
|
||||
|
||||
return FARPROC(module_loader::load_import(module, function));
|
||||
});
|
||||
|
||||
return loader.load(self);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FARPROC entry_point;
|
||||
|
||||
{
|
||||
auto premature_shutdown = true;
|
||||
const auto _ = gsl::finally([&premature_shutdown]()
|
||||
{
|
||||
if (premature_shutdown)
|
||||
{
|
||||
module_loader::pre_destroy();
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
#ifdef GENERATE_DIFFS
|
||||
binary_loader::create();
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
verify_tls();
|
||||
if (!module_loader::post_start()) return 0;
|
||||
|
||||
auto mode = detect_mode_from_arguments();
|
||||
if (mode == launcher::mode::none)
|
||||
{
|
||||
launcher launcher;
|
||||
mode = launcher.run();
|
||||
if (mode == launcher::mode::none) return 0;
|
||||
}
|
||||
|
||||
entry_point = load_binary(mode);
|
||||
if (!entry_point)
|
||||
{
|
||||
throw std::runtime_error("Unable to load binary into memory");
|
||||
}
|
||||
|
||||
game::initialize(mode);
|
||||
if (!module_loader::post_load()) return 0;
|
||||
|
||||
premature_shutdown = false;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return entry_point();
|
||||
}
|
||||
|
@ -1,90 +1,90 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
class ceg final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
// Only SP has CEG
|
||||
// CEG in MP has accidentally been removed due to CVE-2018-10718
|
||||
if (!game::is_sp()) return;
|
||||
|
||||
utils::hook::signature signature(0x401000, 0x3E1000);
|
||||
|
||||
signature.add({
|
||||
"\x56\xE8\x00\x00\x00\x00\x8B\xF0\xE8\x00\x00\x00\x00\x50\x56\xE8", "xx????xxx????xxx", [](char* address)
|
||||
{
|
||||
utils::hook::set<DWORD>(address, 0xC301B0);
|
||||
}
|
||||
});
|
||||
|
||||
// Generic killer caller.
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\x80\x7D\x08\x00\x75\x55", "xxxxxx?xx", [](char* address)
|
||||
{
|
||||
utils::hook::set<DWORD>(address, 0xC301B0);
|
||||
}
|
||||
});
|
||||
|
||||
// CEG initialization.
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\x83\xEC\x18\x53\x56\x57\xE8\x00\x00\x00\x00", "xxxxxxxxxx????", [](char* address)
|
||||
{
|
||||
utils::hook::set<BYTE>(address, 0xC3);
|
||||
}
|
||||
});
|
||||
|
||||
// Some odd trap.
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\x81\xEC\x00\x00\x00\x00\x53\x56\x57\x8B\x3D", "xxxxx??xxxxxxx", [](char* address)
|
||||
{
|
||||
utils::hook::set<DWORD>(address, 0xC301B0);
|
||||
}
|
||||
});
|
||||
|
||||
// Custom shit
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\x68\x00\x00\x00\x00\x68\x00\x00\x00\x00\x64\xFF\x35\x00\x00\x00\x00\x64\x89\x25\x00\x00\x00\x00\xE8",
|
||||
"xxxx????x????xxx????xxx????x", [](char* address)
|
||||
{
|
||||
utils::hook::set<BYTE>(address, 0xC3);
|
||||
}
|
||||
});
|
||||
|
||||
// hkcr guid check
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\xB8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x84\xC0\x75\x06",
|
||||
"xxxx????x????x????xxxx", [](char* address)
|
||||
{
|
||||
utils::hook::nop(address + 0xD, 5); // Call
|
||||
utils::hook::nop(address + 0x14, 2); // Jump
|
||||
}
|
||||
});
|
||||
|
||||
// hkcr guid check 2
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\x81\xEC\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x84\xC0\x75\x06", "xxxxx????x????xxxx", [
|
||||
](char* address)
|
||||
{
|
||||
utils::hook::nop(address + 0x9, 5); // Call
|
||||
utils::hook::nop(address + 0x10, 2); // Jump
|
||||
}
|
||||
});
|
||||
|
||||
signature.process();
|
||||
|
||||
// Function fixup
|
||||
utils::hook(0x4CA310, game::native::DB_LoadXAssets, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Some value obfuscation
|
||||
utils::hook(0x493B81, 0x493BFC, HOOK_JUMP).install()->quick();
|
||||
|
||||
// CEG uninitialization
|
||||
utils::hook::set<BYTE>(0x527110, 0xC3);
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(ceg)
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
class ceg final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
// Only SP has CEG
|
||||
// CEG in MP has accidentally been removed due to CVE-2018-10718
|
||||
if (!game::is_sp()) return;
|
||||
|
||||
utils::hook::signature signature(0x401000, 0x3E1000);
|
||||
|
||||
signature.add({
|
||||
"\x56\xE8\x00\x00\x00\x00\x8B\xF0\xE8\x00\x00\x00\x00\x50\x56\xE8", "xx????xxx????xxx", [](char* address)
|
||||
{
|
||||
utils::hook::set<DWORD>(address, 0xC301B0);
|
||||
}
|
||||
});
|
||||
|
||||
// Generic killer caller.
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\x80\x7D\x08\x00\x75\x55", "xxxxxx?xx", [](char* address)
|
||||
{
|
||||
utils::hook::set<DWORD>(address, 0xC301B0);
|
||||
}
|
||||
});
|
||||
|
||||
// CEG initialization.
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\x83\xEC\x18\x53\x56\x57\xE8\x00\x00\x00\x00", "xxxxxxxxxx????", [](char* address)
|
||||
{
|
||||
utils::hook::set<BYTE>(address, 0xC3);
|
||||
}
|
||||
});
|
||||
|
||||
// Some odd trap.
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\x81\xEC\x00\x00\x00\x00\x53\x56\x57\x8B\x3D", "xxxxx??xxxxxxx", [](char* address)
|
||||
{
|
||||
utils::hook::set<DWORD>(address, 0xC301B0);
|
||||
}
|
||||
});
|
||||
|
||||
// Custom shit
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\x68\x00\x00\x00\x00\x68\x00\x00\x00\x00\x64\xFF\x35\x00\x00\x00\x00\x64\x89\x25\x00\x00\x00\x00\xE8",
|
||||
"xxxx????x????xxx????xxx????x", [](char* address)
|
||||
{
|
||||
utils::hook::set<BYTE>(address, 0xC3);
|
||||
}
|
||||
});
|
||||
|
||||
// hkcr guid check
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\xB8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x84\xC0\x75\x06",
|
||||
"xxxx????x????x????xxxx", [](char* address)
|
||||
{
|
||||
utils::hook::nop(address + 0xD, 5); // Call
|
||||
utils::hook::nop(address + 0x14, 2); // Jump
|
||||
}
|
||||
});
|
||||
|
||||
// hkcr guid check 2
|
||||
signature.add({
|
||||
"\x55\x8B\xEC\x81\xEC\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x84\xC0\x75\x06", "xxxxx????x????xxxx", [
|
||||
](char* address)
|
||||
{
|
||||
utils::hook::nop(address + 0x9, 5); // Call
|
||||
utils::hook::nop(address + 0x10, 2); // Jump
|
||||
}
|
||||
});
|
||||
|
||||
signature.process();
|
||||
|
||||
// Function fixup
|
||||
utils::hook(0x4CA310, game::native::DB_LoadXAssets, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Some value obfuscation
|
||||
utils::hook(0x493B81, 0x493BFC, HOOK_JUMP).install()->quick();
|
||||
|
||||
// CEG uninitialization
|
||||
utils::hook::set<BYTE>(0x527110, 0xC3);
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(ceg)
|
||||
|
@ -1,115 +1,115 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
class console final : public module
|
||||
{
|
||||
public:
|
||||
console()
|
||||
{
|
||||
ShowWindow(GetConsoleWindow(), SW_HIDE);
|
||||
|
||||
_pipe(this->handles_, 1024, _O_TEXT);
|
||||
_dup2(this->handles_[1], 1);
|
||||
_dup2(this->handles_[1], 2);
|
||||
|
||||
//setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
//setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
}
|
||||
|
||||
void post_start() override
|
||||
{
|
||||
scheduler::on_frame(std::bind(&console::log_messages, this));
|
||||
this->console_runner_ = std::thread(std::bind(&console::runner, this));
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
this->terminate_runner_ = true;
|
||||
|
||||
printf("\r\n");
|
||||
_flushall();
|
||||
|
||||
_close(this->handles_[0]);
|
||||
_close(this->handles_[1]);
|
||||
|
||||
if (this->console_runner_.joinable())
|
||||
{
|
||||
this->console_runner_.join();
|
||||
}
|
||||
}
|
||||
|
||||
void post_load() override
|
||||
{
|
||||
if (!game::is_dedi())
|
||||
{
|
||||
game::native::Sys_ShowConsole();
|
||||
}
|
||||
|
||||
std::lock_guard _(this->mutex_);
|
||||
this->console_initialized_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool console_initialized_ = false;
|
||||
bool terminate_runner_ = false;
|
||||
|
||||
std::mutex mutex_;
|
||||
std::thread console_runner_;
|
||||
std::queue<std::string> message_queue_;
|
||||
|
||||
int handles_[2]{};
|
||||
|
||||
void log_messages()
|
||||
{
|
||||
while (this->console_initialized_ && !this->message_queue_.empty())
|
||||
{
|
||||
std::queue<std::string> message_queue_copy;
|
||||
|
||||
{
|
||||
std::lock_guard _(this->mutex_);
|
||||
message_queue_copy = this->message_queue_;
|
||||
this->message_queue_ = {};
|
||||
}
|
||||
|
||||
while (!message_queue_copy.empty())
|
||||
{
|
||||
log_message(message_queue_copy.front());
|
||||
message_queue_copy.pop();
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
static void log_message(const std::string& message)
|
||||
{
|
||||
OutputDebugStringA(message.data());
|
||||
game::native::Conbuf_AppendText(message.data());
|
||||
}
|
||||
|
||||
void runner()
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
while (!this->terminate_runner_ && this->handles_[0])
|
||||
{
|
||||
const auto len = _read(this->handles_[0], buffer, sizeof(buffer));
|
||||
if (len > 0)
|
||||
{
|
||||
std::lock_guard _(this->mutex_);
|
||||
this->message_queue_.push(std::string(buffer, len));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::yield();
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(console)
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
class console final : public module
|
||||
{
|
||||
public:
|
||||
console()
|
||||
{
|
||||
ShowWindow(GetConsoleWindow(), SW_HIDE);
|
||||
|
||||
_pipe(this->handles_, 1024, _O_TEXT);
|
||||
_dup2(this->handles_[1], 1);
|
||||
_dup2(this->handles_[1], 2);
|
||||
|
||||
//setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
//setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
}
|
||||
|
||||
void post_start() override
|
||||
{
|
||||
scheduler::on_frame(std::bind(&console::log_messages, this));
|
||||
this->console_runner_ = std::thread(std::bind(&console::runner, this));
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
this->terminate_runner_ = true;
|
||||
|
||||
printf("\r\n");
|
||||
_flushall();
|
||||
|
||||
_close(this->handles_[0]);
|
||||
_close(this->handles_[1]);
|
||||
|
||||
if (this->console_runner_.joinable())
|
||||
{
|
||||
this->console_runner_.join();
|
||||
}
|
||||
}
|
||||
|
||||
void post_load() override
|
||||
{
|
||||
if (!game::is_dedi())
|
||||
{
|
||||
game::native::Sys_ShowConsole();
|
||||
}
|
||||
|
||||
std::lock_guard _(this->mutex_);
|
||||
this->console_initialized_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool console_initialized_ = false;
|
||||
bool terminate_runner_ = false;
|
||||
|
||||
std::mutex mutex_;
|
||||
std::thread console_runner_;
|
||||
std::queue<std::string> message_queue_;
|
||||
|
||||
int handles_[2]{};
|
||||
|
||||
void log_messages()
|
||||
{
|
||||
while (this->console_initialized_ && !this->message_queue_.empty())
|
||||
{
|
||||
std::queue<std::string> message_queue_copy;
|
||||
|
||||
{
|
||||
std::lock_guard _(this->mutex_);
|
||||
message_queue_copy = this->message_queue_;
|
||||
this->message_queue_ = {};
|
||||
}
|
||||
|
||||
while (!message_queue_copy.empty())
|
||||
{
|
||||
log_message(message_queue_copy.front());
|
||||
message_queue_copy.pop();
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
static void log_message(const std::string& message)
|
||||
{
|
||||
OutputDebugStringA(message.data());
|
||||
game::native::Conbuf_AppendText(message.data());
|
||||
}
|
||||
|
||||
void runner()
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
while (!this->terminate_runner_ && this->handles_[0])
|
||||
{
|
||||
const auto len = _read(this->handles_[0], buffer, sizeof(buffer));
|
||||
if (len > 0)
|
||||
{
|
||||
std::lock_guard _(this->mutex_);
|
||||
this->message_queue_.push(std::string(buffer, len));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::yield();
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(console)
|
||||
|
@ -1,50 +1,50 @@
|
||||
#include <std_include.hpp>
|
||||
#include <discord_rpc.h>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
class discord final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
if (game::is_dedi()) return;
|
||||
|
||||
DiscordEventHandlers handlers;
|
||||
ZeroMemory(&handlers, sizeof(handlers));
|
||||
handlers.ready = ready;
|
||||
handlers.errored = errored;
|
||||
handlers.disconnected = errored;
|
||||
handlers.joinGame = nullptr;
|
||||
handlers.spectateGame = nullptr;
|
||||
handlers.joinRequest = nullptr;
|
||||
|
||||
Discord_Initialize("531526691319971880", &handlers, 1, nullptr);
|
||||
|
||||
scheduler::on_frame(Discord_RunCallbacks);
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
Discord_Shutdown();
|
||||
}
|
||||
|
||||
private:
|
||||
static void ready(const DiscordUser* request)
|
||||
{
|
||||
DiscordRichPresence discord_presence;
|
||||
ZeroMemory(&discord_presence, sizeof(discord_presence));
|
||||
|
||||
discord_presence.state = game::is_mp() ? "Multiplayer" : "Singleplayer";
|
||||
discord_presence.instance = 1;
|
||||
Discord_UpdatePresence(&discord_presence);
|
||||
}
|
||||
|
||||
static void errored(const int error_code, const char* message)
|
||||
{
|
||||
printf("Discord: (%i) %s", error_code, message);
|
||||
}
|
||||
};
|
||||
|
||||
//REGISTER_MODULE(discord)
|
||||
#include <std_include.hpp>
|
||||
#include <discord_rpc.h>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
class discord final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
if (game::is_dedi()) return;
|
||||
|
||||
DiscordEventHandlers handlers;
|
||||
ZeroMemory(&handlers, sizeof(handlers));
|
||||
handlers.ready = ready;
|
||||
handlers.errored = errored;
|
||||
handlers.disconnected = errored;
|
||||
handlers.joinGame = nullptr;
|
||||
handlers.spectateGame = nullptr;
|
||||
handlers.joinRequest = nullptr;
|
||||
|
||||
Discord_Initialize("531526691319971880", &handlers, 1, nullptr);
|
||||
|
||||
scheduler::on_frame(Discord_RunCallbacks);
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
Discord_Shutdown();
|
||||
}
|
||||
|
||||
private:
|
||||
static void ready(const DiscordUser* request)
|
||||
{
|
||||
DiscordRichPresence discord_presence;
|
||||
ZeroMemory(&discord_presence, sizeof(discord_presence));
|
||||
|
||||
discord_presence.state = game::is_mp() ? "Multiplayer" : "Singleplayer";
|
||||
discord_presence.instance = 1;
|
||||
Discord_UpdatePresence(&discord_presence);
|
||||
}
|
||||
|
||||
static void errored(const int error_code, const char* message)
|
||||
{
|
||||
printf("Discord: (%i) %s", error_code, message);
|
||||
}
|
||||
};
|
||||
|
||||
//REGISTER_MODULE(discord)
|
||||
|
@ -1,60 +1,60 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "game/structs.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
|
||||
static __declspec(naked) void db_load_stub_client(game::native::XZoneInfo*, unsigned int, int)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
sub esp, 0Ch
|
||||
mov eax, [esp + 18h]
|
||||
|
||||
mov ecx, game::native::DB_LoadXAssets
|
||||
add ecx, 7h
|
||||
push ecx
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
static __declspec(naked) void db_load_stub_server(game::native::XZoneInfo*, unsigned int, int)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
sub esp, 10h
|
||||
mov eax, [esp + 1Ch]
|
||||
|
||||
mov ecx, game::native::DB_LoadXAssets
|
||||
add ecx, 7h
|
||||
push ecx
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
class fastfiles final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
utils::hook(game::native::DB_LoadXAssets, db_load_stub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
|
||||
private:
|
||||
static void db_load_stub(game::native::XZoneInfo* zone_info, const unsigned int zone_count, const int sync)
|
||||
{
|
||||
for (unsigned int i = 0; i < zone_count; ++i)
|
||||
{
|
||||
if (zone_info[i].name)
|
||||
{
|
||||
printf("Loading FastFile: %s (0x%X | 0x%X)\n", zone_info[i].name, zone_info[i].allocFlags,
|
||||
zone_info[i].freeFlags);
|
||||
}
|
||||
}
|
||||
|
||||
if (game::is_dedi()) return db_load_stub_server(zone_info, zone_count, sync);
|
||||
else return db_load_stub_client(zone_info, zone_count, sync);
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(fastfiles)
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "game/structs.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
|
||||
static __declspec(naked) void db_load_stub_client(game::native::XZoneInfo*, unsigned int, int)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
sub esp, 0Ch
|
||||
mov eax, [esp + 18h]
|
||||
|
||||
mov ecx, game::native::DB_LoadXAssets
|
||||
add ecx, 7h
|
||||
push ecx
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
static __declspec(naked) void db_load_stub_server(game::native::XZoneInfo*, unsigned int, int)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
sub esp, 10h
|
||||
mov eax, [esp + 1Ch]
|
||||
|
||||
mov ecx, game::native::DB_LoadXAssets
|
||||
add ecx, 7h
|
||||
push ecx
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
class fastfiles final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
utils::hook(game::native::DB_LoadXAssets, db_load_stub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
|
||||
private:
|
||||
static void db_load_stub(game::native::XZoneInfo* zone_info, const unsigned int zone_count, const int sync)
|
||||
{
|
||||
for (unsigned int i = 0; i < zone_count; ++i)
|
||||
{
|
||||
if (zone_info[i].name)
|
||||
{
|
||||
printf("Loading FastFile: %s (0x%X | 0x%X)\n", zone_info[i].name, zone_info[i].allocFlags,
|
||||
zone_info[i].freeFlags);
|
||||
}
|
||||
}
|
||||
|
||||
if (game::is_dedi()) return db_load_stub_server(zone_info, zone_count, sync);
|
||||
else return db_load_stub_client(zone_info, zone_count, sync);
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(fastfiles)
|
||||
|
@ -1,37 +1,37 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
class fov final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
if (game::is_dedi()) return;
|
||||
|
||||
// Set dvar flag
|
||||
utils::hook::set<BYTE>(SELECT_VALUE(0x4302C5, 0x455155, 0), 0x1 | (game::is_mp() ? 0x40 : 0));
|
||||
|
||||
if (game::is_mp())
|
||||
{
|
||||
// Set dvar limit
|
||||
static const auto cg_fov_limit = 90.0f;
|
||||
utils::hook::set(0x455148, &cg_fov_limit);
|
||||
|
||||
// Prevent value change via internal scripts
|
||||
utils::hook(0x4698BA, &set_server_command_dvar_stub, HOOK_CALL).install()->quick();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void set_server_command_dvar_stub(const char* dvar, const char* value)
|
||||
{
|
||||
if (strcmp(dvar, "cg_fov") != 0 || strcmp(value, "65") != 0)
|
||||
{
|
||||
game::native::Dvar_SetFromStringByName(dvar, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(fov)
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
class fov final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
if (game::is_dedi()) return;
|
||||
|
||||
// Set dvar flag
|
||||
utils::hook::set<BYTE>(SELECT_VALUE(0x4302C5, 0x455155, 0), 0x1 | (game::is_mp() ? 0x40 : 0));
|
||||
|
||||
if (game::is_mp())
|
||||
{
|
||||
// Set dvar limit
|
||||
static const auto cg_fov_limit = 90.0f;
|
||||
utils::hook::set(0x455148, &cg_fov_limit);
|
||||
|
||||
// Prevent value change via internal scripts
|
||||
utils::hook(0x4698BA, &set_server_command_dvar_stub, HOOK_CALL).install()->quick();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void set_server_command_dvar_stub(const char* dvar, const char* value)
|
||||
{
|
||||
if (strcmp(dvar, "cg_fov") != 0 || strcmp(value, "65") != 0)
|
||||
{
|
||||
game::native::Dvar_SetFromStringByName(dvar, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(fov)
|
||||
|
@ -1,61 +1,61 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
class patches final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
if (!game::is_dedi()) this->patch_clients();
|
||||
|
||||
if (game::is_sp()) this->patch_sp();
|
||||
else if (game::is_mp()) this->patch_mp();
|
||||
else if (game::is_dedi()) this->patch_dedi();
|
||||
|
||||
utils::hook(game::native::_longjmp, long_jump_stub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
|
||||
private:
|
||||
void patch_clients() const
|
||||
{
|
||||
// Remove improper quit check
|
||||
utils::hook::nop(SELECT_VALUE(0x53444A, 0x5CCDC0, 0), 9);
|
||||
|
||||
// Ignore sdm files
|
||||
utils::hook::nop(SELECT_VALUE(0x4438BA, 0x6371EA, 0), 2);
|
||||
}
|
||||
|
||||
void patch_sp() const
|
||||
{
|
||||
// SP doesn't initialize WSA
|
||||
WSADATA wsa_data;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||
|
||||
// Disable remote storage
|
||||
utils::hook::set<BYTE>(0x663B5A, 0xEB);
|
||||
utils::hook::set<BYTE>(0x663C54, 0xEB);
|
||||
}
|
||||
|
||||
void patch_mp() const
|
||||
{
|
||||
}
|
||||
|
||||
void patch_dedi() const
|
||||
{
|
||||
}
|
||||
|
||||
static __declspec(noreturn) void long_jump_stub(jmp_buf buf, const int value) noexcept(false)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
{
|
||||
printf("Unwinding the stack...\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
longjmp(buf, value);
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(patches)
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
class patches final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
if (!game::is_dedi()) this->patch_clients();
|
||||
|
||||
if (game::is_sp()) this->patch_sp();
|
||||
else if (game::is_mp()) this->patch_mp();
|
||||
else if (game::is_dedi()) this->patch_dedi();
|
||||
|
||||
utils::hook(game::native::_longjmp, long_jump_stub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
|
||||
private:
|
||||
void patch_clients() const
|
||||
{
|
||||
// Remove improper quit check
|
||||
utils::hook::nop(SELECT_VALUE(0x53444A, 0x5CCDC0, 0), 9);
|
||||
|
||||
// Ignore sdm files
|
||||
utils::hook::nop(SELECT_VALUE(0x4438BA, 0x6371EA, 0), 2);
|
||||
}
|
||||
|
||||
void patch_sp() const
|
||||
{
|
||||
// SP doesn't initialize WSA
|
||||
WSADATA wsa_data;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||
|
||||
// Disable remote storage
|
||||
utils::hook::set<BYTE>(0x663B5A, 0xEB);
|
||||
utils::hook::set<BYTE>(0x663C54, 0xEB);
|
||||
}
|
||||
|
||||
void patch_mp() const
|
||||
{
|
||||
}
|
||||
|
||||
void patch_dedi() const
|
||||
{
|
||||
}
|
||||
|
||||
static __declspec(noreturn) void long_jump_stub(jmp_buf buf, const int value) noexcept(false)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
{
|
||||
printf("Unwinding the stack...\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
longjmp(buf, value);
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(patches)
|
||||
|
@ -1,162 +1,162 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include "utils/io.hpp"
|
||||
#include "game/scripting/context.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
class scripting final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
start_hook_.initialize(SELECT_VALUE(0x50C575, 0x50D4F2, 0x48A026), &start_execution_stub, HOOK_CALL) //
|
||||
->install() //
|
||||
->quick();
|
||||
|
||||
stop_hook_.initialize(SELECT_VALUE(0x528B04, 0x569E46, 0x4F03FA), &stop_execution_stub, HOOK_CALL) //
|
||||
->install() //
|
||||
->quick();
|
||||
|
||||
utils::hook(SELECT_VALUE(0x4F9706, 0x5772A0, 0x4FAB88), &frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(SELECT_VALUE(0x4FFA48, 0x5774AB, 0x4FEFD7), &frame_stub, HOOK_CALL).install()->quick(); // Only relevant one?
|
||||
|
||||
utils::hook(SELECT_VALUE(0x6109F3, 0x56B637, 0x4EDFF7), &vm_notify_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(SELECT_VALUE(0x6128BE, 0x56D541, 0x4EFAF9), &vm_notify_stub, HOOK_CALL).install()->quick();
|
||||
|
||||
if (game::is_sp())
|
||||
{
|
||||
utils::hook(0x50C57E, &frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x6523A3, &frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x5145D2, &frame_stub, HOOK_CALL).install()->quick();
|
||||
|
||||
utils::hook(0x610970, &vm_notify_stub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
this->scripts_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<game::scripting::context>> scripts_;
|
||||
|
||||
void load_scripts()
|
||||
{
|
||||
const auto scripts = utils::io::list_files("open-iw5/scripts/");
|
||||
|
||||
for (const auto& script : scripts)
|
||||
{
|
||||
if (script.substr(script.find_last_of('.') + 1) == "chai")
|
||||
{
|
||||
try
|
||||
{
|
||||
auto context = std::make_unique<game::scripting::context>();
|
||||
context->get_chai()->eval_file(script);
|
||||
this->scripts_.push_back(std::move(context));
|
||||
}
|
||||
catch (chaiscript::exception::eval_error& e)
|
||||
{
|
||||
throw std::runtime_error(e.pretty_print());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void start_execution()
|
||||
{
|
||||
try
|
||||
{
|
||||
this->load_scripts();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
propagate_error(e);
|
||||
}
|
||||
}
|
||||
|
||||
void stop_execution()
|
||||
{
|
||||
this->scripts_.clear();
|
||||
}
|
||||
|
||||
void run_frame()
|
||||
{
|
||||
for (const auto& script : this->scripts_)
|
||||
{
|
||||
script->get_scheduler()->run_frame();
|
||||
}
|
||||
}
|
||||
|
||||
void dispatch(game::scripting::event* event)
|
||||
{
|
||||
for (const auto& script : this->scripts_)
|
||||
{
|
||||
script->get_event_handler()->dispatch(event);
|
||||
}
|
||||
}
|
||||
|
||||
static utils::hook start_hook_;
|
||||
static utils::hook stop_hook_;
|
||||
|
||||
static void propagate_error(const std::exception& e)
|
||||
{
|
||||
printf("\n******* Script execution error *******\n");
|
||||
printf("%s\n", e.what());
|
||||
printf("**************************************\n\n");
|
||||
|
||||
scheduler::error("Script execution error\n(see console for actual details)\n", 5);
|
||||
}
|
||||
|
||||
static void start_execution_stub()
|
||||
{
|
||||
module_loader::get<scripting>()->start_execution();
|
||||
reinterpret_cast<void(*)()>(start_hook_.get_original())();
|
||||
}
|
||||
|
||||
static void stop_execution_stub()
|
||||
{
|
||||
module_loader::get<scripting>()->stop_execution();
|
||||
reinterpret_cast<void(*)()>(stop_hook_.get_original())();
|
||||
}
|
||||
|
||||
static void vm_notify_stub(const unsigned int notify_id, const unsigned short type,
|
||||
game::native::VariableValue* stack)
|
||||
{
|
||||
try
|
||||
{
|
||||
game::scripting::event e;
|
||||
e.name = game::native::SL_ConvertToString(type);
|
||||
e.entity_id = notify_id;
|
||||
|
||||
if (e.name == "touch") return; // Skip that for now
|
||||
|
||||
//printf("%X: %s\n", e.entity_id, e.name.data());
|
||||
|
||||
for (auto value = stack; value->type != game::native::SCRIPT_END; --value)
|
||||
{
|
||||
e.arguments.emplace_back(*value);
|
||||
}
|
||||
|
||||
module_loader::get<scripting>()->dispatch(&e);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
propagate_error(e);
|
||||
}
|
||||
|
||||
game::native::VM_Notify(notify_id, type, stack);
|
||||
}
|
||||
|
||||
static int frame_stub(int a1, int a2)
|
||||
{
|
||||
module_loader::get<scripting>()->run_frame();
|
||||
return game::native::G_RunFrame(a1, a2);
|
||||
}
|
||||
};
|
||||
|
||||
utils::hook scripting::start_hook_;
|
||||
utils::hook scripting::stop_hook_;
|
||||
|
||||
REGISTER_MODULE(scripting)
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include "utils/io.hpp"
|
||||
#include "game/scripting/context.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
class scripting final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
start_hook_.initialize(SELECT_VALUE(0x50C575, 0x50D4F2, 0x48A026), &start_execution_stub, HOOK_CALL) //
|
||||
->install() //
|
||||
->quick();
|
||||
|
||||
stop_hook_.initialize(SELECT_VALUE(0x528B04, 0x569E46, 0x4F03FA), &stop_execution_stub, HOOK_CALL) //
|
||||
->install() //
|
||||
->quick();
|
||||
|
||||
utils::hook(SELECT_VALUE(0x4F9706, 0x5772A0, 0x4FAB88), &frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(SELECT_VALUE(0x4FFA48, 0x5774AB, 0x4FEFD7), &frame_stub, HOOK_CALL).install()->quick(); // Only relevant one?
|
||||
|
||||
utils::hook(SELECT_VALUE(0x6109F3, 0x56B637, 0x4EDFF7), &vm_notify_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(SELECT_VALUE(0x6128BE, 0x56D541, 0x4EFAF9), &vm_notify_stub, HOOK_CALL).install()->quick();
|
||||
|
||||
if (game::is_sp())
|
||||
{
|
||||
utils::hook(0x50C57E, &frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x6523A3, &frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x5145D2, &frame_stub, HOOK_CALL).install()->quick();
|
||||
|
||||
utils::hook(0x610970, &vm_notify_stub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
this->scripts_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<game::scripting::context>> scripts_;
|
||||
|
||||
void load_scripts()
|
||||
{
|
||||
const auto scripts = utils::io::list_files("open-iw5/scripts/");
|
||||
|
||||
for (const auto& script : scripts)
|
||||
{
|
||||
if (script.substr(script.find_last_of('.') + 1) == "chai")
|
||||
{
|
||||
try
|
||||
{
|
||||
auto context = std::make_unique<game::scripting::context>();
|
||||
context->get_chai()->eval_file(script);
|
||||
this->scripts_.push_back(std::move(context));
|
||||
}
|
||||
catch (chaiscript::exception::eval_error& e)
|
||||
{
|
||||
throw std::runtime_error(e.pretty_print());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void start_execution()
|
||||
{
|
||||
try
|
||||
{
|
||||
this->load_scripts();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
propagate_error(e);
|
||||
}
|
||||
}
|
||||
|
||||
void stop_execution()
|
||||
{
|
||||
this->scripts_.clear();
|
||||
}
|
||||
|
||||
void run_frame()
|
||||
{
|
||||
for (const auto& script : this->scripts_)
|
||||
{
|
||||
script->get_scheduler()->run_frame();
|
||||
}
|
||||
}
|
||||
|
||||
void dispatch(game::scripting::event* event)
|
||||
{
|
||||
for (const auto& script : this->scripts_)
|
||||
{
|
||||
script->get_event_handler()->dispatch(event);
|
||||
}
|
||||
}
|
||||
|
||||
static utils::hook start_hook_;
|
||||
static utils::hook stop_hook_;
|
||||
|
||||
static void propagate_error(const std::exception& e)
|
||||
{
|
||||
printf("\n******* Script execution error *******\n");
|
||||
printf("%s\n", e.what());
|
||||
printf("**************************************\n\n");
|
||||
|
||||
scheduler::error("Script execution error\n(see console for actual details)\n", 5);
|
||||
}
|
||||
|
||||
static void start_execution_stub()
|
||||
{
|
||||
module_loader::get<scripting>()->start_execution();
|
||||
reinterpret_cast<void(*)()>(start_hook_.get_original())();
|
||||
}
|
||||
|
||||
static void stop_execution_stub()
|
||||
{
|
||||
module_loader::get<scripting>()->stop_execution();
|
||||
reinterpret_cast<void(*)()>(stop_hook_.get_original())();
|
||||
}
|
||||
|
||||
static void vm_notify_stub(const unsigned int notify_id, const unsigned short type,
|
||||
game::native::VariableValue* stack)
|
||||
{
|
||||
try
|
||||
{
|
||||
game::scripting::event e;
|
||||
e.name = game::native::SL_ConvertToString(type);
|
||||
e.entity_id = notify_id;
|
||||
|
||||
if (e.name == "touch") return; // Skip that for now
|
||||
|
||||
//printf("%X: %s\n", e.entity_id, e.name.data());
|
||||
|
||||
for (auto value = stack; value->type != game::native::SCRIPT_END; --value)
|
||||
{
|
||||
e.arguments.emplace_back(*value);
|
||||
}
|
||||
|
||||
module_loader::get<scripting>()->dispatch(&e);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
propagate_error(e);
|
||||
}
|
||||
|
||||
game::native::VM_Notify(notify_id, type, stack);
|
||||
}
|
||||
|
||||
static int frame_stub(int a1, int a2)
|
||||
{
|
||||
module_loader::get<scripting>()->run_frame();
|
||||
return game::native::G_RunFrame(a1, a2);
|
||||
}
|
||||
};
|
||||
|
||||
utils::hook scripting::start_hook_;
|
||||
utils::hook scripting::stop_hook_;
|
||||
|
||||
REGISTER_MODULE(scripting)
|
||||
|
@ -1,25 +1,25 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
|
||||
class security final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
if(game::is_mp())
|
||||
{
|
||||
utils::hook(0x4AECD4, read_p2p_auth_ticket_stub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void read_p2p_auth_ticket_stub(game::native::msg_t* msg, void* data, const int len)
|
||||
{
|
||||
if (len < 0) return;
|
||||
return game::native::MSG_ReadData(msg, data, std::min(len, 200));
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(security)
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
|
||||
class security final : public module
|
||||
{
|
||||
public:
|
||||
void post_load() override
|
||||
{
|
||||
if(game::is_mp())
|
||||
{
|
||||
utils::hook(0x4AECD4, read_p2p_auth_ticket_stub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void read_p2p_auth_ticket_stub(game::native::msg_t* msg, void* data, const int len)
|
||||
{
|
||||
if (len < 0) return;
|
||||
return game::native::MSG_ReadData(msg, data, std::min(len, 200));
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_MODULE(security)
|
||||
|
@ -1,178 +1,178 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
#include "steam/interface.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
class steam_proxy final : public module
|
||||
{
|
||||
public:
|
||||
void post_start() override
|
||||
{
|
||||
if (game::is_dedi()) return;
|
||||
|
||||
this->run_mod();
|
||||
this->load_client();
|
||||
|
||||
this->clean_up_on_error();
|
||||
}
|
||||
|
||||
void post_load() override
|
||||
{
|
||||
if (game::is_dedi()) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (game::is_sp())
|
||||
{
|
||||
this->start_mod("Open-IW5 Singleplayer", 42680);
|
||||
}
|
||||
else if (game::is_mp())
|
||||
{
|
||||
this->start_mod("Open-IW5 Multiplayer", 42690);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
printf("Steam: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
if (this->steam_client_module_)
|
||||
{
|
||||
if (this->steam_pipe_)
|
||||
{
|
||||
if (this->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_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
utils::nt::module steam_client_module_;
|
||||
|
||||
steam::interface client_engine_;
|
||||
steam::interface client_user_;
|
||||
steam::interface client_utils_;
|
||||
|
||||
void* steam_pipe_ = nullptr;
|
||||
void* global_user_ = nullptr;
|
||||
|
||||
void run_mod() const
|
||||
{
|
||||
const auto command = "-proc ";
|
||||
const char* parent_proc = strstr(GetCommandLineA(), command);
|
||||
|
||||
if (parent_proc)
|
||||
{
|
||||
const auto pid = atoi(parent_proc + strlen(command));
|
||||
const auto process_handle = OpenProcess(SYNCHRONIZE, FALSE, pid);
|
||||
if (process_handle && process_handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WaitForSingleObject(process_handle, INFINITE);
|
||||
CloseHandle(process_handle);
|
||||
}
|
||||
|
||||
module_loader::trigger_premature_shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
const auto client_engine = this->steam_client_module_
|
||||
.invoke<void*>("CreateInterface", name.data(), nullptr);
|
||||
if (client_engine) return client_engine;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void load_client()
|
||||
{
|
||||
const auto steam_path = ::steam::get_steam_install_directory();
|
||||
if (steam_path.empty()) return;
|
||||
|
||||
utils::nt::module::load(steam_path + "tier0_s.dll");
|
||||
utils::nt::module::load(steam_path + "vstdlib_s.dll");
|
||||
this->steam_client_module_ = utils::nt::module::load(steam_path + "steamclient.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_,
|
||||
"CLIENTUSER_INTERFACE_VERSION001"); // GetIClientUser
|
||||
this->client_utils_ = this->client_engine_.invoke<void*>(13, this->steam_pipe_,
|
||||
"CLIENTUTILS_INTERFACE_VERSION001"); // GetIClientUtils
|
||||
}
|
||||
|
||||
void start_mod(const std::string& title, size_t app_id)
|
||||
{
|
||||
if (!this->client_utils_ || !this->client_user_) return;
|
||||
|
||||
if (!this->client_user_.invoke<bool>("BIsSubscribedApp", app_id))
|
||||
{
|
||||
app_id = 480; // Spacewar
|
||||
}
|
||||
|
||||
this->client_utils_.invoke<void>("SetAppIDForCurrentPipe", app_id, false);
|
||||
|
||||
utils::nt::module self;
|
||||
const auto path = self.get_path();
|
||||
|
||||
char our_directory[MAX_PATH] = {0};
|
||||
GetCurrentDirectoryA(sizeof(our_directory), our_directory);
|
||||
|
||||
const std::string cmdline = utils::string::va("\"%s\" -proc %d", path.data(), GetCurrentProcessId());
|
||||
|
||||
game_id game_id;
|
||||
game_id.raw.type = 1; // k_EGameIDTypeGameMod
|
||||
game_id.raw.app_id = app_id & 0xFFFFFF;
|
||||
|
||||
const auto mod_id = "OIW5";
|
||||
game_id.raw.mod_id = *reinterpret_cast<const unsigned int*>(mod_id) | 0x80000000;
|
||||
|
||||
this->client_user_.invoke<bool>("SpawnProcess", self.get_path().data(), cmdline.data(), 0, our_directory,
|
||||
game_id.bits, title.data(), app_id, 0, 0);
|
||||
}
|
||||
|
||||
void clean_up_on_error()
|
||||
{
|
||||
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_))
|
||||
{
|
||||
scheduler::once(std::bind(&steam_proxy::clean_up_on_error, this));
|
||||
return;
|
||||
}
|
||||
|
||||
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::module{nullptr};
|
||||
}
|
||||
};
|
||||
|
||||
//REGISTER_MODULE(steam_proxy)
|
||||
#include <std_include.hpp>
|
||||
#include "loader/module_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
#include "steam/steam.hpp"
|
||||
#include "steam/interface.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
class steam_proxy final : public module
|
||||
{
|
||||
public:
|
||||
void post_start() override
|
||||
{
|
||||
if (game::is_dedi()) return;
|
||||
|
||||
this->run_mod();
|
||||
this->load_client();
|
||||
|
||||
this->clean_up_on_error();
|
||||
}
|
||||
|
||||
void post_load() override
|
||||
{
|
||||
if (game::is_dedi()) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (game::is_sp())
|
||||
{
|
||||
this->start_mod("Open-IW5 Singleplayer", 42680);
|
||||
}
|
||||
else if (game::is_mp())
|
||||
{
|
||||
this->start_mod("Open-IW5 Multiplayer", 42690);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
printf("Steam: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
if (this->steam_client_module_)
|
||||
{
|
||||
if (this->steam_pipe_)
|
||||
{
|
||||
if (this->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_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
utils::nt::module steam_client_module_;
|
||||
|
||||
steam::interface client_engine_;
|
||||
steam::interface client_user_;
|
||||
steam::interface client_utils_;
|
||||
|
||||
void* steam_pipe_ = nullptr;
|
||||
void* global_user_ = nullptr;
|
||||
|
||||
void run_mod() const
|
||||
{
|
||||
const auto command = "-proc ";
|
||||
const char* parent_proc = strstr(GetCommandLineA(), command);
|
||||
|
||||
if (parent_proc)
|
||||
{
|
||||
const auto pid = atoi(parent_proc + strlen(command));
|
||||
const auto process_handle = OpenProcess(SYNCHRONIZE, FALSE, pid);
|
||||
if (process_handle && process_handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WaitForSingleObject(process_handle, INFINITE);
|
||||
CloseHandle(process_handle);
|
||||
}
|
||||
|
||||
module_loader::trigger_premature_shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
const auto client_engine = this->steam_client_module_
|
||||
.invoke<void*>("CreateInterface", name.data(), nullptr);
|
||||
if (client_engine) return client_engine;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void load_client()
|
||||
{
|
||||
const auto steam_path = ::steam::get_steam_install_directory();
|
||||
if (steam_path.empty()) return;
|
||||
|
||||
utils::nt::module::load(steam_path + "tier0_s.dll");
|
||||
utils::nt::module::load(steam_path + "vstdlib_s.dll");
|
||||
this->steam_client_module_ = utils::nt::module::load(steam_path + "steamclient.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_,
|
||||
"CLIENTUSER_INTERFACE_VERSION001"); // GetIClientUser
|
||||
this->client_utils_ = this->client_engine_.invoke<void*>(13, this->steam_pipe_,
|
||||
"CLIENTUTILS_INTERFACE_VERSION001"); // GetIClientUtils
|
||||
}
|
||||
|
||||
void start_mod(const std::string& title, size_t app_id)
|
||||
{
|
||||
if (!this->client_utils_ || !this->client_user_) return;
|
||||
|
||||
if (!this->client_user_.invoke<bool>("BIsSubscribedApp", app_id))
|
||||
{
|
||||
app_id = 480; // Spacewar
|
||||
}
|
||||
|
||||
this->client_utils_.invoke<void>("SetAppIDForCurrentPipe", app_id, false);
|
||||
|
||||
utils::nt::module self;
|
||||
const auto path = self.get_path();
|
||||
|
||||
char our_directory[MAX_PATH] = {0};
|
||||
GetCurrentDirectoryA(sizeof(our_directory), our_directory);
|
||||
|
||||
const std::string cmdline = utils::string::va("\"%s\" -proc %d", path.data(), GetCurrentProcessId());
|
||||
|
||||
game_id game_id;
|
||||
game_id.raw.type = 1; // k_EGameIDTypeGameMod
|
||||
game_id.raw.app_id = app_id & 0xFFFFFF;
|
||||
|
||||
const auto mod_id = "OIW5";
|
||||
game_id.raw.mod_id = *reinterpret_cast<const unsigned int*>(mod_id) | 0x80000000;
|
||||
|
||||
this->client_user_.invoke<bool>("SpawnProcess", self.get_path().data(), cmdline.data(), 0, our_directory,
|
||||
game_id.bits, title.data(), app_id, 0, 0);
|
||||
}
|
||||
|
||||
void clean_up_on_error()
|
||||
{
|
||||
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_))
|
||||
{
|
||||
scheduler::once(std::bind(&steam_proxy::clean_up_on_error, this));
|
||||
return;
|
||||
}
|
||||
|
||||
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::module{nullptr};
|
||||
}
|
||||
};
|
||||
|
||||
//REGISTER_MODULE(steam_proxy)
|
||||
|
@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#define BINARY_SP 300
|
||||
#define BINARY_MP 301
|
||||
|
||||
#define DW_HEATMAP 302
|
||||
#define DW_MOTD 303
|
||||
#define DW_IMG 304
|
||||
#define DW_WAD 305
|
||||
#define DW_PLAYLIST 306
|
||||
#define DW_CONFIG 307
|
||||
#define DW_IOTD_TXT 308
|
||||
#define DW_IOTD_IMG 309
|
||||
|
||||
#define MENU_MAIN 310
|
||||
#define MENU_SETTINGS 311
|
||||
#pragma once
|
||||
|
||||
#define BINARY_SP 300
|
||||
#define BINARY_MP 301
|
||||
|
||||
#define DW_HEATMAP 302
|
||||
#define DW_MOTD 303
|
||||
#define DW_IMG 304
|
||||
#define DW_WAD 305
|
||||
#define DW_PLAYLIST 306
|
||||
#define DW_CONFIG 307
|
||||
#define DW_IOTD_TXT 308
|
||||
#define DW_IOTD_IMG 309
|
||||
|
||||
#define MENU_MAIN 310
|
||||
#define MENU_SETTINGS 311
|
||||
|
234
src/resource.rc
234
src/resource.rc
@ -1,117 +1,117 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#pragma code_page(65001)
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "windows.h"
|
||||
#include "resource.hpp"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""windows.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,0
|
||||
PRODUCTVERSION 1,0,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "momo5502"
|
||||
VALUE "FileDescription", "Open-IW5"
|
||||
VALUE "FileVersion", "1.0.0.0"
|
||||
VALUE "InternalName", "Open-IW5"
|
||||
VALUE "LegalCopyright", "All rights reserved."
|
||||
VALUE "OriginalFilename", "open-iw5.exe"
|
||||
VALUE "ProductName", "open-iw5"
|
||||
VALUE "ProductVersion", "1.0.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Binary Data
|
||||
//
|
||||
|
||||
102 ICON "resources/icon.ico"
|
||||
|
||||
BINARY_SP RCDATA "resources/iw5sp.exe.diff"
|
||||
BINARY_MP RCDATA "resources/iw5mp.exe.diff"
|
||||
|
||||
DW_HEATMAP RCDATA "resources/dw/heatmap.raw"
|
||||
DW_MOTD RCDATA "resources/dw/motd-english.txt"
|
||||
DW_IMG RCDATA "resources/dw/online_mp.img"
|
||||
DW_WAD RCDATA "resources/dw/online_tu14_mp_english.wad"
|
||||
DW_PLAYLIST RCDATA "resources/dw/playlists.aggr"
|
||||
DW_CONFIG RCDATA "resources/dw/social_tu1.cfg"
|
||||
DW_IOTD_TXT RCDATA "resources/dw/iotd-english.txt"
|
||||
DW_IOTD_IMG RCDATA "resources/dw/iotd-english.jpg"
|
||||
|
||||
MENU_MAIN RCDATA "resources/main.html"
|
||||
MENU_SETTINGS RCDATA "resources/settings.html"
|
||||
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#pragma code_page(65001)
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "windows.h"
|
||||
#include "resource.hpp"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""windows.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,0
|
||||
PRODUCTVERSION 1,0,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "momo5502"
|
||||
VALUE "FileDescription", "Open-IW5"
|
||||
VALUE "FileVersion", "1.0.0.0"
|
||||
VALUE "InternalName", "Open-IW5"
|
||||
VALUE "LegalCopyright", "All rights reserved."
|
||||
VALUE "OriginalFilename", "open-iw5.exe"
|
||||
VALUE "ProductName", "open-iw5"
|
||||
VALUE "ProductVersion", "1.0.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Binary Data
|
||||
//
|
||||
|
||||
102 ICON "resources/icon.ico"
|
||||
|
||||
BINARY_SP RCDATA "resources/iw5sp.exe.diff"
|
||||
BINARY_MP RCDATA "resources/iw5mp.exe.diff"
|
||||
|
||||
DW_HEATMAP RCDATA "resources/dw/heatmap.raw"
|
||||
DW_MOTD RCDATA "resources/dw/motd-english.txt"
|
||||
DW_IMG RCDATA "resources/dw/online_mp.img"
|
||||
DW_WAD RCDATA "resources/dw/online_tu14_mp_english.wad"
|
||||
DW_PLAYLIST RCDATA "resources/dw/playlists.aggr"
|
||||
DW_CONFIG RCDATA "resources/dw/social_tu1.cfg"
|
||||
DW_IOTD_TXT RCDATA "resources/dw/iotd-english.txt"
|
||||
DW_IOTD_IMG RCDATA "resources/dw/iotd-english.jpg"
|
||||
|
||||
MENU_MAIN RCDATA "resources/main.html"
|
||||
MENU_SETTINGS RCDATA "resources/settings.html"
|
||||
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,44 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
||||
<title>Open-IW5 Settings</title>
|
||||
|
||||
<style>
|
||||
* {
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
background-color: #2D2D2D;
|
||||
color: white;
|
||||
|
||||
font-family: "Segoe UI Light", "Segoe UI", "Lucida Sans", Arial, sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: lighter;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="content">
|
||||
<h1>No settings, yet!</h1>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
||||
<title>Open-IW5 Settings</title>
|
||||
|
||||
<style>
|
||||
* {
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
background-color: #2D2D2D;
|
||||
color: white;
|
||||
|
||||
font-family: "Segoe UI Light", "Segoe UI", "Lucida Sans", Arial, sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: lighter;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="content">
|
||||
<h1>No settings, yet!</h1>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,143 +1,143 @@
|
||||
#include <std_include.hpp>
|
||||
#include "steam/steam.hpp"
|
||||
#include "module/dw.hpp"
|
||||
|
||||
namespace steam
|
||||
{
|
||||
std::string auth_ticket;
|
||||
|
||||
int user::GetHSteamUser()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool user::LoggedOn()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
steam_id user::GetSteamID()
|
||||
{
|
||||
steam_id id;
|
||||
id.bits = 0x110000100000000 | (0x1377 & ~0x80000000);
|
||||
return id;
|
||||
}
|
||||
|
||||
int user::InitiateGameConnection(void* pAuthBlob, int cbMaxAuthBlob, steam_id steamIDGameServer,
|
||||
unsigned int unIPServer, unsigned short usPortServer, bool bSecure)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void user::TerminateGameConnection(unsigned int unIPServer, unsigned short usPortServer)
|
||||
{
|
||||
}
|
||||
|
||||
void user::TrackAppUsageEvent(steam_id gameID, int eAppUsageEvent, const char* pchExtraInfo)
|
||||
{
|
||||
}
|
||||
|
||||
bool user::GetUserDataFolder(char* pchBuffer, int cubBuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void user::StartVoiceRecording()
|
||||
{
|
||||
}
|
||||
|
||||
void user::StopVoiceRecording()
|
||||
{
|
||||
}
|
||||
|
||||
int user::GetAvailableVoice(unsigned int* pcbCompressed, unsigned int* pcbUncompressed,
|
||||
unsigned int nUncompressedVoiceDesiredSampleRate)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user::GetVoice(bool bWantCompressed, void* pDestBuffer, unsigned int cbDestBufferSize,
|
||||
unsigned int* nBytesWritten, bool bWantUncompressed, void* pUncompressedDestBuffer,
|
||||
unsigned int cbUncompressedDestBufferSize, unsigned int* nUncompressBytesWritten,
|
||||
unsigned int nUncompressedVoiceDesiredSampleRate)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user::DecompressVoice(void* pCompressed, unsigned int cbCompressed, void* pDestBuffer,
|
||||
unsigned int cbDestBufferSize, unsigned int* nBytesWritten)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int user::GetVoiceOptimalSampleRate()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int user::GetAuthSessionTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user::BeginAuthSession(const void* pAuthTicket, int cbAuthTicket, steam_id steamID)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void user::EndAuthSession(steam_id steamID)
|
||||
{
|
||||
}
|
||||
|
||||
void user::CancelAuthTicket(unsigned int hAuthTicket)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int user::UserHasLicenseForApp(steam_id steamID, unsigned int appID)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool user::BIsBehindNAT()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void user::AdvertiseGame(steam_id steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned __int64 user::RequestEncryptedAppTicket(void* pUserData, int cbUserData)
|
||||
{
|
||||
// Generate the authentication ticket
|
||||
const auto id = this->GetSteamID();
|
||||
|
||||
auth_ticket = "Open-IW5";
|
||||
auth_ticket.resize(32);
|
||||
auth_ticket.append(reinterpret_cast<char*>(pUserData), cbUserData);
|
||||
auth_ticket.append(reinterpret_cast<const char*>(&id.bits), sizeof(id.bits));
|
||||
|
||||
// Create the call response
|
||||
const auto result = callbacks::register_call();
|
||||
auto retvals = static_cast<encrypted_app_ticket_response*>(calloc(1, sizeof(encrypted_app_ticket_response)));
|
||||
//::Utils::Memory::AllocateArray<EncryptedAppTicketResponse>();
|
||||
retvals->m_e_result = 1;
|
||||
|
||||
// Return the call response
|
||||
callbacks::return_call(retvals, sizeof(encrypted_app_ticket_response),
|
||||
encrypted_app_ticket_response::callback_id, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool user::GetEncryptedAppTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket)
|
||||
{
|
||||
if (cbMaxTicket < 0 || auth_ticket.empty()) return false;
|
||||
|
||||
const auto size = std::min(size_t(cbMaxTicket), auth_ticket.size());
|
||||
std::memcpy(pTicket, auth_ticket.data(), size);
|
||||
*pcbTicket = size;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "steam/steam.hpp"
|
||||
#include "module/dw.hpp"
|
||||
|
||||
namespace steam
|
||||
{
|
||||
std::string auth_ticket;
|
||||
|
||||
int user::GetHSteamUser()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool user::LoggedOn()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
steam_id user::GetSteamID()
|
||||
{
|
||||
steam_id id;
|
||||
id.bits = 0x110000100000000 | (0x1377 & ~0x80000000);
|
||||
return id;
|
||||
}
|
||||
|
||||
int user::InitiateGameConnection(void* pAuthBlob, int cbMaxAuthBlob, steam_id steamIDGameServer,
|
||||
unsigned int unIPServer, unsigned short usPortServer, bool bSecure)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void user::TerminateGameConnection(unsigned int unIPServer, unsigned short usPortServer)
|
||||
{
|
||||
}
|
||||
|
||||
void user::TrackAppUsageEvent(steam_id gameID, int eAppUsageEvent, const char* pchExtraInfo)
|
||||
{
|
||||
}
|
||||
|
||||
bool user::GetUserDataFolder(char* pchBuffer, int cubBuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void user::StartVoiceRecording()
|
||||
{
|
||||
}
|
||||
|
||||
void user::StopVoiceRecording()
|
||||
{
|
||||
}
|
||||
|
||||
int user::GetAvailableVoice(unsigned int* pcbCompressed, unsigned int* pcbUncompressed,
|
||||
unsigned int nUncompressedVoiceDesiredSampleRate)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user::GetVoice(bool bWantCompressed, void* pDestBuffer, unsigned int cbDestBufferSize,
|
||||
unsigned int* nBytesWritten, bool bWantUncompressed, void* pUncompressedDestBuffer,
|
||||
unsigned int cbUncompressedDestBufferSize, unsigned int* nUncompressBytesWritten,
|
||||
unsigned int nUncompressedVoiceDesiredSampleRate)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user::DecompressVoice(void* pCompressed, unsigned int cbCompressed, void* pDestBuffer,
|
||||
unsigned int cbDestBufferSize, unsigned int* nBytesWritten)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int user::GetVoiceOptimalSampleRate()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int user::GetAuthSessionTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user::BeginAuthSession(const void* pAuthTicket, int cbAuthTicket, steam_id steamID)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void user::EndAuthSession(steam_id steamID)
|
||||
{
|
||||
}
|
||||
|
||||
void user::CancelAuthTicket(unsigned int hAuthTicket)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int user::UserHasLicenseForApp(steam_id steamID, unsigned int appID)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool user::BIsBehindNAT()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void user::AdvertiseGame(steam_id steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned __int64 user::RequestEncryptedAppTicket(void* pUserData, int cbUserData)
|
||||
{
|
||||
// Generate the authentication ticket
|
||||
const auto id = this->GetSteamID();
|
||||
|
||||
auth_ticket = "Open-IW5";
|
||||
auth_ticket.resize(32);
|
||||
auth_ticket.append(reinterpret_cast<char*>(pUserData), cbUserData);
|
||||
auth_ticket.append(reinterpret_cast<const char*>(&id.bits), sizeof(id.bits));
|
||||
|
||||
// Create the call response
|
||||
const auto result = callbacks::register_call();
|
||||
auto retvals = static_cast<encrypted_app_ticket_response*>(calloc(1, sizeof(encrypted_app_ticket_response)));
|
||||
//::Utils::Memory::AllocateArray<EncryptedAppTicketResponse>();
|
||||
retvals->m_e_result = 1;
|
||||
|
||||
// Return the call response
|
||||
callbacks::return_call(retvals, sizeof(encrypted_app_ticket_response),
|
||||
encrypted_app_ticket_response::callback_id, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool user::GetEncryptedAppTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket)
|
||||
{
|
||||
if (cbMaxTicket < 0 || auth_ticket.empty()) return false;
|
||||
|
||||
const auto size = std::min(size_t(cbMaxTicket), auth_ticket.size());
|
||||
std::memcpy(pTicket, auth_ticket.data(), size);
|
||||
*pcbTicket = size;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user