Fix stuff

This commit is contained in:
momo5502 2019-09-24 10:30:08 +02:00
parent 0fb12bdc32
commit fbfdc30e25
48 changed files with 3950 additions and 3950 deletions

View File

@ -1,3 +1,3 @@
@echo off
git submodule update --init --recursive
tools\premake5 %* vs2017
@echo off
git submodule update --init --recursive
tools\premake5 %* vs2019

View File

@ -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()

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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_;
};

View File

@ -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, &params);
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, &params);
return S_OK;
}

View File

@ -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;
};

View File

@ -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 = &params->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 = &params->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);
}

View File

@ -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_;
};

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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));
}

View File

@ -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);
};

View File

@ -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_;
}

View File

@ -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();
};

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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++;
}
}

View File

@ -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;
};

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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.