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 @echo off
git submodule update --init --recursive git submodule update --init --recursive
tools\premake5 %* vs2017 tools\premake5 %* vs2019

View File

@ -1,131 +1,131 @@
dependencies = { dependencies = {
basePath = "./deps" basePath = "./deps"
} }
function dependencies.load() function dependencies.load()
dir = path.join(dependencies.basePath, "premake/*.lua") dir = path.join(dependencies.basePath, "premake/*.lua")
deps = os.matchfiles(dir) deps = os.matchfiles(dir)
for i, dep in pairs(deps) do for i, dep in pairs(deps) do
dep = dep:gsub(".lua", "") dep = dep:gsub(".lua", "")
require(dep) require(dep)
end end
end end
function dependencies.imports() function dependencies.imports()
for i, proj in pairs(dependencies) do for i, proj in pairs(dependencies) do
if type(i) == 'number' then if type(i) == 'number' then
proj.import() proj.import()
end end
end end
end end
function dependencies.projects() function dependencies.projects()
for i, proj in pairs(dependencies) do for i, proj in pairs(dependencies) do
if type(i) == 'number' then if type(i) == 'number' then
proj.project() proj.project()
end end
end end
end end
newoption { newoption {
trigger = "copy-to", trigger = "copy-to",
description = "Optional, copy the EXE to a custom folder after build, define the path here if wanted.", description = "Optional, copy the EXE to a custom folder after build, define the path here if wanted.",
value = "PATH" value = "PATH"
} }
dependencies.load() dependencies.load()
workspace "open-iw5" workspace "open-iw5"
startproject "open-iw5" startproject "open-iw5"
location "./build" location "./build"
objdir "%{wks.location}/obj" objdir "%{wks.location}/obj"
targetdir "%{wks.location}/bin/%{cfg.platform}/%{cfg.buildcfg}" targetdir "%{wks.location}/bin/%{cfg.platform}/%{cfg.buildcfg}"
configurations { configurations {
"Debug", "Debug",
"Release", "Release",
} }
architecture "x32" architecture "x32"
platforms "x32" platforms "x32"
buildoptions "/std:c++latest" buildoptions "/std:c++latest"
systemversion "latest" systemversion "latest"
symbols "On" symbols "On"
staticruntime "On" staticruntime "On"
editandcontinue "Off" editandcontinue "Off"
warnings "Extra" warnings "Extra"
characterset "ASCII" characterset "ASCII"
toolset "v142" toolset "v142"
flags { flags {
"NoIncrementalLink", "NoIncrementalLink",
"NoMinimalRebuild", "NoMinimalRebuild",
"MultiProcessorCompile", "MultiProcessorCompile",
"No64BitChecks" "No64BitChecks"
} }
configuration "windows" configuration "windows"
defines { defines {
"_WINDOWS", "_WINDOWS",
"WIN32", "WIN32",
} }
configuration "Release" configuration "Release"
optimize "Full" optimize "Full"
defines { defines {
"NDEBUG", "NDEBUG",
} }
flags { flags {
"FatalCompileWarnings", "FatalCompileWarnings",
} }
configuration "Debug" configuration "Debug"
optimize "Debug" optimize "Debug"
defines { defines {
"DEBUG", "DEBUG",
"_DEBUG", "_DEBUG",
} }
configuration {} configuration {}
project "open-iw5" project "open-iw5"
kind "ConsoleApp" kind "ConsoleApp"
language "C++" language "C++"
pchheader "std_include.hpp" pchheader "std_include.hpp"
pchsource "src/std_include.cpp" pchsource "src/std_include.cpp"
linkoptions "/IGNORE:4254 /DYNAMICBASE:NO /SAFESEH:NO /LARGEADDRESSAWARE" linkoptions "/IGNORE:4254 /DYNAMICBASE:NO /SAFESEH:NO /LARGEADDRESSAWARE"
linkoptions "/LAST:.main" linkoptions "/LAST:.main"
files { files {
"./src/**.rc", "./src/**.rc",
"./src/**.hpp", "./src/**.hpp",
"./src/**.cpp", "./src/**.cpp",
"./src/resources/**.*" "./src/resources/**.*"
} }
includedirs { includedirs {
"./src" "./src"
} }
resincludedirs { resincludedirs {
"$(ProjectDir)src" "$(ProjectDir)src"
} }
if _OPTIONS["copy-to"] then if _OPTIONS["copy-to"] then
postbuildcommands { postbuildcommands {
"copy /y \"$(TargetDir)*.exe\" \"" .. _OPTIONS["copy-to"] .. "\"" "copy /y \"$(TargetDir)*.exe\" \"" .. _OPTIONS["copy-to"] .. "\""
} }
end end
dependencies.imports() dependencies.imports()
group "Dependencies" group "Dependencies"
dependencies.projects() dependencies.projects()

View File

@ -1,61 +1,61 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "bdDediAuth.hpp" #include "bdDediAuth.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "steam/steam.hpp" #include "steam/steam.hpp"
#include "utils/cryptography.hpp" #include "utils/cryptography.hpp"
namespace demonware namespace demonware
{ {
void bdDediAuth::call_service(i_server* server, const std::string& data) void bdDediAuth::call_service(i_server* server, const std::string& data)
{ {
bit_buffer buffer(data); bit_buffer buffer(data);
bool more_data; bool more_data;
buffer.set_use_data_types(false); buffer.set_use_data_types(false);
buffer.read_bool(&more_data); buffer.read_bool(&more_data);
buffer.set_use_data_types(true); buffer.set_use_data_types(true);
uint32_t seed, title_id, ticket_size; uint32_t seed, title_id, ticket_size;
buffer.read_uint32(&seed); buffer.read_uint32(&seed);
buffer.read_uint32(&title_id); buffer.read_uint32(&title_id);
uint8_t ticket[1024]; uint8_t ticket[1024];
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket); buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
game::native::bdAuthTicket auth_ticket{}; game::native::bdAuthTicket auth_ticket{};
std::memset(&auth_ticket, 0xA, sizeof auth_ticket); std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
auth_ticket.m_magicNumber = 0x0EFBDADDE; auth_ticket.m_magicNumber = 0x0EFBDADDE;
auth_ticket.m_type = 0; auth_ticket.m_type = 0;
auth_ticket.m_titleID = title_id; auth_ticket.m_titleID = title_id;
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits; auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
auth_ticket.m_licenseID = 4; auth_ticket.m_licenseID = 4;
auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY); auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY);
strcpy_s(auth_ticket.m_username, "Open-IW5 Server"); strcpy_s(auth_ticket.m_username, "Open-IW5 Server");
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24); std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr)); auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
uint8_t lsg_ticket[128]; uint8_t lsg_ticket[128];
ZeroMemory(&lsg_ticket, sizeof lsg_ticket); ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
std::memcpy(lsg_ticket, key.data(), 24); std::memcpy(lsg_ticket, key.data(), 24);
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4)); 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); const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
auto enc_ticket = utils::cryptography::des3::encrypt( auto enc_ticket = utils::cryptography::des3::encrypt(
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key); std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
bit_buffer response; bit_buffer response;
response.set_use_data_types(false); response.set_use_data_types(false);
response.write_bool(false); response.write_bool(false);
response.write_uint32(700); response.write_uint32(700);
response.write_uint32(seed); response.write_uint32(seed);
response.write_bytes(enc_ticket.size(), enc_ticket.data()); response.write_bytes(enc_ticket.size(), enc_ticket.data());
response.write_bytes(sizeof(lsg_ticket), lsg_ticket); response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
auto reply = server->create_message(29); auto reply = server->create_message(29);
reply->send(&response, false); reply->send(&response, false);
} }
} }

View File

@ -1,71 +1,71 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "bdDediRSAAuth.hpp" #include "bdDediRSAAuth.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "steam/steam.hpp" #include "steam/steam.hpp"
#include "utils/cryptography.hpp" #include "utils/cryptography.hpp"
namespace demonware namespace demonware
{ {
void bdDediRSAAuth::call_service(i_server* server, const std::string& data) void bdDediRSAAuth::call_service(i_server* server, const std::string& data)
{ {
bit_buffer buffer(data); bit_buffer buffer(data);
bool more_data; bool more_data;
buffer.set_use_data_types(false); buffer.set_use_data_types(false);
buffer.read_bool(&more_data); buffer.read_bool(&more_data);
buffer.set_use_data_types(true); buffer.set_use_data_types(true);
uint32_t seed, title_id, ticket_size; uint32_t seed, title_id, ticket_size;
buffer.read_uint32(&seed); buffer.read_uint32(&seed);
buffer.read_uint32(&title_id); buffer.read_uint32(&title_id);
unsigned char rsakey[140]; unsigned char rsakey[140];
buffer.read_bytes(sizeof(rsakey), rsakey); buffer.read_bytes(sizeof(rsakey), rsakey);
uint8_t ticket[1024]; uint8_t ticket[1024];
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket); buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
game::native::bdAuthTicket auth_ticket{}; game::native::bdAuthTicket auth_ticket{};
std::memset(&auth_ticket, 0xA, sizeof auth_ticket); std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
auth_ticket.m_magicNumber = 0x0EFBDADDE; auth_ticket.m_magicNumber = 0x0EFBDADDE;
auth_ticket.m_type = 0; auth_ticket.m_type = 0;
auth_ticket.m_titleID = title_id; auth_ticket.m_titleID = title_id;
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits; auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY); auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY);
strcpy_s(auth_ticket.m_username, "Open-IW5 Server"); strcpy_s(auth_ticket.m_username, "Open-IW5 Server");
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24); std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr)); auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
uint8_t lsg_ticket[128]; uint8_t lsg_ticket[128];
ZeroMemory(&lsg_ticket, sizeof lsg_ticket); ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
std::memcpy(lsg_ticket, key.data(), 24); std::memcpy(lsg_ticket, key.data(), 24);
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4)); 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); const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
auto enc_ticket = utils::cryptography::des3::encrypt( auto enc_ticket = utils::cryptography::des3::encrypt(
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key); std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
register_hash(&sha1_desc); register_hash(&sha1_desc);
register_prng(&yarrow_desc); register_prng(&yarrow_desc);
std::string encrypted_key = utils::cryptography::rsa::encrypt(std::string(SERVER_CD_KEY, 24), std::string encrypted_key = utils::cryptography::rsa::encrypt(std::string(SERVER_CD_KEY, 24),
std::string("DW-RSAENC", 10), std::string("DW-RSAENC", 10),
std::string(PCHAR(rsakey), sizeof(rsakey))); std::string(PCHAR(rsakey), sizeof(rsakey)));
bit_buffer response; bit_buffer response;
response.set_use_data_types(false); response.set_use_data_types(false);
response.write_bool(false); response.write_bool(false);
response.write_uint32(700); response.write_uint32(700);
response.write_uint32(seed); response.write_uint32(seed);
response.write_bytes(enc_ticket.size(), enc_ticket.data()); response.write_bytes(enc_ticket.size(), enc_ticket.data());
response.write_bytes(sizeof(lsg_ticket), lsg_ticket); response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
response.write_bytes(encrypted_key.size(), encrypted_key.data()); response.write_bytes(encrypted_key.size(), encrypted_key.data());
auto reply = server->create_message(29); auto reply = server->create_message(29);
reply->send(&response, false); reply->send(&response, false);
} }
} }

View File

@ -1,61 +1,61 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "bdSteamAuth.hpp" #include "bdSteamAuth.hpp"
#include "game/structs.hpp" #include "game/structs.hpp"
#include "steam/steam.hpp" #include "steam/steam.hpp"
#include "utils/cryptography.hpp" #include "utils/cryptography.hpp"
namespace demonware namespace demonware
{ {
void bdSteamAuth::call_service(i_server* server, const std::string& data) void bdSteamAuth::call_service(i_server* server, const std::string& data)
{ {
bit_buffer buffer(data); bit_buffer buffer(data);
bool more_data; bool more_data;
buffer.set_use_data_types(false); buffer.set_use_data_types(false);
buffer.read_bool(&more_data); buffer.read_bool(&more_data);
buffer.set_use_data_types(true); buffer.set_use_data_types(true);
uint32_t seed, title_id, ticket_size; uint32_t seed, title_id, ticket_size;
buffer.read_uint32(&seed); buffer.read_uint32(&seed);
buffer.read_uint32(&title_id); buffer.read_uint32(&title_id);
buffer.read_uint32(&ticket_size); buffer.read_uint32(&ticket_size);
uint8_t ticket[1024]; uint8_t ticket[1024];
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket); buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
game::native::bdAuthTicket auth_ticket{}; game::native::bdAuthTicket auth_ticket{};
std::memset(&auth_ticket, 0xA, sizeof auth_ticket); std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
auth_ticket.m_magicNumber = 0x0EFBDADDE; auth_ticket.m_magicNumber = 0x0EFBDADDE;
auth_ticket.m_type = 0; auth_ticket.m_type = 0;
auth_ticket.m_titleID = title_id; auth_ticket.m_titleID = title_id;
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits; auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
auto key = utils::cryptography::tiger::compute("Open-IW5"); auto key = utils::cryptography::tiger::compute("Open-IW5");
strcpy_s(auth_ticket.m_username, "Open-IW5 User"); strcpy_s(auth_ticket.m_username, "Open-IW5 User");
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24); std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr)); auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
uint8_t lsg_ticket[128]; uint8_t lsg_ticket[128];
ZeroMemory(&lsg_ticket, sizeof lsg_ticket); ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
std::memcpy(lsg_ticket, key.data(), 24); std::memcpy(lsg_ticket, key.data(), 24);
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4)); 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); const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
auto enc_ticket = utils::cryptography::des3::encrypt( auto enc_ticket = utils::cryptography::des3::encrypt(
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key); std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
bit_buffer response; bit_buffer response;
response.set_use_data_types(false); response.set_use_data_types(false);
response.write_bool(false); response.write_bool(false);
response.write_uint32(700); response.write_uint32(700);
response.write_uint32(seed); response.write_uint32(seed);
response.write_bytes(enc_ticket.size(), enc_ticket.data()); response.write_bytes(enc_ticket.size(), enc_ticket.data());
response.write_bytes(sizeof(lsg_ticket), lsg_ticket); response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
auto reply = server->create_message(29); auto reply = server->create_message(29);
reply->send(&response, false); reply->send(&response, false);
} }
} }

View File

@ -1,374 +1,374 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "game.hpp" #include "game.hpp"
namespace game namespace game
{ {
namespace native namespace native
{ {
Cmd_AddCommand_t Cmd_AddCommand; Cmd_AddCommand_t Cmd_AddCommand;
Com_Error_t Com_Error; Com_Error_t Com_Error;
DB_LoadXAssets_t DB_LoadXAssets; DB_LoadXAssets_t DB_LoadXAssets;
Dvar_SetFromStringByName_t Dvar_SetFromStringByName; Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
G_RunFrame_t G_RunFrame; G_RunFrame_t G_RunFrame;
MSG_ReadData_t MSG_ReadData; MSG_ReadData_t MSG_ReadData;
MT_AllocIndex_t MT_AllocIndex; MT_AllocIndex_t MT_AllocIndex;
RemoveRefToValue_t RemoveRefToValue; RemoveRefToValue_t RemoveRefToValue;
SL_GetStringOfSize_t SL_GetStringOfSize; SL_GetStringOfSize_t SL_GetStringOfSize;
Sys_ShowConsole_t Sys_ShowConsole; Sys_ShowConsole_t Sys_ShowConsole;
VM_Notify_t VM_Notify; VM_Notify_t VM_Notify;
decltype(longjmp)* _longjmp; decltype(longjmp)* _longjmp;
int* cmd_args; int* cmd_args;
int* cmd_argc; int* cmd_argc;
const char*** cmd_argv; const char*** cmd_argv;
short* scrVarGlob; short* scrVarGlob;
char** scrMemTreePub; char** scrMemTreePub;
char* scrMemTreeGlob; char* scrMemTreeGlob;
scrVmPub_t* scr_VmPub; scrVmPub_t* scr_VmPub;
scr_call_t* scr_instanceFunctions; scr_call_t* scr_instanceFunctions;
scr_call_t* scr_globalFunctions; scr_call_t* scr_globalFunctions;
unsigned int* levelEntityId; unsigned int* levelEntityId;
int* g_script_error_level; int* g_script_error_level;
jmp_buf* g_script_error; jmp_buf* g_script_error;
scr_classStruct_t* g_classMap; scr_classStruct_t* g_classMap;
void AddRefToValue(VariableValue* value) void AddRefToValue(VariableValue* value)
{ {
if (value->type == SCRIPT_OBJECT) if (value->type == SCRIPT_OBJECT)
{ {
++scrVarGlob[4 * value->u.entityId]; ++scrVarGlob[4 * value->u.entityId];
} }
else if ((value->type & ~1) == SCRIPT_STRING) else if ((value->type & ~1) == SCRIPT_STRING)
{ {
static const auto size = is_sp() ? 16 : 12; static const auto size = is_sp() ? 16 : 12;
const auto ref_count = reinterpret_cast<unsigned volatile *>(*scrMemTreePub + size * value const auto ref_count = reinterpret_cast<unsigned volatile *>(*scrMemTreePub + size * value
->u.stringValue); ->u.stringValue);
InterlockedIncrement(ref_count); InterlockedIncrement(ref_count);
} }
else if (value->type == SCRIPT_VECTOR) else if (value->type == SCRIPT_VECTOR)
{ {
if (!*PBYTE(value->u.vectorValue - 1)) if (!*PBYTE(value->u.vectorValue - 1))
{ {
++*PWORD(value->u.vectorValue - 4); ++*PWORD(value->u.vectorValue - 4);
} }
} }
} }
__declspec(naked) unsigned int conbuf_append_text_dedicated(const char* message) __declspec(naked) unsigned int conbuf_append_text_dedicated(const char* message)
{ {
static DWORD func = 0x53C790; static DWORD func = 0x53C790;
__asm __asm
{ {
mov ecx, message mov ecx, message
call func call func
retn retn
} }
} }
void Conbuf_AppendText(const char* message) void Conbuf_AppendText(const char* message)
{ {
if(is_dedi()) if(is_dedi())
{ {
conbuf_append_text_dedicated(message); conbuf_append_text_dedicated(message);
} }
else else
{ {
reinterpret_cast<void(*)(const char*)>(SELECT_VALUE(0x4C84E0, 0x5CF610, 0))(message); reinterpret_cast<void(*)(const char*)>(SELECT_VALUE(0x4C84E0, 0x5CF610, 0))(message);
} }
} }
__declspec(naked) unsigned int find_variable_dedicated(unsigned int parentId, unsigned int name) __declspec(naked) unsigned int find_variable_dedicated(unsigned int parentId, unsigned int name)
{ {
static DWORD func = 0x4E7ED0; static DWORD func = 0x4E7ED0;
__asm __asm
{ {
mov eax, name mov eax, name
mov ecx, parentId mov ecx, parentId
call func call func
retn retn
} }
} }
unsigned int FindVariable(const unsigned int parentId, const unsigned int name) unsigned int FindVariable(const unsigned int parentId, const unsigned int name)
{ {
if (is_dedi()) if (is_dedi())
{ {
return find_variable_dedicated(parentId, name); return find_variable_dedicated(parentId, name);
} }
else else
{ {
return reinterpret_cast<unsigned int(*)(unsigned int, unsigned int)> // return reinterpret_cast<unsigned int(*)(unsigned int, unsigned int)> //
(SELECT_VALUE(0x4C4E70, 0x5651F0, 0x0))(parentId, name); (SELECT_VALUE(0x4C4E70, 0x5651F0, 0x0))(parentId, name);
} }
} }
__declspec(naked) VariableValue get_entity_field_value_dedicated(unsigned int classnum, int entnum, int _offset) __declspec(naked) VariableValue get_entity_field_value_dedicated(unsigned int classnum, int entnum, int _offset)
{ {
static DWORD func = 0x4F1400; static DWORD func = 0x4F1400;
__asm __asm
{ {
push _offset push _offset
push entnum push entnum
mov ecx, classnum mov ecx, classnum
call func call func
add esp, 8h add esp, 8h
retn retn
} }
} }
VariableValue GetEntityFieldValue(const unsigned int classnum, const int entnum, const int offset) VariableValue GetEntityFieldValue(const unsigned int classnum, const int entnum, const int offset)
{ {
if (is_dedi()) if (is_dedi())
{ {
return get_entity_field_value_dedicated(classnum, entnum, offset); return get_entity_field_value_dedicated(classnum, entnum, offset);
} }
else else
{ {
return reinterpret_cast<VariableValue(*)(unsigned int, int, int)> // return reinterpret_cast<VariableValue(*)(unsigned int, int, int)> //
(SELECT_VALUE(0x530E30, 0x56AF20, 0x0))(classnum, entnum, offset); (SELECT_VALUE(0x530E30, 0x56AF20, 0x0))(classnum, entnum, offset);
} }
} }
void* MT_Alloc(const int numBytes, const int type) void* MT_Alloc(const int numBytes, const int type)
{ {
return scrMemTreeGlob + 12 * size_t(MT_AllocIndex(numBytes, type)); return scrMemTreeGlob + 12 * size_t(MT_AllocIndex(numBytes, type));
} }
const float* Scr_AllocVector(const float* v) const float* Scr_AllocVector(const float* v)
{ {
const auto mem = static_cast<DWORD*>(MT_Alloc(16, 2)); const auto mem = static_cast<DWORD*>(MT_Alloc(16, 2));
*mem = 0; *mem = 0;
const auto array = reinterpret_cast<float*>(mem + 1); const auto array = reinterpret_cast<float*>(mem + 1);
array[0] = v[0]; array[0] = v[0];
array[1] = v[1]; array[1] = v[1];
array[2] = v[2]; array[2] = v[2];
return array; return array;
} }
void Scr_ClearOutParams() void Scr_ClearOutParams()
{ {
const auto num_params = scr_VmPub->outparamcount; const auto num_params = scr_VmPub->outparamcount;
for (unsigned int i = num_params; i > 0; --i) for (unsigned int i = num_params; i > 0; --i)
{ {
const auto value = scr_VmPub->top[i - 1]; const auto value = scr_VmPub->top[i - 1];
RemoveRefToValue(value.type, value.u); RemoveRefToValue(value.type, value.u);
} }
scr_VmPub->top -= num_params; scr_VmPub->top -= num_params;
} }
scr_entref_t Scr_GetEntityIdRef(const unsigned int id) scr_entref_t Scr_GetEntityIdRef(const unsigned int id)
{ {
static auto class_array = reinterpret_cast<DWORD*>(SELECT_VALUE(0x19AFC84, 0x1E72184, 0x1D3C804)); static auto class_array = reinterpret_cast<DWORD*>(SELECT_VALUE(0x19AFC84, 0x1E72184, 0x1D3C804));
static auto ent_array = reinterpret_cast<WORD*>(SELECT_VALUE(0x19AFC82, 0x1E72182, 0x1D3C802)); static auto ent_array = reinterpret_cast<WORD*>(SELECT_VALUE(0x19AFC82, 0x1E72182, 0x1D3C802));
scr_entref_t result{}; scr_entref_t result{};
result.raw.classnum = static_cast<unsigned short>(class_array[2 * id]) >> 8; result.raw.classnum = static_cast<unsigned short>(class_array[2 * id]) >> 8;
result.raw.entnum = ent_array[4 * id]; result.raw.entnum = ent_array[4 * id];
return result; return result;
} }
scr_call_t Scr_GetFunc(const unsigned int index) scr_call_t Scr_GetFunc(const unsigned int index)
{ {
if (index > 0x1C7) if (index > 0x1C7)
{ {
return scr_instanceFunctions[index]; return scr_instanceFunctions[index];
} }
else else
{ {
return scr_globalFunctions[index]; return scr_globalFunctions[index];
} }
} }
__declspec(naked) void scr_notify_id_multiplayer(unsigned int id, unsigned int stringValue, __declspec(naked) void scr_notify_id_multiplayer(unsigned int id, unsigned int stringValue,
unsigned int paramcount) unsigned int paramcount)
{ {
static DWORD func = 0x56B5E0; static DWORD func = 0x56B5E0;
__asm __asm
{ {
mov eax, paramcount mov eax, paramcount
push stringValue push stringValue
push id push id
call func call func
add esp, 8h add esp, 8h
retn retn
} }
} }
__declspec(naked) void scr_notify_id_singleplayer(unsigned int id, unsigned int stringValue, __declspec(naked) void scr_notify_id_singleplayer(unsigned int id, unsigned int stringValue,
unsigned int paramcount) unsigned int paramcount)
{ {
static DWORD func = 0x610980; static DWORD func = 0x610980;
__asm __asm
{ {
mov eax, paramcount mov eax, paramcount
push stringValue push stringValue
push id push id
call func call func
add esp, 8h add esp, 8h
retn retn
} }
} }
void Scr_NotifyId(unsigned int id, unsigned int stringValue, unsigned int paramcount) void Scr_NotifyId(unsigned int id, unsigned int stringValue, unsigned int paramcount)
{ {
if (is_mp()) if (is_mp())
{ {
return scr_notify_id_multiplayer(id, stringValue, paramcount); return scr_notify_id_multiplayer(id, stringValue, paramcount);
} }
else if (is_sp()) else if (is_sp())
{ {
return scr_notify_id_singleplayer(id, stringValue, paramcount); return scr_notify_id_singleplayer(id, stringValue, paramcount);
} }
else else
{ {
return reinterpret_cast<void(*)(unsigned int, unsigned int, unsigned int)>(0x4EFAA0)(id, stringValue, paramcount); 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) __declspec(naked) int scr_set_object_field_dedicated(unsigned int classnum, int entnum, int _offset)
{ {
static DWORD func = 0x4B15C0; static DWORD func = 0x4B15C0;
__asm __asm
{ {
mov ecx, _offset mov ecx, _offset
mov eax, entnum mov eax, entnum
push classnum push classnum
call func call func
add esp, 4h add esp, 4h
retn retn
} }
} }
int Scr_SetObjectField(const unsigned int classnum, const int entnum, const int offset) int Scr_SetObjectField(const unsigned int classnum, const int entnum, const int offset)
{ {
if (is_dedi()) if (is_dedi())
{ {
return scr_set_object_field_dedicated(classnum, entnum, offset); return scr_set_object_field_dedicated(classnum, entnum, offset);
} }
else else
{ {
return reinterpret_cast<int(*)(unsigned int, int, int)> // return reinterpret_cast<int(*)(unsigned int, int, int)> //
(SELECT_VALUE(0x42CAD0, 0x52BCC0, 0x0))(classnum, entnum, offset); (SELECT_VALUE(0x42CAD0, 0x52BCC0, 0x0))(classnum, entnum, offset);
} }
} }
const char* SL_ConvertToString(const unsigned int stringValue) const char* SL_ConvertToString(const unsigned int stringValue)
{ {
if (!stringValue) return nullptr; if (!stringValue) return nullptr;
static const auto size = is_sp() ? 16 : 12; static const auto size = is_sp() ? 16 : 12;
return *scrMemTreePub + size * stringValue + 4; return *scrMemTreePub + size * stringValue + 4;
} }
unsigned int SL_GetString(const char* str, const unsigned int user) unsigned int SL_GetString(const char* str, const unsigned int user)
{ {
return SL_GetStringOfSize(str, user, strlen(str) + 1, 7); return SL_GetStringOfSize(str, user, strlen(str) + 1, 7);
} }
} }
launcher::mode mode = launcher::mode::none; launcher::mode mode = launcher::mode::none;
launcher::mode get_mode() launcher::mode get_mode()
{ {
if(mode == launcher::mode::none) if(mode == launcher::mode::none)
{ {
throw std::runtime_error("Launcher mode not valid. Something must be wrong."); throw std::runtime_error("Launcher mode not valid. Something must be wrong.");
} }
return mode; return mode;
} }
bool is_mp() bool is_mp()
{ {
return get_mode() == launcher::mode::multiplayer; return get_mode() == launcher::mode::multiplayer;
} }
bool is_sp() bool is_sp()
{ {
return get_mode() == launcher::mode::singleplayer; return get_mode() == launcher::mode::singleplayer;
} }
bool is_dedi() bool is_dedi()
{ {
return get_mode() == launcher::mode::server; return get_mode() == launcher::mode::server;
} }
void initialize(const launcher::mode _mode) void initialize(const launcher::mode _mode)
{ {
mode = _mode; mode = _mode;
native::Cmd_AddCommand = native::Cmd_AddCommand_t(SELECT_VALUE(0x558820, 0x545DF0, 0)); 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::Com_Error = native::Com_Error_t(SELECT_VALUE(0x425540, 0x555450, 0x4D93F0));
native::DB_LoadXAssets = native::DB_LoadXAssets_t(SELECT_VALUE(0x48A8E0, 0x4CD020, 0x44F770)); 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::Dvar_SetFromStringByName = native::Dvar_SetFromStringByName_t(SELECT_VALUE(0x4DD090, 0x5BF740, 0x518DF0));
native::G_RunFrame = native::G_RunFrame_t(SELECT_VALUE(0x52EAA0, 0x50CB70, 0x48AD60)); 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::MSG_ReadData = native::MSG_ReadData_t(SELECT_VALUE(0, 0x5592A0, 0));
native::MT_AllocIndex = native::MT_AllocIndex_t(SELECT_VALUE(0x4B9610, 0x562080, 0x4E6C30)); native::MT_AllocIndex = native::MT_AllocIndex_t(SELECT_VALUE(0x4B9610, 0x562080, 0x4E6C30));
native::RemoveRefToValue = native::RemoveRefToValue_t(SELECT_VALUE(0x477EA0, 0x565730, 0x4E8A40)); native::RemoveRefToValue = native::RemoveRefToValue_t(SELECT_VALUE(0x477EA0, 0x565730, 0x4E8A40));
native::SL_GetStringOfSize = native::SL_GetStringOfSize_t(SELECT_VALUE(0x4E13F0, 0x564650, 0x4E7490)); 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::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0));
native::VM_Notify = native::VM_Notify_t(SELECT_VALUE(0x610200, 0x569720, 0x4EF450)); native::VM_Notify = native::VM_Notify_t(SELECT_VALUE(0x610200, 0x569720, 0x4EF450));
native::_longjmp = reinterpret_cast<decltype(longjmp)*>(SELECT_VALUE(0x73AC20, 0x7363BC, 0x655558)); native::_longjmp = reinterpret_cast<decltype(longjmp)*>(SELECT_VALUE(0x73AC20, 0x7363BC, 0x655558));
native::cmd_args = reinterpret_cast<int*>(SELECT_VALUE(0x1750750, 0x1C978D0, 0x1B455F8)); native::cmd_args = reinterpret_cast<int*>(SELECT_VALUE(0x1750750, 0x1C978D0, 0x1B455F8));
native::cmd_argc = reinterpret_cast<int*>(SELECT_VALUE(0x1750794, 0x1C97914, 0x1B4563C)); native::cmd_argc = reinterpret_cast<int*>(SELECT_VALUE(0x1750794, 0x1C97914, 0x1B4563C));
native::cmd_argv = reinterpret_cast<const char***>(SELECT_VALUE(0x17507B4, 0x1C97934, 0x1B4565C)); native::cmd_argv = reinterpret_cast<const char***>(SELECT_VALUE(0x17507B4, 0x1C97934, 0x1B4565C));
native::scrVarGlob = reinterpret_cast<short*>(SELECT_VALUE(0x19AFC80, 0x1E72180, 0x1D3C800)); native::scrVarGlob = reinterpret_cast<short*>(SELECT_VALUE(0x19AFC80, 0x1E72180, 0x1D3C800));
native::scrMemTreePub = reinterpret_cast<char**>(SELECT_VALUE(0x196FB00, 0x1E32000, 0x1C152A4)); native::scrMemTreePub = reinterpret_cast<char**>(SELECT_VALUE(0x196FB00, 0x1E32000, 0x1C152A4));
native::scrMemTreeGlob = reinterpret_cast<char*>(SELECT_VALUE(0x186DA00, 0x1D6FF00, 0x1C16600)); 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_VmPub = reinterpret_cast<native::scrVmPub_t*>(SELECT_VALUE(0x1BF2580, 0x20B4A80, 0x1F5B080));
native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x184CDB0, 0x1D4F258, native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x184CDB0, 0x1D4F258,
0x1BF59C8)); 0x1BF59C8));
native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x186C68C, 0x1D6EB34, native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>( SELECT_VALUE(0x186C68C, 0x1D6EB34,
0x1C152A4 0x1C152A4
)); ));
native::g_script_error_level = reinterpret_cast<int*>(SELECT_VALUE(0x1BEFCFC, 0x20B21FC, 0x1F5B058)); 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_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::g_classMap = reinterpret_cast<native::scr_classStruct_t*>(SELECT_VALUE(0x92D140, 0x8B4300, 0x7C0408));
native::levelEntityId = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BCBCA4, 0x208E1A4, 0x1CD873C)); native::levelEntityId = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BCBCA4, 0x208E1A4, 0x1CD873C));
} }
} }

View File

@ -1,95 +1,95 @@
#pragma once #pragma once
#include "structs.hpp" #include "structs.hpp"
#include "launcher/launcher.hpp" #include "launcher/launcher.hpp"
#define SELECT_VALUE(sp, mp, dedi) (game::is_sp() ? (sp) : (game::is_mp() ? (mp) : (dedi))) #define SELECT_VALUE(sp, mp, dedi) (game::is_sp() ? (sp) : (game::is_mp() ? (mp) : (dedi)))
#define SERVER_CD_KEY "Open-IW5-CD-Key" #define SERVER_CD_KEY "Open-IW5-CD-Key"
namespace game namespace game
{ {
namespace native namespace native
{ {
typedef void (*Cmd_AddCommand_t)(const char* cmdName, void (*function)(), cmd_function_t* allocedCmd); typedef void (*Cmd_AddCommand_t)(const char* cmdName, void (*function)(), cmd_function_t* allocedCmd);
extern Cmd_AddCommand_t Cmd_AddCommand; extern Cmd_AddCommand_t Cmd_AddCommand;
typedef void (*Com_Error_t)(int code, const char* fmt, ...); typedef void (*Com_Error_t)(int code, const char* fmt, ...);
extern Com_Error_t Com_Error; extern Com_Error_t Com_Error;
typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync); typedef void (*DB_LoadXAssets_t)(XZoneInfo* zoneInfo, unsigned int zoneCount, int sync);
extern DB_LoadXAssets_t DB_LoadXAssets; extern DB_LoadXAssets_t DB_LoadXAssets;
typedef void (*Dvar_SetFromStringByName_t)(const char *dvarName, const char *string); typedef void (*Dvar_SetFromStringByName_t)(const char *dvarName, const char *string);
extern Dvar_SetFromStringByName_t Dvar_SetFromStringByName; extern Dvar_SetFromStringByName_t Dvar_SetFromStringByName;
typedef int (*G_RunFrame_t)(int, int); typedef int (*G_RunFrame_t)(int, int);
extern G_RunFrame_t G_RunFrame; extern G_RunFrame_t G_RunFrame;
typedef void (*MSG_ReadData_t)(msg_t* msg, void* data, int len); typedef void (*MSG_ReadData_t)(msg_t* msg, void* data, int len);
extern MSG_ReadData_t MSG_ReadData; extern MSG_ReadData_t MSG_ReadData;
typedef void* (*MT_AllocIndex_t)(int numBytes, int type); typedef void* (*MT_AllocIndex_t)(int numBytes, int type);
extern MT_AllocIndex_t MT_AllocIndex; extern MT_AllocIndex_t MT_AllocIndex;
typedef void (*RemoveRefToValue_t)(scriptType_e type, VariableUnion u); typedef void (*RemoveRefToValue_t)(scriptType_e type, VariableUnion u);
extern RemoveRefToValue_t RemoveRefToValue; extern RemoveRefToValue_t RemoveRefToValue;
typedef unsigned int (*SL_GetStringOfSize_t)(const char* str, unsigned int user, unsigned int len, int type); typedef unsigned int (*SL_GetStringOfSize_t)(const char* str, unsigned int user, unsigned int len, int type);
extern SL_GetStringOfSize_t SL_GetStringOfSize; extern SL_GetStringOfSize_t SL_GetStringOfSize;
typedef void (*Sys_ShowConsole_t)(); typedef void (*Sys_ShowConsole_t)();
extern Sys_ShowConsole_t Sys_ShowConsole; extern Sys_ShowConsole_t Sys_ShowConsole;
typedef void (*VM_Notify_t)(unsigned int notifyListOwnerId, unsigned int stringValue, VariableValue* top); typedef void (*VM_Notify_t)(unsigned int notifyListOwnerId, unsigned int stringValue, VariableValue* top);
extern VM_Notify_t VM_Notify; extern VM_Notify_t VM_Notify;
extern decltype(longjmp)* _longjmp; extern decltype(longjmp)* _longjmp;
extern int* cmd_args; extern int* cmd_args;
extern int* cmd_argc; extern int* cmd_argc;
extern const char*** cmd_argv; extern const char*** cmd_argv;
extern short* scrVarGlob; extern short* scrVarGlob;
extern char** scrMemTreePub; extern char** scrMemTreePub;
extern char* scrMemTreeGlob; extern char* scrMemTreeGlob;
extern scrVmPub_t* scr_VmPub; extern scrVmPub_t* scr_VmPub;
extern scr_call_t* scr_instanceFunctions; extern scr_call_t* scr_instanceFunctions;
extern scr_call_t* scr_globalFunctions; extern scr_call_t* scr_globalFunctions;
extern unsigned int* levelEntityId; extern unsigned int* levelEntityId;
extern int* g_script_error_level; extern int* g_script_error_level;
extern jmp_buf* g_script_error; extern jmp_buf* g_script_error;
extern scr_classStruct_t* g_classMap; extern scr_classStruct_t* g_classMap;
void AddRefToValue(VariableValue* value); void AddRefToValue(VariableValue* value);
void Conbuf_AppendText(const char* message); void Conbuf_AppendText(const char* message);
unsigned int FindVariable(unsigned int parentId, unsigned int name); unsigned int FindVariable(unsigned int parentId, unsigned int name);
VariableValue GetEntityFieldValue(unsigned int classnum, int entnum, int offset); VariableValue GetEntityFieldValue(unsigned int classnum, int entnum, int offset);
void* MT_Alloc(int numBytes, int type); void* MT_Alloc(int numBytes, int type);
const float* Scr_AllocVector(const float* v); const float* Scr_AllocVector(const float* v);
void Scr_ClearOutParams(); void Scr_ClearOutParams();
scr_entref_t Scr_GetEntityIdRef(unsigned int id); scr_entref_t Scr_GetEntityIdRef(unsigned int id);
scr_call_t Scr_GetFunc(unsigned int index); scr_call_t Scr_GetFunc(unsigned int index);
void Scr_NotifyId(unsigned int id, unsigned int stringValue, unsigned int paramcount); void Scr_NotifyId(unsigned int id, unsigned int stringValue, unsigned int paramcount);
int Scr_SetObjectField(unsigned int classnum, int entnum, int offset); int Scr_SetObjectField(unsigned int classnum, int entnum, int offset);
const char* SL_ConvertToString(unsigned int stringValue); const char* SL_ConvertToString(unsigned int stringValue);
unsigned int SL_GetString(const char* str, unsigned int user); unsigned int SL_GetString(const char* str, unsigned int user);
} }
bool is_mp(); bool is_mp();
bool is_sp(); bool is_sp();
bool is_dedi(); bool is_dedi();
void initialize(launcher::mode mode); void initialize(launcher::mode mode);
} }

View File

@ -1,115 +1,115 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "html_frame.hpp" #include "html_frame.hpp"
doc_host_ui_handler::doc_host_ui_handler(html_frame* frame): frame_(frame) doc_host_ui_handler::doc_host_ui_handler(html_frame* frame): frame_(frame)
{ {
} }
HRESULT doc_host_ui_handler::QueryInterface(REFIID riid, LPVOID* ppvObj) HRESULT doc_host_ui_handler::QueryInterface(REFIID riid, LPVOID* ppvObj)
{ {
auto client_site = this->frame_->get_client_site(); auto client_site = this->frame_->get_client_site();
if (client_site) if (client_site)
{ {
return client_site->QueryInterface(riid, ppvObj); return client_site->QueryInterface(riid, ppvObj);
} }
return E_NOINTERFACE; return E_NOINTERFACE;
} }
ULONG doc_host_ui_handler::AddRef() ULONG doc_host_ui_handler::AddRef()
{ {
return 1; return 1;
} }
ULONG doc_host_ui_handler::Release() ULONG doc_host_ui_handler::Release()
{ {
return 1; return 1;
} }
HRESULT doc_host_ui_handler::ShowContextMenu(DWORD /*dwID*/, POINT* /*ppt*/, IUnknown* /*pcmdtReserved*/, HRESULT doc_host_ui_handler::ShowContextMenu(DWORD /*dwID*/, POINT* /*ppt*/, IUnknown* /*pcmdtReserved*/,
IDispatch* /*pdispReserved*/) IDispatch* /*pdispReserved*/)
{ {
return S_OK; return S_OK;
} }
HRESULT doc_host_ui_handler::ShowUI(DWORD /*dwID*/, IOleInPlaceActiveObject* /*pActiveObject*/, HRESULT doc_host_ui_handler::ShowUI(DWORD /*dwID*/, IOleInPlaceActiveObject* /*pActiveObject*/,
IOleCommandTarget* /*pCommandTarget*/, IOleCommandTarget* /*pCommandTarget*/,
IOleInPlaceFrame* /*pFrame*/, IOleInPlaceUIWindow* /*pDoc*/) IOleInPlaceFrame* /*pFrame*/, IOleInPlaceUIWindow* /*pDoc*/)
{ {
return S_OK; return S_OK;
} }
HRESULT doc_host_ui_handler::HideUI() HRESULT doc_host_ui_handler::HideUI()
{ {
return S_OK; return S_OK;
} }
HRESULT doc_host_ui_handler::UpdateUI() HRESULT doc_host_ui_handler::UpdateUI()
{ {
return S_OK; return S_OK;
} }
HRESULT doc_host_ui_handler::EnableModeless(BOOL /*fEnable*/) HRESULT doc_host_ui_handler::EnableModeless(BOOL /*fEnable*/)
{ {
return S_OK; return S_OK;
} }
HRESULT doc_host_ui_handler::OnDocWindowActivate(BOOL /*fActivate*/) HRESULT doc_host_ui_handler::OnDocWindowActivate(BOOL /*fActivate*/)
{ {
return S_OK; return S_OK;
} }
HRESULT doc_host_ui_handler::OnFrameWindowActivate(BOOL /*fActivate*/) HRESULT doc_host_ui_handler::OnFrameWindowActivate(BOOL /*fActivate*/)
{ {
return S_OK; return S_OK;
} }
HRESULT doc_host_ui_handler::ResizeBorder(LPCRECT /*prcBorder*/, IOleInPlaceUIWindow* /*pUIWindow*/, HRESULT doc_host_ui_handler::ResizeBorder(LPCRECT /*prcBorder*/, IOleInPlaceUIWindow* /*pUIWindow*/,
BOOL /*fRameWindow*/) BOOL /*fRameWindow*/)
{ {
return S_OK; return S_OK;
} }
HRESULT doc_host_ui_handler::TranslateAcceleratorA(LPMSG /*lpMsg*/, const GUID* pguidCmdGroup, DWORD /*nCmdID*/) HRESULT doc_host_ui_handler::TranslateAcceleratorA(LPMSG /*lpMsg*/, const GUID* pguidCmdGroup, DWORD /*nCmdID*/)
{ {
pguidCmdGroup = nullptr; pguidCmdGroup = nullptr;
return S_FALSE; return S_FALSE;
} }
HRESULT doc_host_ui_handler::GetOptionKeyPath(LPOLESTR* /*pchKey*/, DWORD /*dw*/) HRESULT doc_host_ui_handler::GetOptionKeyPath(LPOLESTR* /*pchKey*/, DWORD /*dw*/)
{ {
return S_FALSE; return S_FALSE;
} }
HRESULT doc_host_ui_handler::GetDropTarget(IDropTarget* /*pDropTarget*/, IDropTarget** /*ppDropTarget*/) HRESULT doc_host_ui_handler::GetDropTarget(IDropTarget* /*pDropTarget*/, IDropTarget** /*ppDropTarget*/)
{ {
return S_FALSE; return S_FALSE;
} }
HRESULT doc_host_ui_handler::GetExternal(IDispatch** ppDispatch) HRESULT doc_host_ui_handler::GetExternal(IDispatch** ppDispatch)
{ {
*ppDispatch = this->frame_->get_html_dispatch(); *ppDispatch = this->frame_->get_html_dispatch();
return (*ppDispatch) ? S_OK : S_FALSE; return (*ppDispatch) ? S_OK : S_FALSE;
} }
HRESULT doc_host_ui_handler::FilterDataObject(IDataObject* /*pDO*/, IDataObject** ppDORet) HRESULT doc_host_ui_handler::FilterDataObject(IDataObject* /*pDO*/, IDataObject** ppDORet)
{ {
*ppDORet = nullptr; *ppDORet = nullptr;
return S_FALSE; return S_FALSE;
} }
HRESULT STDMETHODCALLTYPE doc_host_ui_handler::TranslateUrl(DWORD /*dwTranslate*/, OLECHAR __RPC_FAR* /*pchURLIn*/, HRESULT STDMETHODCALLTYPE doc_host_ui_handler::TranslateUrl(DWORD /*dwTranslate*/, OLECHAR __RPC_FAR* /*pchURLIn*/,
OLECHAR __RPC_FAR* __RPC_FAR* ppchURLOut) OLECHAR __RPC_FAR* __RPC_FAR* ppchURLOut)
{ {
*ppchURLOut = nullptr; *ppchURLOut = nullptr;
return S_FALSE; return S_FALSE;
} }
HRESULT doc_host_ui_handler::GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo) HRESULT doc_host_ui_handler::GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo)
{ {
pInfo->cbSize = sizeof(DOCHOSTUIINFO); pInfo->cbSize = sizeof(DOCHOSTUIINFO);
pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_DPI_AWARE | DOCHOSTUIFLAG_SCROLL_NO; pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_DPI_AWARE | DOCHOSTUIFLAG_SCROLL_NO;
pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
return S_OK; return S_OK;
} }

View File

@ -1,47 +1,47 @@
#pragma once #pragma once
class html_frame; class html_frame;
class doc_host_ui_handler final : public IDocHostUIHandler class doc_host_ui_handler final : public IDocHostUIHandler
{ {
public: public:
doc_host_ui_handler(html_frame* frame); doc_host_ui_handler(html_frame* frame);
virtual ~doc_host_ui_handler() = default; virtual ~doc_host_ui_handler() = default;
private: private:
html_frame* frame_; html_frame* frame_;
public: // IDocHostUIHandler interface public: // IDocHostUIHandler interface
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObj) override; HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObj) override;
ULONG STDMETHODCALLTYPE AddRef() override; ULONG STDMETHODCALLTYPE AddRef() override;
ULONG STDMETHODCALLTYPE Release() override; ULONG STDMETHODCALLTYPE Release() override;
HRESULT STDMETHODCALLTYPE ShowContextMenu( HRESULT STDMETHODCALLTYPE ShowContextMenu(
DWORD dwID, DWORD dwID,
POINT __RPC_FAR * ppt, POINT __RPC_FAR * ppt,
IUnknown __RPC_FAR * pcmdtReserved, IUnknown __RPC_FAR * pcmdtReserved,
IDispatch __RPC_FAR * pdispReserved) override; IDispatch __RPC_FAR * pdispReserved) override;
HRESULT STDMETHODCALLTYPE ShowUI( HRESULT STDMETHODCALLTYPE ShowUI(
DWORD dwID, DWORD dwID,
IOleInPlaceActiveObject __RPC_FAR * pActiveObject, IOleInPlaceActiveObject __RPC_FAR * pActiveObject,
IOleCommandTarget __RPC_FAR * pCommandTarget, IOleCommandTarget __RPC_FAR * pCommandTarget,
IOleInPlaceFrame __RPC_FAR * pFrame, IOleInPlaceFrame __RPC_FAR * pFrame,
IOleInPlaceUIWindow __RPC_FAR * pDoc) override; IOleInPlaceUIWindow __RPC_FAR * pDoc) override;
HRESULT STDMETHODCALLTYPE GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo) override; HRESULT STDMETHODCALLTYPE GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo) override;
HRESULT STDMETHODCALLTYPE HideUI() override; HRESULT STDMETHODCALLTYPE HideUI() override;
HRESULT STDMETHODCALLTYPE UpdateUI() override; HRESULT STDMETHODCALLTYPE UpdateUI() override;
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override; HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override;
HRESULT STDMETHODCALLTYPE OnDocWindowActivate(BOOL fActivate) override; HRESULT STDMETHODCALLTYPE OnDocWindowActivate(BOOL fActivate) override;
HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(BOOL fActivate) override; HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(BOOL fActivate) override;
HRESULT STDMETHODCALLTYPE ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR * pUIWindow, HRESULT STDMETHODCALLTYPE ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR * pUIWindow,
BOOL fRameWindow) override; BOOL fRameWindow) override;
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpMsg, const GUID __RPC_FAR * pguidCmdGroup, DWORD nCmdID) HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpMsg, const GUID __RPC_FAR * pguidCmdGroup, DWORD nCmdID)
override; override;
HRESULT STDMETHODCALLTYPE GetOptionKeyPath(LPOLESTR __RPC_FAR * pchKey, DWORD dw) override; HRESULT STDMETHODCALLTYPE GetOptionKeyPath(LPOLESTR __RPC_FAR * pchKey, DWORD dw) override;
HRESULT STDMETHODCALLTYPE GetDropTarget(IDropTarget __RPC_FAR * pDropTarget, HRESULT STDMETHODCALLTYPE GetDropTarget(IDropTarget __RPC_FAR * pDropTarget,
IDropTarget __RPC_FAR *__RPC_FAR * ppDropTarget) override; IDropTarget __RPC_FAR *__RPC_FAR * ppDropTarget) override;
HRESULT STDMETHODCALLTYPE GetExternal(IDispatch __RPC_FAR *__RPC_FAR * ppDispatch) override; HRESULT STDMETHODCALLTYPE GetExternal(IDispatch __RPC_FAR *__RPC_FAR * ppDispatch) override;
HRESULT STDMETHODCALLTYPE TranslateUrl(DWORD dwTranslate, OLECHAR __RPC_FAR * pchURLIn, HRESULT STDMETHODCALLTYPE TranslateUrl(DWORD dwTranslate, OLECHAR __RPC_FAR * pchURLIn,
OLECHAR __RPC_FAR *__RPC_FAR * ppchURLOut) override; OLECHAR __RPC_FAR *__RPC_FAR * ppchURLOut) override;
HRESULT STDMETHODCALLTYPE FilterDataObject(IDataObject __RPC_FAR * pDO, IDataObject __RPC_FAR *__RPC_FAR * ppDORet) HRESULT STDMETHODCALLTYPE FilterDataObject(IDataObject __RPC_FAR * pDO, IDataObject __RPC_FAR *__RPC_FAR * ppDORet)
override; override;
}; };

View File

@ -1,48 +1,48 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "html_argument.hpp" #include "html_argument.hpp"
html_argument::html_argument(VARIANT* val) : value_(val) html_argument::html_argument(VARIANT* val) : value_(val)
{ {
} }
bool html_argument::is_empty() const bool html_argument::is_empty() const
{ {
return this->value_ == nullptr || this->value_->vt == VT_EMPTY; return this->value_ == nullptr || this->value_->vt == VT_EMPTY;
} }
bool html_argument::is_string() const bool html_argument::is_string() const
{ {
if (this->is_empty()) return false; if (this->is_empty()) return false;
return this->value_->vt == VT_BSTR; return this->value_->vt == VT_BSTR;
} }
bool html_argument::is_number() const bool html_argument::is_number() const
{ {
if (this->is_empty()) return false; if (this->is_empty()) return false;
return this->value_->vt == VT_I4; return this->value_->vt == VT_I4;
} }
bool html_argument::is_bool() const bool html_argument::is_bool() const
{ {
if (this->is_empty()) return false; if (this->is_empty()) return false;
return this->value_->vt == VT_BOOL; return this->value_->vt == VT_BOOL;
} }
std::string html_argument::get_string() const std::string html_argument::get_string() const
{ {
if (!this->is_string()) return {}; if (!this->is_string()) return {};
std::wstring wide_string(this->value_->bstrVal); std::wstring wide_string(this->value_->bstrVal);
return std::string(wide_string.begin(), wide_string.end()); return std::string(wide_string.begin(), wide_string.end());
} }
int html_argument::get_number() const int html_argument::get_number() const
{ {
if (!this->is_number()) return 0; if (!this->is_number()) return 0;
return this->value_->intVal; return this->value_->intVal;
} }
bool html_argument::get_bool() const bool html_argument::get_bool() const
{ {
if(!this->is_bool()) return false; if(!this->is_bool()) return false;
return this->value_->boolVal != FALSE; return this->value_->boolVal != FALSE;
} }

View File

@ -1,20 +1,20 @@
#pragma once #pragma once
class html_argument final class html_argument final
{ {
public: public:
html_argument(VARIANT* val); html_argument(VARIANT* val);
bool is_empty() const; bool is_empty() const;
bool is_string() const; bool is_string() const;
bool is_number() const; bool is_number() const;
bool is_bool() const; bool is_bool() const;
std::string get_string() const; std::string get_string() const;
int get_number() const; int get_number() const;
bool get_bool() const; bool get_bool() const;
private: private:
VARIANT* value_; VARIANT* value_;
}; };

View File

@ -1,61 +1,61 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "html_frame.hpp" #include "html_frame.hpp"
html_dispatch::html_dispatch(html_frame* frame) : frame_(frame) html_dispatch::html_dispatch(html_frame* frame) : frame_(frame)
{ {
} }
HRESULT html_dispatch::QueryInterface(const IID& riid, LPVOID* ppvObj) HRESULT html_dispatch::QueryInterface(const IID& riid, LPVOID* ppvObj)
{ {
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) || if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) ||
!memcmp(&riid, &IID_IDispatch, sizeof(GUID))) !memcmp(&riid, &IID_IDispatch, sizeof(GUID)))
{ {
*ppvObj = this; *ppvObj = this;
this->AddRef(); this->AddRef();
return S_OK; return S_OK;
} }
*ppvObj = nullptr; *ppvObj = nullptr;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
ULONG html_dispatch::AddRef() ULONG html_dispatch::AddRef()
{ {
return 1; return 1;
} }
ULONG html_dispatch::Release() ULONG html_dispatch::Release()
{ {
return 1; return 1;
} }
HRESULT html_dispatch::GetTypeInfoCount(UINT* pctinfo) HRESULT html_dispatch::GetTypeInfoCount(UINT* pctinfo)
{ {
return S_FALSE; return S_FALSE;
} }
HRESULT html_dispatch::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) HRESULT html_dispatch::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
{ {
return S_FALSE; return S_FALSE;
} }
HRESULT html_dispatch::GetIDsOfNames(const IID& riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) HRESULT html_dispatch::GetIDsOfNames(const IID& riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
{ {
for (unsigned int i = 0; i < cNames; ++i) for (unsigned int i = 0; i < cNames; ++i)
{ {
std::wstring wide_name(rgszNames[i]); std::wstring wide_name(rgszNames[i]);
std::string name(wide_name.begin(), wide_name.end()); std::string name(wide_name.begin(), wide_name.end());
rgDispId[i] = this->frame_->get_callback_id(name); rgDispId[i] = this->frame_->get_callback_id(name);
} }
return S_OK; return S_OK;
} }
HRESULT html_dispatch::Invoke(DISPID dispIdMember, const IID& riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, HRESULT html_dispatch::Invoke(DISPID dispIdMember, const IID& riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
{ {
html_frame::callback_params params(pDispParams, pVarResult); html_frame::callback_params params(pDispParams, pVarResult);
this->frame_->invoke_callback(dispIdMember, &params); this->frame_->invoke_callback(dispIdMember, &params);
return S_OK; return S_OK;
} }

View File

@ -1,24 +1,24 @@
#pragma once #pragma once
class html_frame; class html_frame;
class html_dispatch final : public IDispatch class html_dispatch final : public IDispatch
{ {
public: public:
html_dispatch(html_frame* frame); html_dispatch(html_frame* frame);
virtual ~html_dispatch() = default; virtual ~html_dispatch() = default;
private: private:
html_frame* frame_; html_frame* frame_;
public: // IDispatch interface public: // IDispatch interface
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override; HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
ULONG STDMETHODCALLTYPE AddRef() override; ULONG STDMETHODCALLTYPE AddRef() override;
ULONG STDMETHODCALLTYPE Release() override; ULONG STDMETHODCALLTYPE Release() override;
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override; HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override;
HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override; HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override;
HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
override; override;
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override; VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
}; };

View File

@ -1,262 +1,262 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "html_frame.hpp" #include "html_frame.hpp"
#include "utils/nt.hpp" #include "utils/nt.hpp"
std::atomic<int> html_frame::frame_count_ = 0; std::atomic<int> html_frame::frame_count_ = 0;
html_frame::callback_params::callback_params(DISPPARAMS* params, VARIANT* res) : result(res) html_frame::callback_params::callback_params(DISPPARAMS* params, VARIANT* res) : result(res)
{ {
for (auto i = params->cArgs; i > 0; --i) for (auto i = params->cArgs; i > 0; --i)
{ {
auto param = &params->rgvarg[i - 1]; auto param = &params->rgvarg[i - 1];
this->arguments.emplace_back(param); this->arguments.emplace_back(param);
} }
} }
html_frame::html_frame() : in_place_frame_(this), in_place_site_(this), ui_handler_(this), client_site_(this), html_frame::html_frame() : in_place_frame_(this), in_place_site_(this), ui_handler_(this), client_site_(this),
html_dispatch_(this) html_dispatch_(this)
{ {
if (frame_count_++ == 0 && OleInitialize(nullptr) != S_OK) if (frame_count_++ == 0 && OleInitialize(nullptr) != S_OK)
{ {
throw std::runtime_error("Unable to initialize the OLE library"); throw std::runtime_error("Unable to initialize the OLE library");
} }
set_browser_feature("FEATURE_BROWSER_EMULATION", 11000); set_browser_feature("FEATURE_BROWSER_EMULATION", 11000);
set_browser_feature("FEATURE_GPU_RENDERING", 1); set_browser_feature("FEATURE_GPU_RENDERING", 1);
} }
html_frame::~html_frame() html_frame::~html_frame()
{ {
if (--frame_count_ <= 0) if (--frame_count_ <= 0)
{ {
frame_count_ = 0; frame_count_ = 0;
OleUninitialize(); OleUninitialize();
} }
} }
void html_frame::object_deleter(IUnknown* object) void html_frame::object_deleter(IUnknown* object)
{ {
if (object) if (object)
{ {
object->Release(); object->Release();
} }
} }
HWND html_frame::get_window() const HWND html_frame::get_window() const
{ {
return this->window_; return this->window_;
} }
std::shared_ptr<IOleObject> html_frame::get_browser_object() const std::shared_ptr<IOleObject> html_frame::get_browser_object() const
{ {
return this->browser_object_; return this->browser_object_;
} }
ole_in_place_frame* html_frame::get_in_place_frame() ole_in_place_frame* html_frame::get_in_place_frame()
{ {
return &this->in_place_frame_; return &this->in_place_frame_;
} }
ole_in_place_site* html_frame::get_in_place_site() ole_in_place_site* html_frame::get_in_place_site()
{ {
return &this->in_place_site_; return &this->in_place_site_;
} }
doc_host_ui_handler* html_frame::get_ui_handler() doc_host_ui_handler* html_frame::get_ui_handler()
{ {
return &this->ui_handler_; return &this->ui_handler_;
} }
ole_client_site* html_frame::get_client_site() ole_client_site* html_frame::get_client_site()
{ {
return &this->client_site_; return &this->client_site_;
} }
html_dispatch* html_frame::get_html_dispatch() html_dispatch* html_frame::get_html_dispatch()
{ {
return &this->html_dispatch_; return &this->html_dispatch_;
} }
std::shared_ptr<IWebBrowser2> html_frame::get_web_browser() const std::shared_ptr<IWebBrowser2> html_frame::get_web_browser() const
{ {
if (!this->browser_object_) return {}; if (!this->browser_object_) return {};
IWebBrowser2* web_browser = nullptr; IWebBrowser2* web_browser = nullptr;
if (this->browser_object_->QueryInterface(IID_IWebBrowser2, reinterpret_cast<void**>(&web_browser)) || !web_browser) if (this->browser_object_->QueryInterface(IID_IWebBrowser2, reinterpret_cast<void**>(&web_browser)) || !web_browser)
return {}; return {};
return std::shared_ptr<IWebBrowser2>(web_browser, object_deleter); return std::shared_ptr<IWebBrowser2>(web_browser, object_deleter);
} }
std::shared_ptr<IDispatch> html_frame::get_dispatch() const std::shared_ptr<IDispatch> html_frame::get_dispatch() const
{ {
const auto web_browser = this->get_web_browser(); const auto web_browser = this->get_web_browser();
if (!web_browser) return {}; if (!web_browser) return {};
IDispatch* dispatch = nullptr; IDispatch* dispatch = nullptr;
if (web_browser->get_Document(&dispatch) || !dispatch) return {}; if (web_browser->get_Document(&dispatch) || !dispatch) return {};
return std::shared_ptr<IDispatch>(dispatch, object_deleter); return std::shared_ptr<IDispatch>(dispatch, object_deleter);
} }
std::shared_ptr<IHTMLDocument2> html_frame::get_document() const std::shared_ptr<IHTMLDocument2> html_frame::get_document() const
{ {
const auto dispatch = this->get_dispatch(); const auto dispatch = this->get_dispatch();
if (!dispatch) return {}; if (!dispatch) return {};
IHTMLDocument2* document = nullptr; IHTMLDocument2* document = nullptr;
if (dispatch->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void**>(&document)) || !document) return {}; if (dispatch->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void**>(&document)) || !document) return {};
return std::shared_ptr<IHTMLDocument2>(document, object_deleter); return std::shared_ptr<IHTMLDocument2>(document, object_deleter);
} }
void html_frame::initialize(const HWND window) void html_frame::initialize(const HWND window)
{ {
if (this->window_) return; if (this->window_) return;
this->window_ = window; this->window_ = window;
this->create_browser(); this->create_browser();
this->initialize_browser(); this->initialize_browser();
} }
void html_frame::create_browser() void html_frame::create_browser()
{ {
LPCLASSFACTORY class_factory = nullptr; LPCLASSFACTORY class_factory = nullptr;
if (CoGetClassObject(CLSID_WebBrowser, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, nullptr, IID_IClassFactory, if (CoGetClassObject(CLSID_WebBrowser, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, nullptr, IID_IClassFactory,
reinterpret_cast<void **>(&class_factory)) || !class_factory) reinterpret_cast<void **>(&class_factory)) || !class_factory)
{ {
throw std::runtime_error("Unable to get the class factory"); throw std::runtime_error("Unable to get the class factory");
} }
IOleObject* browser_object = nullptr; IOleObject* browser_object = nullptr;
class_factory->CreateInstance(nullptr, IID_IOleObject, reinterpret_cast<void**>(&browser_object)); class_factory->CreateInstance(nullptr, IID_IOleObject, reinterpret_cast<void**>(&browser_object));
class_factory->Release(); class_factory->Release();
if (!browser_object) if (!browser_object)
{ {
throw std::runtime_error("Unable to create browser object"); throw std::runtime_error("Unable to create browser object");
} }
this->browser_object_ = std::shared_ptr<IOleObject>(browser_object, [](IOleObject* browser_object) this->browser_object_ = std::shared_ptr<IOleObject>(browser_object, [](IOleObject* browser_object)
{ {
if (browser_object) if (browser_object)
{ {
browser_object->Close(OLECLOSE_NOSAVE); browser_object->Close(OLECLOSE_NOSAVE);
object_deleter(browser_object); object_deleter(browser_object);
} }
}); });
} }
void html_frame::initialize_browser() void html_frame::initialize_browser()
{ {
this->browser_object_->SetClientSite(this->get_client_site()); this->browser_object_->SetClientSite(this->get_client_site());
this->browser_object_->SetHostNames(L"Hostname", nullptr); this->browser_object_->SetHostNames(L"Hostname", nullptr);
RECT rect; RECT rect;
GetClientRect(this->get_window(), &rect); GetClientRect(this->get_window(), &rect);
OleSetContainedObject(this->browser_object_.get(), TRUE); OleSetContainedObject(this->browser_object_.get(), TRUE);
this->browser_object_->DoVerb(OLEIVERB_SHOW, nullptr, this->get_client_site(), -1, this->get_window(), &rect); this->browser_object_->DoVerb(OLEIVERB_SHOW, nullptr, this->get_client_site(), -1, this->get_window(), &rect);
this->resize(rect.right, rect.bottom); this->resize(rect.right, rect.bottom);
} }
void html_frame::set_browser_feature(const std::string& feature, DWORD value) void html_frame::set_browser_feature(const std::string& feature, DWORD value)
{ {
const auto registry_path = R"(SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\)" + feature; const auto registry_path = R"(SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\)" + feature;
HKEY key = nullptr; HKEY key = nullptr;
if (RegOpenKeyExA( if (RegOpenKeyExA(
HKEY_CURRENT_USER, registry_path.data(), 0, HKEY_CURRENT_USER, registry_path.data(), 0,
KEY_ALL_ACCESS, &key) != ERROR_SUCCESS) KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
return; return;
const utils::nt::module self; const utils::nt::module self;
const auto name = self.get_name(); const auto name = self.get_name();
RegSetValueExA(key, name.data(), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value)); RegSetValueExA(key, name.data(), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
RegCloseKey(key); RegCloseKey(key);
} }
void html_frame::resize(const DWORD width, const DWORD height) const void html_frame::resize(const DWORD width, const DWORD height) const
{ {
auto web_browser = this->get_web_browser(); auto web_browser = this->get_web_browser();
if (web_browser) if (web_browser)
{ {
web_browser->put_Left(0); web_browser->put_Left(0);
web_browser->put_Top(0); web_browser->put_Top(0);
web_browser->put_Width(width); web_browser->put_Width(width);
web_browser->put_Height(height); web_browser->put_Height(height);
} }
} }
bool html_frame::load_url(const std::string& url) const bool html_frame::load_url(const std::string& url) const
{ {
auto web_browser = this->get_web_browser(); auto web_browser = this->get_web_browser();
if (!web_browser) return false; if (!web_browser) return false;
std::wstring wide_url(url.begin(), url.end()); std::wstring wide_url(url.begin(), url.end());
VARIANT my_url; VARIANT my_url;
VariantInit(&my_url); VariantInit(&my_url);
my_url.vt = VT_BSTR; my_url.vt = VT_BSTR;
my_url.bstrVal = SysAllocString(wide_url.data()); my_url.bstrVal = SysAllocString(wide_url.data());
const auto _ = gsl::finally([&my_url]() { VariantClear(&my_url); }); const auto _ = gsl::finally([&my_url]() { VariantClear(&my_url); });
if (!my_url.bstrVal) return false; if (!my_url.bstrVal) return false;
return SUCCEEDED(web_browser->Navigate2(&my_url, nullptr, nullptr, nullptr, nullptr)); return SUCCEEDED(web_browser->Navigate2(&my_url, nullptr, nullptr, nullptr, nullptr));
} }
bool html_frame::load_html(const std::string& html) const bool html_frame::load_html(const std::string& html) const
{ {
if (!this->load_url("about:blank")) return false; if (!this->load_url("about:blank")) return false;
const auto document = this->get_document(); const auto document = this->get_document();
if (!document) return false; if (!document) return false;
SAFEARRAYBOUND safe_array_bound = {1, 0}; SAFEARRAYBOUND safe_array_bound = {1, 0};
auto safe_array = SafeArrayCreate(VT_VARIANT, 1, &safe_array_bound); auto safe_array = SafeArrayCreate(VT_VARIANT, 1, &safe_array_bound);
if (!safe_array) return false; if (!safe_array) return false;
const auto _ = gsl::finally([safe_array]() { SafeArrayDestroy(safe_array); }); const auto _ = gsl::finally([safe_array]() { SafeArrayDestroy(safe_array); });
VARIANT* variant = nullptr; VARIANT* variant = nullptr;
if (SafeArrayAccessData(safe_array, reinterpret_cast<void**>(&variant)) || !variant) return false; if (SafeArrayAccessData(safe_array, reinterpret_cast<void**>(&variant)) || !variant) return false;
std::wstring wide_html(html.begin(), html.end()); std::wstring wide_html(html.begin(), html.end());
variant->vt = VT_BSTR; variant->vt = VT_BSTR;
variant->bstrVal = SysAllocString(wide_html.data()); variant->bstrVal = SysAllocString(wide_html.data());
if (!variant->bstrVal) return false; if (!variant->bstrVal) return false;
document->write(safe_array); document->write(safe_array);
document->close(); document->close();
return true; return true;
} }
int html_frame::get_callback_id(const std::string& name) int html_frame::get_callback_id(const std::string& name)
{ {
for (auto i = 0u; i < this->callbacks_.size(); ++i) for (auto i = 0u; i < this->callbacks_.size(); ++i)
{ {
if (this->callbacks_[i].first == name) if (this->callbacks_[i].first == name)
{ {
return i; return i;
} }
} }
return -1; return -1;
} }
void html_frame::invoke_callback(const int id, callback_params* params) void html_frame::invoke_callback(const int id, callback_params* params)
{ {
if (id >= 0 && static_cast<unsigned int>(id) < this->callbacks_.size()) if (id >= 0 && static_cast<unsigned int>(id) < this->callbacks_.size())
{ {
this->callbacks_[id].second(params); this->callbacks_[id].second(params);
} }
} }
void html_frame::register_callback(const std::string& name, const std::function<void(callback_params*)>& callback) void html_frame::register_callback(const std::string& name, const std::function<void(callback_params*)>& callback)
{ {
this->callbacks_.emplace_back(name, callback); this->callbacks_.emplace_back(name, callback);
} }

View File

@ -1,67 +1,67 @@
#pragma once #pragma once
#include "ole_in_place_frame.hpp" #include "ole_in_place_frame.hpp"
#include "ole_in_place_site.hpp" #include "ole_in_place_site.hpp"
#include "doc_host_ui_handler.hpp" #include "doc_host_ui_handler.hpp"
#include "ole_client_site.hpp" #include "ole_client_site.hpp"
#include "html_dispatch.hpp" #include "html_dispatch.hpp"
#include "html_argument.hpp" #include "html_argument.hpp"
class html_frame class html_frame
{ {
public: public:
class callback_params final class callback_params final
{ {
public: public:
callback_params(DISPPARAMS* params, VARIANT* res); callback_params(DISPPARAMS* params, VARIANT* res);
std::vector<html_argument> arguments; std::vector<html_argument> arguments;
html_argument result; html_argument result;
}; };
html_frame(); html_frame();
virtual ~html_frame(); virtual ~html_frame();
void initialize(HWND window); void initialize(HWND window);
void resize(DWORD width, DWORD height) const; void resize(DWORD width, DWORD height) const;
bool load_url(const std::string& url) const; bool load_url(const std::string& url) const;
bool load_html(const std::string& html) const; bool load_html(const std::string& html) const;
HWND get_window() const; HWND get_window() const;
std::shared_ptr<IOleObject> get_browser_object() const; std::shared_ptr<IOleObject> get_browser_object() const;
std::shared_ptr<IWebBrowser2> get_web_browser() const; std::shared_ptr<IWebBrowser2> get_web_browser() const;
std::shared_ptr<IDispatch> get_dispatch() const; std::shared_ptr<IDispatch> get_dispatch() const;
std::shared_ptr<IHTMLDocument2> get_document() const; std::shared_ptr<IHTMLDocument2> get_document() const;
ole_in_place_frame* get_in_place_frame(); ole_in_place_frame* get_in_place_frame();
ole_in_place_site* get_in_place_site(); ole_in_place_site* get_in_place_site();
doc_host_ui_handler* get_ui_handler(); doc_host_ui_handler* get_ui_handler();
ole_client_site* get_client_site(); ole_client_site* get_client_site();
html_dispatch* get_html_dispatch(); html_dispatch* get_html_dispatch();
int get_callback_id(const std::string& name); int get_callback_id(const std::string& name);
void invoke_callback(int id, callback_params* params); void invoke_callback(int id, callback_params* params);
void register_callback(const std::string& name, const std::function<void(callback_params*)>& callback); void register_callback(const std::string& name, const std::function<void(callback_params*)>& callback);
private: private:
HWND window_ = nullptr; HWND window_ = nullptr;
std::shared_ptr<IOleObject> browser_object_; std::shared_ptr<IOleObject> browser_object_;
ole_in_place_frame in_place_frame_; ole_in_place_frame in_place_frame_;
ole_in_place_site in_place_site_; ole_in_place_site in_place_site_;
doc_host_ui_handler ui_handler_; doc_host_ui_handler ui_handler_;
ole_client_site client_site_; ole_client_site client_site_;
html_dispatch html_dispatch_; html_dispatch html_dispatch_;
std::vector<std::pair<std::string, std::function<void(callback_params*)>>> callbacks_; std::vector<std::pair<std::string, std::function<void(callback_params*)>>> callbacks_;
void create_browser(); void create_browser();
void initialize_browser(); void initialize_browser();
static void set_browser_feature(const std::string& feature, DWORD value); static void set_browser_feature(const std::string& feature, DWORD value);
static void object_deleter(IUnknown* object); static void object_deleter(IUnknown* object);
static std::atomic<int> frame_count_; static std::atomic<int> frame_count_;
}; };

View File

@ -1,29 +1,29 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "html_window.hpp" #include "html_window.hpp"
window* html_window::get_window() window* html_window::get_window()
{ {
return this; return this;
} }
html_frame* html_window::get_html_frame() html_frame* html_window::get_html_frame()
{ {
return this; return this;
} }
LRESULT html_window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param) LRESULT html_window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
{ {
if (message == WM_SIZE) if (message == WM_SIZE)
{ {
this->resize(LOWORD(l_param), HIWORD(l_param)); this->resize(LOWORD(l_param), HIWORD(l_param));
return 0; return 0;
} }
if (message == WM_CREATE) if (message == WM_CREATE)
{ {
this->initialize(*this); this->initialize(*this);
return 0; return 0;
} }
return window::processor(message, w_param, l_param); return window::processor(message, w_param, l_param);
} }

View File

@ -1,15 +1,15 @@
#pragma once #pragma once
#include "../window.hpp" #include "../window.hpp"
#include "html_frame.hpp" #include "html_frame.hpp"
class html_window final : public window, public html_frame class html_window final : public window, public html_frame
{ {
public: public:
~html_window() = default; ~html_window() = default;
window* get_window(); window* get_window();
html_frame* get_html_frame(); html_frame* get_html_frame();
private: private:
LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param) override; LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param) override;
}; };

View File

@ -1,77 +1,77 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "html_frame.hpp" #include "html_frame.hpp"
ole_client_site::ole_client_site(html_frame* frame): frame_(frame) ole_client_site::ole_client_site(html_frame* frame): frame_(frame)
{ {
} }
HRESULT ole_client_site::QueryInterface(REFIID riid, LPVOID* ppvObject) HRESULT ole_client_site::QueryInterface(REFIID riid, LPVOID* ppvObject)
{ {
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) || if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) ||
!memcmp(&riid, &IID_IOleClientSite, sizeof(GUID))) !memcmp(&riid, &IID_IOleClientSite, sizeof(GUID)))
{ {
*ppvObject = this; *ppvObject = this;
this->AddRef(); this->AddRef();
return S_OK; return S_OK;
} }
if (!memcmp(&riid, &IID_IOleInPlaceSite, sizeof(GUID))) if (!memcmp(&riid, &IID_IOleInPlaceSite, sizeof(GUID)))
{ {
auto in_place_site = this->frame_->get_in_place_site(); auto in_place_site = this->frame_->get_in_place_site();
in_place_site->AddRef(); in_place_site->AddRef();
*ppvObject = in_place_site; *ppvObject = in_place_site;
return S_OK; return S_OK;
} }
if (!memcmp(&riid, &IID_IDocHostUIHandler, sizeof(GUID))) if (!memcmp(&riid, &IID_IDocHostUIHandler, sizeof(GUID)))
{ {
auto ui_handler = this->frame_->get_ui_handler(); auto ui_handler = this->frame_->get_ui_handler();
ui_handler->AddRef(); ui_handler->AddRef();
*ppvObject = ui_handler; *ppvObject = ui_handler;
return S_OK; return S_OK;
} }
*ppvObject = nullptr; *ppvObject = nullptr;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
ULONG ole_client_site::AddRef() ULONG ole_client_site::AddRef()
{ {
return 1; return 1;
} }
ULONG ole_client_site::Release() ULONG ole_client_site::Release()
{ {
return 1; return 1;
} }
HRESULT ole_client_site::SaveObject() HRESULT ole_client_site::SaveObject()
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_client_site::GetMoniker(DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker** /*ppmk*/) HRESULT ole_client_site::GetMoniker(DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker** /*ppmk*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_client_site::GetContainer(LPOLECONTAINER* ppContainer) HRESULT ole_client_site::GetContainer(LPOLECONTAINER* ppContainer)
{ {
*ppContainer = nullptr; *ppContainer = nullptr;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
HRESULT ole_client_site::ShowObject() HRESULT ole_client_site::ShowObject()
{ {
return NOERROR; return NOERROR;
} }
HRESULT ole_client_site::OnShowWindow(BOOL /*fShow*/) HRESULT ole_client_site::OnShowWindow(BOOL /*fShow*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_client_site::RequestNewObjectLayout() HRESULT ole_client_site::RequestNewObjectLayout()
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }

View File

@ -1,24 +1,24 @@
#pragma once #pragma once
class html_frame; class html_frame;
class ole_client_site final : public IOleClientSite class ole_client_site final : public IOleClientSite
{ {
public: public:
ole_client_site(html_frame* frame); ole_client_site(html_frame* frame);
virtual ~ole_client_site() = default; virtual ~ole_client_site() = default;
private: private:
html_frame* frame_; html_frame* frame_;
public: public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObject) override; HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObject) override;
ULONG STDMETHODCALLTYPE AddRef() override; ULONG STDMETHODCALLTYPE AddRef() override;
ULONG STDMETHODCALLTYPE Release() override; ULONG STDMETHODCALLTYPE Release() override;
HRESULT STDMETHODCALLTYPE SaveObject() override; HRESULT STDMETHODCALLTYPE SaveObject() override;
HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk) override; HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk) override;
HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER FAR* ppContainer) override; HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER FAR* ppContainer) override;
HRESULT STDMETHODCALLTYPE ShowObject() override; HRESULT STDMETHODCALLTYPE ShowObject() override;
HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL fShow) override; HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL fShow) override;
HRESULT STDMETHODCALLTYPE RequestNewObjectLayout() override; HRESULT STDMETHODCALLTYPE RequestNewObjectLayout() override;
}; };

View File

@ -1,82 +1,82 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "html_frame.hpp" #include "html_frame.hpp"
ole_in_place_frame::ole_in_place_frame(html_frame* frame): frame_(frame) ole_in_place_frame::ole_in_place_frame(html_frame* frame): frame_(frame)
{ {
} }
HRESULT ole_in_place_frame::QueryInterface(REFIID /*riid*/, LPVOID* /*ppvObj*/) HRESULT ole_in_place_frame::QueryInterface(REFIID /*riid*/, LPVOID* /*ppvObj*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
ULONG ole_in_place_frame::AddRef() ULONG ole_in_place_frame::AddRef()
{ {
return 1; return 1;
} }
ULONG ole_in_place_frame::Release() ULONG ole_in_place_frame::Release()
{ {
return 1; return 1;
} }
HRESULT ole_in_place_frame::GetWindow(HWND* lphwnd) HRESULT ole_in_place_frame::GetWindow(HWND* lphwnd)
{ {
*lphwnd = this->frame_->get_window(); *lphwnd = this->frame_->get_window();
return S_OK; return S_OK;
} }
HRESULT ole_in_place_frame::ContextSensitiveHelp(BOOL /*fEnterMode*/) HRESULT ole_in_place_frame::ContextSensitiveHelp(BOOL /*fEnterMode*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_in_place_frame::GetBorder(LPRECT /*lprectBorder*/) HRESULT ole_in_place_frame::GetBorder(LPRECT /*lprectBorder*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_in_place_frame::RequestBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/) HRESULT ole_in_place_frame::RequestBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_in_place_frame::SetBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/) HRESULT ole_in_place_frame::SetBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_in_place_frame::SetActiveObject(IOleInPlaceActiveObject* /*pActiveObject*/, LPCOLESTR /*pszObjName*/) HRESULT ole_in_place_frame::SetActiveObject(IOleInPlaceActiveObject* /*pActiveObject*/, LPCOLESTR /*pszObjName*/)
{ {
return S_OK; return S_OK;
} }
HRESULT ole_in_place_frame::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/) HRESULT ole_in_place_frame::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_in_place_frame::SetMenu(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/) HRESULT ole_in_place_frame::SetMenu(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/)
{ {
return S_OK; return S_OK;
} }
HRESULT ole_in_place_frame::RemoveMenus(HMENU /*hmenuShared*/) HRESULT ole_in_place_frame::RemoveMenus(HMENU /*hmenuShared*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_in_place_frame::SetStatusText(LPCOLESTR /*pszStatusText*/) HRESULT ole_in_place_frame::SetStatusText(LPCOLESTR /*pszStatusText*/)
{ {
return S_OK; return S_OK;
} }
HRESULT ole_in_place_frame::EnableModeless(BOOL /*fEnable*/) HRESULT ole_in_place_frame::EnableModeless(BOOL /*fEnable*/)
{ {
return S_OK; return S_OK;
} }
HRESULT ole_in_place_frame::TranslateAcceleratorA(LPMSG /*lpmsg*/, WORD /*wID*/) HRESULT ole_in_place_frame::TranslateAcceleratorA(LPMSG /*lpmsg*/, WORD /*wID*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }

View File

@ -1,30 +1,30 @@
#pragma once #pragma once
class html_frame; class html_frame;
class ole_in_place_frame final : public IOleInPlaceFrame class ole_in_place_frame final : public IOleInPlaceFrame
{ {
public: public:
ole_in_place_frame(html_frame* frame); ole_in_place_frame(html_frame* frame);
virtual ~ole_in_place_frame() = default; virtual ~ole_in_place_frame() = default;
private: private:
html_frame* frame_; html_frame* frame_;
public: // IOleInPlaceFrame interface public: // IOleInPlaceFrame interface
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override; HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
ULONG STDMETHODCALLTYPE AddRef() override; ULONG STDMETHODCALLTYPE AddRef() override;
ULONG STDMETHODCALLTYPE Release() override; ULONG STDMETHODCALLTYPE Release() override;
HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override; HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override;
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override; HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder) override; HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder) override;
HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) override; HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) override;
HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS pborderwidths) override; HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS pborderwidths) override;
HRESULT STDMETHODCALLTYPE SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR pszObjName) override; HRESULT STDMETHODCALLTYPE SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR pszObjName) override;
HRESULT STDMETHODCALLTYPE InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override; HRESULT STDMETHODCALLTYPE InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override;
HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) override; HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) override;
HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenuShared) override; HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenuShared) override;
HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR pszStatusText) override; HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR pszStatusText) override;
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override; HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override;
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD wID) override; HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD wID) override;
}; };

View File

@ -1,105 +1,105 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "html_frame.hpp" #include "html_frame.hpp"
ole_in_place_site::ole_in_place_site(html_frame* frame) : frame_(frame) ole_in_place_site::ole_in_place_site(html_frame* frame) : frame_(frame)
{ {
} }
HRESULT ole_in_place_site::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) HRESULT ole_in_place_site::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
{ {
auto client_site = this->frame_->get_client_site(); auto client_site = this->frame_->get_client_site();
if (client_site) if (client_site)
{ {
return client_site->QueryInterface(riid, ppvObj); return client_site->QueryInterface(riid, ppvObj);
} }
return E_NOINTERFACE; return E_NOINTERFACE;
} }
ULONG ole_in_place_site::AddRef() ULONG ole_in_place_site::AddRef()
{ {
return 1; return 1;
} }
ULONG ole_in_place_site::Release() ULONG ole_in_place_site::Release()
{ {
return 1; return 1;
} }
HRESULT ole_in_place_site::GetWindow(HWND* lphwnd) HRESULT ole_in_place_site::GetWindow(HWND* lphwnd)
{ {
*lphwnd = this->frame_->get_window(); *lphwnd = this->frame_->get_window();
return S_OK; return S_OK;
} }
HRESULT ole_in_place_site::ContextSensitiveHelp(BOOL /*fEnterMode*/) HRESULT ole_in_place_site::ContextSensitiveHelp(BOOL /*fEnterMode*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_in_place_site::CanInPlaceActivate() HRESULT ole_in_place_site::CanInPlaceActivate()
{ {
return S_OK; return S_OK;
} }
HRESULT ole_in_place_site::OnInPlaceActivate() HRESULT ole_in_place_site::OnInPlaceActivate()
{ {
return S_OK; return S_OK;
} }
HRESULT ole_in_place_site::OnUIActivate() HRESULT ole_in_place_site::OnUIActivate()
{ {
return S_OK; return S_OK;
} }
HRESULT ole_in_place_site::GetWindowContext(LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc, HRESULT ole_in_place_site::GetWindowContext(LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc,
LPRECT /*lprcPosRect*/, LPRECT /*lprcClipRect*/, LPRECT /*lprcPosRect*/, LPRECT /*lprcClipRect*/,
LPOLEINPLACEFRAMEINFO lpFrameInfo) LPOLEINPLACEFRAMEINFO lpFrameInfo)
{ {
*lplpFrame = this->frame_->get_in_place_frame(); *lplpFrame = this->frame_->get_in_place_frame();
*lplpDoc = nullptr; *lplpDoc = nullptr;
lpFrameInfo->fMDIApp = FALSE; lpFrameInfo->fMDIApp = FALSE;
lpFrameInfo->hwndFrame = this->frame_->get_window(); lpFrameInfo->hwndFrame = this->frame_->get_window();
lpFrameInfo->haccel = nullptr; lpFrameInfo->haccel = nullptr;
lpFrameInfo->cAccelEntries = 0; lpFrameInfo->cAccelEntries = 0;
return S_OK; return S_OK;
} }
HRESULT ole_in_place_site::Scroll(SIZE /*scrollExtent*/) HRESULT ole_in_place_site::Scroll(SIZE /*scrollExtent*/)
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_in_place_site::OnUIDeactivate(BOOL /*fUndoable*/) HRESULT ole_in_place_site::OnUIDeactivate(BOOL /*fUndoable*/)
{ {
return S_OK; return S_OK;
} }
HRESULT ole_in_place_site::OnInPlaceDeactivate() HRESULT ole_in_place_site::OnInPlaceDeactivate()
{ {
return S_OK; return S_OK;
} }
HRESULT ole_in_place_site::DiscardUndoState() HRESULT ole_in_place_site::DiscardUndoState()
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_in_place_site::DeactivateAndUndo() HRESULT ole_in_place_site::DeactivateAndUndo()
{ {
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT ole_in_place_site::OnPosRectChange(LPCRECT lprcPosRect) HRESULT ole_in_place_site::OnPosRectChange(LPCRECT lprcPosRect)
{ {
IOleInPlaceObject* in_place = nullptr; IOleInPlaceObject* in_place = nullptr;
if (!this->frame_->get_browser_object()->QueryInterface(IID_IOleInPlaceObject, reinterpret_cast<void**>(&in_place))) if (!this->frame_->get_browser_object()->QueryInterface(IID_IOleInPlaceObject, reinterpret_cast<void**>(&in_place)))
{ {
in_place->SetObjectRects(lprcPosRect, lprcPosRect); in_place->SetObjectRects(lprcPosRect, lprcPosRect);
in_place->Release(); in_place->Release();
} }
return S_OK; return S_OK;
} }

View File

@ -1,32 +1,32 @@
#pragma once #pragma once
class html_frame; class html_frame;
class ole_in_place_site final : public IOleInPlaceSite class ole_in_place_site final : public IOleInPlaceSite
{ {
public: public:
ole_in_place_site(html_frame* frame); ole_in_place_site(html_frame* frame);
virtual ~ole_in_place_site() = default; virtual ~ole_in_place_site() = default;
private: private:
html_frame* frame_; html_frame* frame_;
public: // IOleInPlaceSite interface public: // IOleInPlaceSite interface
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override; HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
ULONG STDMETHODCALLTYPE AddRef() override; ULONG STDMETHODCALLTYPE AddRef() override;
ULONG STDMETHODCALLTYPE Release() override; ULONG STDMETHODCALLTYPE Release() override;
HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override; HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override;
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override; HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
HRESULT STDMETHODCALLTYPE CanInPlaceActivate() override; HRESULT STDMETHODCALLTYPE CanInPlaceActivate() override;
HRESULT STDMETHODCALLTYPE OnInPlaceActivate() override; HRESULT STDMETHODCALLTYPE OnInPlaceActivate() override;
HRESULT STDMETHODCALLTYPE OnUIActivate() override; HRESULT STDMETHODCALLTYPE OnUIActivate() override;
HRESULT STDMETHODCALLTYPE GetWindowContext(LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc, HRESULT STDMETHODCALLTYPE GetWindowContext(LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc,
LPRECT lprcPosRect, LPRECT lprcClipRect, LPRECT lprcPosRect, LPRECT lprcClipRect,
LPOLEINPLACEFRAMEINFO lpFrameInfo) override; LPOLEINPLACEFRAMEINFO lpFrameInfo) override;
HRESULT STDMETHODCALLTYPE Scroll(SIZE scrollExtent) override; HRESULT STDMETHODCALLTYPE Scroll(SIZE scrollExtent) override;
HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL fUndoable) override; HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL fUndoable) override;
HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate() override; HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate() override;
HRESULT STDMETHODCALLTYPE DiscardUndoState() override; HRESULT STDMETHODCALLTYPE DiscardUndoState() override;
HRESULT STDMETHODCALLTYPE DeactivateAndUndo() override; HRESULT STDMETHODCALLTYPE DeactivateAndUndo() override;
HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect) override; HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect) override;
}; };

View File

@ -1,88 +1,88 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "launcher.hpp" #include "launcher.hpp"
#include "utils/nt.hpp" #include "utils/nt.hpp"
launcher::launcher() launcher::launcher()
{ {
this->create_settings_menu(); this->create_settings_menu();
this->create_main_menu(); this->create_main_menu();
} }
void launcher::create_main_menu() void launcher::create_main_menu()
{ {
this->main_window_.register_callback("selectMode", [this](html_frame::callback_params* params) this->main_window_.register_callback("selectMode", [this](html_frame::callback_params* params)
{ {
if (params->arguments.empty()) return; if (params->arguments.empty()) return;
const auto param = params->arguments[0]; const auto param = params->arguments[0];
if (!param.is_number()) return; if (!param.is_number()) return;
const auto number = param.get_number(); const auto number = param.get_number();
if (number == singleplayer || number == multiplayer) if (number == singleplayer || number == multiplayer)
{ {
this->select_mode(static_cast<mode>(number)); this->select_mode(static_cast<mode>(number));
} }
}); });
this->main_window_.register_callback("showSettings", [this](html_frame::callback_params*) this->main_window_.register_callback("showSettings", [this](html_frame::callback_params*)
{ {
this->settings_window_.show(); this->settings_window_.show();
}); });
this->main_window_.set_callback( this->main_window_.set_callback(
[](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT [](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT
{ {
if (message == WM_CLOSE) if (message == WM_CLOSE)
{ {
window::close_all(); window::close_all();
} }
return DefWindowProcA(*window, message, w_param, l_param); return DefWindowProcA(*window, message, w_param, l_param);
}); });
this->main_window_.create("Open-IW5", 615, 300); this->main_window_.create("Open-IW5", 615, 300);
this->main_window_.load_html(load_content(MENU_MAIN)); this->main_window_.load_html(load_content(MENU_MAIN));
this->main_window_.show(); this->main_window_.show();
} }
void launcher::create_settings_menu() void launcher::create_settings_menu()
{ {
this->settings_window_.set_callback( this->settings_window_.set_callback(
[](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT [](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT
{ {
if (message == WM_CLOSE) if (message == WM_CLOSE)
{ {
window->hide(); window->hide();
return TRUE; return TRUE;
} }
return DefWindowProcA(*window, message, w_param, l_param); 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_.create("Open-IW5 Settings", 400, 200, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU);
this->settings_window_.load_html(load_content(MENU_SETTINGS)); this->settings_window_.load_html(load_content(MENU_SETTINGS));
} }
launcher::mode launcher::run() const launcher::mode launcher::run() const
{ {
window::run(); window::run();
return this->mode_; return this->mode_;
} }
void launcher::select_mode(const mode mode) void launcher::select_mode(const mode mode)
{ {
this->mode_ = mode; this->mode_ = mode;
this->settings_window_.close(); this->settings_window_.close();
this->main_window_.close(); this->main_window_.close();
} }
std::string launcher::load_content(const int res) std::string launcher::load_content(const int res)
{ {
const auto resource = FindResource(utils::nt::module(), MAKEINTRESOURCE(res), RT_RCDATA); const auto resource = FindResource(utils::nt::module(), MAKEINTRESOURCE(res), RT_RCDATA);
if (!resource) return {}; if (!resource) return {};
const auto handle = LoadResource(nullptr, resource); const auto handle = LoadResource(nullptr, resource);
if (!handle) return {}; if (!handle) return {};
return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, resource)); return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, resource));
} }

View File

@ -1,31 +1,31 @@
#pragma once #pragma once
#include "html/html_window.hpp" #include "html/html_window.hpp"
class launcher final class launcher final
{ {
public: public:
enum mode enum mode
{ {
none, none,
singleplayer, singleplayer,
multiplayer, multiplayer,
server, server,
}; };
launcher(); launcher();
mode run() const; mode run() const;
private: private:
mode mode_ = none; mode mode_ = none;
html_window main_window_; html_window main_window_;
html_window settings_window_; html_window settings_window_;
void select_mode(mode mode); void select_mode(mode mode);
void create_main_menu(); void create_main_menu();
void create_settings_menu(); void create_settings_menu();
static std::string load_content(int res); static std::string load_content(int res);
}; };

View File

@ -1,180 +1,180 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "window.hpp" #include "window.hpp"
std::mutex window::mutex_; std::mutex window::mutex_;
std::vector<window*> window::windows_; std::vector<window*> window::windows_;
window::window() window::window()
{ {
ZeroMemory(&this->wc_, sizeof(this->wc_)); ZeroMemory(&this->wc_, sizeof(this->wc_));
this->classname_ = "window-base-" + std::to_string(time(nullptr)); this->classname_ = "window-base-" + std::to_string(time(nullptr));
this->wc_.cbSize = sizeof(this->wc_); this->wc_.cbSize = sizeof(this->wc_);
this->wc_.style = CS_HREDRAW | CS_VREDRAW; this->wc_.style = CS_HREDRAW | CS_VREDRAW;
this->wc_.lpfnWndProc = static_processor; this->wc_.lpfnWndProc = static_processor;
this->wc_.hInstance = GetModuleHandle(nullptr); this->wc_.hInstance = GetModuleHandle(nullptr);
this->wc_.hCursor = LoadCursor(nullptr, IDC_ARROW); this->wc_.hCursor = LoadCursor(nullptr, IDC_ARROW);
this->wc_.hIcon = LoadIcon(this->wc_.hInstance, MAKEINTRESOURCE(102)); this->wc_.hIcon = LoadIcon(this->wc_.hInstance, MAKEINTRESOURCE(102));
this->wc_.hIconSm = this->wc_.hIcon; this->wc_.hIconSm = this->wc_.hIcon;
this->wc_.hbrBackground = HBRUSH(COLOR_WINDOW); this->wc_.hbrBackground = HBRUSH(COLOR_WINDOW);
this->wc_.lpszClassName = this->classname_.data(); this->wc_.lpszClassName = this->classname_.data();
RegisterClassEx(&this->wc_); RegisterClassEx(&this->wc_);
} }
void window::create(const std::string& title, const int width, const int height, const long flags) void window::create(const std::string& title, const int width, const int height, const long flags)
{ {
{ {
std::lock_guard _(mutex_); std::lock_guard _(mutex_);
windows_.push_back(this); windows_.push_back(this);
} }
const auto x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2; const auto x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
const auto y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2; const auto y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
this->handle_ = CreateWindowExA(NULL, this->wc_.lpszClassName, title.data(), flags, x, y, width, height, nullptr, this->handle_ = CreateWindowExA(NULL, this->wc_.lpszClassName, title.data(), flags, x, y, width, height, nullptr,
nullptr, this->wc_.hInstance, this); nullptr, this->wc_.hInstance, this);
} }
window::~window() window::~window()
{ {
this->close(); this->close();
UnregisterClass(this->wc_.lpszClassName, this->wc_.hInstance); UnregisterClass(this->wc_.lpszClassName, this->wc_.hInstance);
} }
void window::close() void window::close()
{ {
if (!this->handle_) return; if (!this->handle_) return;
SendMessageA(this->handle_, WM_KILL_WINDOW, NULL, NULL); SendMessageA(this->handle_, WM_KILL_WINDOW, NULL, NULL);
this->handle_ = nullptr; this->handle_ = nullptr;
} }
void window::run() void window::run()
{ {
MSG msg; MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) while (GetMessage(&msg, nullptr, 0, 0))
{ {
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
} }
} }
void window::close_all() void window::close_all()
{ {
std::unique_lock lock(mutex_); std::unique_lock lock(mutex_);
auto window_list = windows_; auto window_list = windows_;
lock.unlock(); lock.unlock();
const auto current_thread_id = GetCurrentThreadId(); const auto current_thread_id = GetCurrentThreadId();
for (auto& window : window_list) for (auto& window : window_list)
{ {
const auto thread_id = GetWindowThreadProcessId(*window, nullptr); const auto thread_id = GetWindowThreadProcessId(*window, nullptr);
if (thread_id == current_thread_id) if (thread_id == current_thread_id)
{ {
window->close(); window->close();
} }
} }
} }
void window::remove_window(const window* window) void window::remove_window(const window* window)
{ {
std::lock_guard _(mutex_); std::lock_guard _(mutex_);
for (auto i = windows_.begin(); i != windows_.end(); ++i) for (auto i = windows_.begin(); i != windows_.end(); ++i)
{ {
if (*i == window) if (*i == window)
{ {
windows_.erase(i); windows_.erase(i);
break; break;
} }
} }
} }
int window::get_window_count() int window::get_window_count()
{ {
std::lock_guard _(mutex_); std::lock_guard _(mutex_);
auto count = 0; auto count = 0;
const auto current_thread_id = GetCurrentThreadId(); const auto current_thread_id = GetCurrentThreadId();
for (const auto& window : windows_) for (const auto& window : windows_)
{ {
const auto thread_id = GetWindowThreadProcessId(*window, nullptr); const auto thread_id = GetWindowThreadProcessId(*window, nullptr);
if (thread_id == current_thread_id) if (thread_id == current_thread_id)
{ {
++count; ++count;
} }
} }
return count; return count;
} }
void window::show() const void window::show() const
{ {
ShowWindow(this->handle_, SW_SHOW); ShowWindow(this->handle_, SW_SHOW);
UpdateWindow(this->handle_); UpdateWindow(this->handle_);
} }
void window::hide() const void window::hide() const
{ {
ShowWindow(this->handle_, SW_HIDE); ShowWindow(this->handle_, SW_HIDE);
UpdateWindow(this->handle_); UpdateWindow(this->handle_);
} }
void window::set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback) void window::set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback)
{ {
this->callback_ = callback; this->callback_ = callback;
} }
LRESULT window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param) LRESULT window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
{ {
if (message == WM_DESTROY) if (message == WM_DESTROY)
{ {
remove_window(this); remove_window(this);
if (get_window_count() == 0) if (get_window_count() == 0)
{ {
PostQuitMessage(0); PostQuitMessage(0);
} }
return TRUE; return TRUE;
} }
if (message == WM_KILL_WINDOW) if (message == WM_KILL_WINDOW)
{ {
DestroyWindow(*this); DestroyWindow(*this);
return 0; return 0;
} }
if (this->callback_) if (this->callback_)
{ {
return this->callback_(this, message, w_param, l_param); return this->callback_(this, message, w_param, l_param);
} }
return DefWindowProc(*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) LRESULT CALLBACK window::static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param)
{ {
if (message == WM_CREATE) if (message == WM_CREATE)
{ {
auto data = reinterpret_cast<LPCREATESTRUCT>(l_param); auto data = reinterpret_cast<LPCREATESTRUCT>(l_param);
SetWindowLongPtrA(hwnd, GWLP_USERDATA, LONG_PTR(data->lpCreateParams)); SetWindowLongPtrA(hwnd, GWLP_USERDATA, LONG_PTR(data->lpCreateParams));
reinterpret_cast<window*>(data->lpCreateParams)->handle_ = hwnd; reinterpret_cast<window*>(data->lpCreateParams)->handle_ = hwnd;
} }
const auto self = reinterpret_cast<window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); const auto self = reinterpret_cast<window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (self) return self->processor(message, w_param, l_param); if (self) return self->processor(message, w_param, l_param);
return DefWindowProc(hwnd, message, w_param, l_param); return DefWindowProc(hwnd, message, w_param, l_param);
} }
window::operator HWND() const window::operator HWND() const
{ {
return this->handle_; return this->handle_;
} }

View File

@ -1,42 +1,42 @@
#pragma once #pragma once
#define WM_KILL_WINDOW (WM_USER+0) #define WM_KILL_WINDOW (WM_USER+0)
class window class window
{ {
public: public:
window(); window();
virtual ~window(); virtual ~window();
void create(const std::string& title, int width, int height, void create(const std::string& title, int width, int height,
long flags = (WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX))); long flags = (WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX)));
void close(); void close();
void show() const; void show() const;
void hide() const; void hide() const;
void set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback); void set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback);
operator HWND() const; operator HWND() const;
static void run(); static void run();
static void close_all(); static void close_all();
protected: protected:
virtual LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param); virtual LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param);
private: private:
WNDCLASSEX wc_{}; WNDCLASSEX wc_{};
HWND handle_ = nullptr; HWND handle_ = nullptr;
std::string classname_; std::string classname_;
std::function<LRESULT(window*, UINT, WPARAM, LPARAM)> callback_; std::function<LRESULT(window*, UINT, WPARAM, LPARAM)> callback_;
static LRESULT CALLBACK static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param); static LRESULT CALLBACK static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param);
static std::mutex mutex_; static std::mutex mutex_;
static std::vector<window*> windows_; static std::vector<window*> windows_;
static void remove_window(const window* window); static void remove_window(const window* window);
static int get_window_count(); static int get_window_count();
}; };

View File

@ -1,121 +1,121 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "binary_loader.hpp" #include "binary_loader.hpp"
#include "utils/nt.hpp" #include "utils/nt.hpp"
#include "utils/io.hpp" #include "utils/io.hpp"
#include "utils/cryptography.hpp" #include "utils/cryptography.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#include "utils/compression.hpp" #include "utils/compression.hpp"
#define DEDI_HASH "F271C305117B79242E254E9F64BD5AA2993CAC8E57975243EBD44CD576418D20" #define DEDI_HASH "F271C305117B79242E254E9F64BD5AA2993CAC8E57975243EBD44CD576418D20"
namespace binary_loader namespace binary_loader
{ {
std::string load_resource(const int id) std::string load_resource(const int id)
{ {
const auto res = FindResource(::utils::nt::module(), MAKEINTRESOURCE(id), RT_RCDATA); const auto res = FindResource(::utils::nt::module(), MAKEINTRESOURCE(id), RT_RCDATA);
if (!res) return {}; if (!res) return {};
const auto handle = LoadResource(nullptr, res); const auto handle = LoadResource(nullptr, res);
if (!handle) return {}; if (!handle) return {};
return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res)); return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res));
} }
std::string load_delta(const launcher::mode mode) std::string load_delta(const launcher::mode mode)
{ {
if (mode == launcher::mode::singleplayer) if (mode == launcher::mode::singleplayer)
{ {
return load_resource(BINARY_SP); return load_resource(BINARY_SP);
} }
if (mode == launcher::mode::multiplayer) if (mode == launcher::mode::multiplayer)
{ {
return load_resource(BINARY_MP); return load_resource(BINARY_MP);
} }
return {}; return {};
} }
std::string load_base(const bool verify = true) std::string load_base(const bool verify = true)
{ {
std::string data; std::string data;
if (!utils::io::read_file("iw5mp_server.exe", &data)) if (!utils::io::read_file("iw5mp_server.exe", &data))
{ {
throw std::runtime_error("Unable to load iw5mp_server.exe"); throw std::runtime_error("Unable to load iw5mp_server.exe");
} }
if (verify && utils::cryptography::sha256::compute(data, true) != DEDI_HASH) if (verify && utils::cryptography::sha256::compute(data, true) != DEDI_HASH)
{ {
throw std::runtime_error("Your iw5mp_server.exe is incompatible with this client."); throw std::runtime_error("Your iw5mp_server.exe is incompatible with this client.");
} }
return data; return data;
} }
void create_for_file(const std::string& file, const std::string& base) void create_for_file(const std::string& file, const std::string& base)
{ {
std::string data; std::string data;
if (!utils::io::read_file(file, &data)) if (!utils::io::read_file(file, &data))
{ {
throw std::runtime_error(utils::string::va("Unable to load file %s!", 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 new_data = reinterpret_cast<const unsigned char*>(data.data());
const auto old_data = reinterpret_cast<const unsigned char*>(base.data()); const auto old_data = reinterpret_cast<const unsigned char*>(base.data());
std::vector<unsigned char> diff; std::vector<unsigned char> diff;
create_diff(new_data, new_data + data.size(), old_data, old_data + base.size(), diff); create_diff(new_data, new_data + data.size(), old_data, old_data + base.size(), diff);
const unsigned long long size = data.size(); const unsigned long long size = data.size();
std::string result(reinterpret_cast<char*>(diff.data()), diff.size()); std::string result(reinterpret_cast<char*>(diff.data()), diff.size());
result.append(reinterpret_cast<const char*>(&size), sizeof(size)); result.append(reinterpret_cast<const char*>(&size), sizeof(size));
result = utils::compression::zlib::compress(result); result = utils::compression::zlib::compress(result);
utils::io::write_file(file + ".diff", result); utils::io::write_file(file + ".diff", result);
} }
void create() void create()
{ {
const auto base = load_base(false); const auto base = load_base(false);
utils::io::write_file("hash.txt", utils::cryptography::sha256::compute(base, true)); utils::io::write_file("hash.txt", utils::cryptography::sha256::compute(base, true));
create_for_file("iw5sp.exe", base); create_for_file("iw5sp.exe", base);
create_for_file("iw5mp.exe", base); create_for_file("iw5mp.exe", base);
} }
std::string build_binary(const std::string& base, const std::string& diff) 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 const auto* size = reinterpret_cast<const unsigned long long*>(diff.data() + diff.size() - sizeof(unsigned long
long)); long));
std::string binary; std::string binary;
binary.resize(size_t(*size)); binary.resize(size_t(*size));
const auto new_data = reinterpret_cast<unsigned char*>(binary.data()); const auto new_data = reinterpret_cast<unsigned char*>(binary.data());
const auto old_data = reinterpret_cast<const unsigned char*>(base.data()); const auto old_data = reinterpret_cast<const unsigned char*>(base.data());
const auto diff_data = reinterpret_cast<const unsigned char*>(diff.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, 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()) diff_data + diff.size() - sizeof(*size)) == hpatch_FALSE || binary.empty())
{ {
throw std::runtime_error("Unable to create binary from patch!"); throw std::runtime_error("Unable to create binary from patch!");
} }
return binary; return binary;
} }
std::string load(const launcher::mode mode) std::string load(const launcher::mode mode)
{ {
auto base = load_base(); auto base = load_base();
if (mode == launcher::mode::server) if (mode == launcher::mode::server)
{ {
return base; return base;
} }
auto delta = load_delta(mode); auto delta = load_delta(mode);
delta = utils::compression::zlib::decompress(delta); delta = utils::compression::zlib::decompress(delta);
return build_binary(base, delta); return build_binary(base, delta);
} }
} }

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "launcher/launcher.hpp" #include "launcher/launcher.hpp"
namespace binary_loader namespace binary_loader
{ {
void create(); void create();
std::string load(launcher::mode mode); std::string load(launcher::mode mode);
} }

View File

@ -1,165 +1,165 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "loader.hpp" #include "loader.hpp"
#include "binary_loader.hpp" #include "binary_loader.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
loader::loader(const launcher::mode mode) : mode_(mode) loader::loader(const launcher::mode mode) : mode_(mode)
{ {
} }
FARPROC loader::load(const utils::nt::module& module) const FARPROC loader::load(const utils::nt::module& module) const
{ {
const auto buffer = binary_loader::load(this->mode_); const auto buffer = binary_loader::load(this->mode_);
if (buffer.empty()) return nullptr; if (buffer.empty()) return nullptr;
utils::nt::module source(HMODULE(buffer.data())); utils::nt::module source(HMODULE(buffer.data()));
if (!source) return nullptr; if (!source) return nullptr;
this->load_sections(module, source); this->load_sections(module, source);
this->load_imports(module, source); this->load_imports(module, source);
if (source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) if (source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
{ {
const auto target_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + module const auto target_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + module
.get_optional_header() .get_optional_header()
-> ->
DataDirectory DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); [IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
const auto source_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + source const auto source_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + source
.get_optional_header() .get_optional_header()
-> ->
DataDirectory DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); [IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
const auto tls_size = source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData; const auto tls_size = source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData;
const auto tls_index = *reinterpret_cast<DWORD*>(target_tls->AddressOfIndex); const auto tls_index = *reinterpret_cast<DWORD*>(target_tls->AddressOfIndex);
*reinterpret_cast<DWORD*>(source_tls->AddressOfIndex) = tls_index; *reinterpret_cast<DWORD*>(source_tls->AddressOfIndex) = tls_index;
if (tls_size > TLS_PAYLOAD_SIZE) if (tls_size > TLS_PAYLOAD_SIZE)
{ {
throw std::runtime_error(utils::string::va( 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)); "TLS data is of size 0x%X, but we have only reserved 0x%X bytes!", tls_size, TLS_PAYLOAD_SIZE));
} }
DWORD old_protect; DWORD old_protect;
VirtualProtect(PVOID(target_tls->StartAddressOfRawData), VirtualProtect(PVOID(target_tls->StartAddressOfRawData),
source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData, PAGE_READWRITE, source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData, PAGE_READWRITE,
&old_protect); &old_protect);
const auto tls_base = *reinterpret_cast<LPVOID*>(__readfsdword(0x2C) + 4 * tls_index); const auto tls_base = *reinterpret_cast<LPVOID*>(__readfsdword(0x2C) + 4 * tls_index);
std::memmove(tls_base, PVOID(source_tls->StartAddressOfRawData), tls_size); std::memmove(tls_base, PVOID(source_tls->StartAddressOfRawData), tls_size);
std::memmove(PVOID(target_tls->StartAddressOfRawData), PVOID(source_tls->StartAddressOfRawData), tls_size); std::memmove(PVOID(target_tls->StartAddressOfRawData), PVOID(source_tls->StartAddressOfRawData), tls_size);
} }
DWORD oldProtect; DWORD oldProtect;
VirtualProtect(module.get_nt_headers(), 0x1000, PAGE_EXECUTE_READWRITE, &oldProtect); VirtualProtect(module.get_nt_headers(), 0x1000, PAGE_EXECUTE_READWRITE, &oldProtect);
module.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] = source module.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] = source
.get_optional_header()->DataDirectory[ .get_optional_header()->DataDirectory[
IMAGE_DIRECTORY_ENTRY_IMPORT]; IMAGE_DIRECTORY_ENTRY_IMPORT];
std::memmove(module.get_nt_headers(), source.get_nt_headers(), std::memmove(module.get_nt_headers(), source.get_nt_headers(),
sizeof(IMAGE_NT_HEADERS) + (source.get_nt_headers()->FileHeader.NumberOfSections * (sizeof( sizeof(IMAGE_NT_HEADERS) + (source.get_nt_headers()->FileHeader.NumberOfSections * (sizeof(
IMAGE_SECTION_HEADER)))); IMAGE_SECTION_HEADER))));
return FARPROC(module.get_ptr() + source.get_relative_entry_point()); 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) void loader::set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver)
{ {
this->import_resolver_ = resolver; this->import_resolver_ = resolver;
} }
void loader::load_section(const utils::nt::module& target, const utils::nt::module& source, void loader::load_section(const utils::nt::module& target, const utils::nt::module& source,
IMAGE_SECTION_HEADER* section) IMAGE_SECTION_HEADER* section)
{ {
void* target_ptr = target.get_ptr() + section->VirtualAddress; void* target_ptr = target.get_ptr() + section->VirtualAddress;
const void* source_ptr = source.get_ptr() + section->PointerToRawData; const void* source_ptr = source.get_ptr() + section->PointerToRawData;
if (PBYTE(target_ptr) >= (target.get_ptr() + BINARY_PAYLOAD_SIZE)) if (PBYTE(target_ptr) >= (target.get_ptr() + BINARY_PAYLOAD_SIZE))
{ {
throw std::runtime_error("Section exceeds the binary payload size, please increase it!"); throw std::runtime_error("Section exceeds the binary payload size, please increase it!");
} }
if (section->SizeOfRawData > 0) if (section->SizeOfRawData > 0)
{ {
const auto size_of_data = std::min(section->SizeOfRawData, section->Misc.VirtualSize); const auto size_of_data = std::min(section->SizeOfRawData, section->Misc.VirtualSize);
std::memmove(target_ptr, source_ptr, size_of_data); std::memmove(target_ptr, source_ptr, size_of_data);
DWORD old_protect; DWORD old_protect;
VirtualProtect(target_ptr, size_of_data, PAGE_EXECUTE_READWRITE, &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 void loader::load_sections(const utils::nt::module& target, const utils::nt::module& source) const
{ {
for (auto& section : source.get_section_headers()) for (auto& section : source.get_section_headers())
{ {
this->load_section(target, source, section); this->load_section(target, source, section);
} }
} }
void loader::load_imports(const utils::nt::module& target, const utils::nt::module& source) const 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]; const auto import_directory = &source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
auto descriptor = PIMAGE_IMPORT_DESCRIPTOR(target.get_ptr() + import_directory->VirtualAddress); auto descriptor = PIMAGE_IMPORT_DESCRIPTOR(target.get_ptr() + import_directory->VirtualAddress);
while (descriptor->Name) while (descriptor->Name)
{ {
std::string name = LPSTR(target.get_ptr() + 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 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); auto address_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
if (!descriptor->OriginalFirstThunk) if (!descriptor->OriginalFirstThunk)
{ {
name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk); name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
} }
while (*name_table_entry) while (*name_table_entry)
{ {
FARPROC function = nullptr; FARPROC function = nullptr;
std::string function_name; std::string function_name;
// is this an ordinal-only import? // is this an ordinal-only import?
if (IMAGE_SNAP_BY_ORDINAL(*name_table_entry)) if (IMAGE_SNAP_BY_ORDINAL(*name_table_entry))
{ {
auto module = utils::nt::module::load(name); auto module = utils::nt::module::load(name);
if (module) if (module)
{ {
function = GetProcAddress(module, MAKEINTRESOURCEA(IMAGE_ORDINAL(*name_table_entry))); function = GetProcAddress(module, MAKEINTRESOURCEA(IMAGE_ORDINAL(*name_table_entry)));
} }
function_name = "#" + std::to_string(IMAGE_ORDINAL(*name_table_entry)); function_name = "#" + std::to_string(IMAGE_ORDINAL(*name_table_entry));
} }
else else
{ {
auto import = PIMAGE_IMPORT_BY_NAME(target.get_ptr() + *name_table_entry); auto import = PIMAGE_IMPORT_BY_NAME(target.get_ptr() + *name_table_entry);
function_name = import->Name; function_name = import->Name;
if (this->import_resolver_) function = this->import_resolver_(name, function_name); if (this->import_resolver_) function = this->import_resolver_(name, function_name);
if (!function) if (!function)
{ {
auto module = utils::nt::module::load(name); auto module = utils::nt::module::load(name);
if (module) if (module)
{ {
function = GetProcAddress(module, function_name.data()); function = GetProcAddress(module, function_name.data());
} }
} }
} }
if (!function) if (!function)
{ {
throw std::runtime_error(utils::string::va("Unable to load import '%s' from module '%s'", throw std::runtime_error(utils::string::va("Unable to load import '%s' from module '%s'",
function_name.data(), name.data())); function_name.data(), name.data()));
} }
*address_table_entry = reinterpret_cast<uintptr_t>(function); *address_table_entry = reinterpret_cast<uintptr_t>(function);
name_table_entry++; name_table_entry++;
address_table_entry++; address_table_entry++;
} }
descriptor++; descriptor++;
} }
} }

View File

@ -1,22 +1,22 @@
#pragma once #pragma once
#include "utils/nt.hpp" #include "utils/nt.hpp"
#include "launcher/launcher.hpp" #include "launcher/launcher.hpp"
class loader final class loader final
{ {
public: public:
explicit loader(launcher::mode mode); explicit loader(launcher::mode mode);
FARPROC load(const utils::nt::module& module) const; FARPROC load(const utils::nt::module& module) const;
void set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver); void set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver);
private: private:
launcher::mode mode_; launcher::mode mode_;
std::function<FARPROC(const std::string&, const std::string&)> import_resolver_; 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, static void load_section(const utils::nt::module& target, const utils::nt::module& source,
IMAGE_SECTION_HEADER* section); IMAGE_SECTION_HEADER* section);
void load_sections(const utils::nt::module& target, const utils::nt::module& source) const; 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; 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 <std_include.hpp>
#include "module_loader.hpp" #include "module_loader.hpp"
std::vector<std::unique_ptr<module>>* module_loader::modules_ = nullptr; std::vector<std::unique_ptr<module>>* module_loader::modules_ = nullptr;
void module_loader::register_module(std::unique_ptr<module>&& module_) void module_loader::register_module(std::unique_ptr<module>&& module_)
{ {
if (!modules_) if (!modules_)
{ {
modules_ = new std::vector<std::unique_ptr<module>>(); modules_ = new std::vector<std::unique_ptr<module>>();
atexit(destroy_modules); atexit(destroy_modules);
} }
modules_->push_back(std::move(module_)); modules_->push_back(std::move(module_));
} }
bool module_loader::post_start() bool module_loader::post_start()
{ {
static auto handled = false; static auto handled = false;
if (handled || !modules_) return true; if (handled || !modules_) return true;
handled = true; handled = true;
try try
{ {
for (const auto& module_ : *modules_) for (const auto& module_ : *modules_)
{ {
module_->post_start(); module_->post_start();
} }
} }
catch(premature_shutdown_trigger&) catch(premature_shutdown_trigger&)
{ {
return false; return false;
} }
return true; return true;
} }
bool module_loader::post_load() bool module_loader::post_load()
{ {
static auto handled = false; static auto handled = false;
if (handled || !modules_) return true; if (handled || !modules_) return true;
handled = true; handled = true;
try try
{ {
for (const auto& module_ : *modules_) for (const auto& module_ : *modules_)
{ {
module_->post_load(); module_->post_load();
} }
} }
catch (premature_shutdown_trigger&) catch (premature_shutdown_trigger&)
{ {
return false; return false;
} }
return true; return true;
} }
void module_loader::pre_destroy() void module_loader::pre_destroy()
{ {
static auto handled = false; static auto handled = false;
if (handled || !modules_) return; if (handled || !modules_) return;
handled = true; handled = true;
for (const auto& module_ : *modules_) for (const auto& module_ : *modules_)
{ {
module_->pre_destroy(); module_->pre_destroy();
} }
} }
void* module_loader::load_import(const std::string& module, const std::string& function) void* module_loader::load_import(const std::string& module, const std::string& function)
{ {
void* function_ptr = nullptr; void* function_ptr = nullptr;
for (const auto& module_ : *modules_) for (const auto& module_ : *modules_)
{ {
const auto module_function_ptr = module_->load_import(module, function); const auto module_function_ptr = module_->load_import(module, function);
if(module_function_ptr) if(module_function_ptr)
{ {
function_ptr = module_function_ptr; function_ptr = module_function_ptr;
} }
} }
return function_ptr; return function_ptr;
} }
void module_loader::destroy_modules() void module_loader::destroy_modules()
{ {
pre_destroy(); pre_destroy();
if (!modules_) return; if (!modules_) return;
delete modules_; delete modules_;
modules_ = nullptr; modules_ = nullptr;
} }
void module_loader::trigger_premature_shutdown() void module_loader::trigger_premature_shutdown()
{ {
throw premature_shutdown_trigger(); throw premature_shutdown_trigger();
} }

View File

@ -1,132 +1,132 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "launcher/launcher.hpp" #include "launcher/launcher.hpp"
#include "loader/loader.hpp" #include "loader/loader.hpp"
#include "loader/module_loader.hpp" #include "loader/module_loader.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "loader/binary_loader.hpp" #include "loader/binary_loader.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#include "utils/flags.hpp" #include "utils/flags.hpp"
//#define GENERATE_DIFFS //#define GENERATE_DIFFS
DECLSPEC_NORETURN void WINAPI exit_hook(const int code) DECLSPEC_NORETURN void WINAPI exit_hook(const int code)
{ {
module_loader::pre_destroy(); module_loader::pre_destroy();
exit(code); exit(code);
} }
void verify_tls() void verify_tls()
{ {
utils::nt::module self; utils::nt::module self;
const auto self_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(self.get_ptr() + self const auto self_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(self.get_ptr() + self
.get_optional_header() .get_optional_header()
-> ->
DataDirectory DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress); [IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
const auto ref = DWORD(&tls_data); const auto ref = DWORD(&tls_data);
const auto tls_index = *reinterpret_cast<DWORD*>(self_tls->AddressOfIndex); const auto tls_index = *reinterpret_cast<DWORD*>(self_tls->AddressOfIndex);
const auto tls_vector = *reinterpret_cast<DWORD*>(__readfsdword(0x2C) + 4 * tls_index); const auto tls_vector = *reinterpret_cast<DWORD*>(__readfsdword(0x2C) + 4 * tls_index);
const auto offset = ref - tls_vector; const auto offset = ref - tls_vector;
if (offset != 0 && offset != 8) // Actually 8 is bad, but I think msvc places custom stuff before 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!", throw std::runtime_error(utils::string::va("TLS payload is at offset 0x%X, but should be at 0!",
offset)); offset));
} }
} }
launcher::mode detect_mode_from_arguments() launcher::mode detect_mode_from_arguments()
{ {
if (utils::flags::has_flag("dedicated")) if (utils::flags::has_flag("dedicated"))
{ {
return launcher::mode::server; return launcher::mode::server;
} }
if (utils::flags::has_flag("multiplayer")) if (utils::flags::has_flag("multiplayer"))
{ {
return launcher::mode::multiplayer; return launcher::mode::multiplayer;
} }
if (utils::flags::has_flag("singleplayer")) if (utils::flags::has_flag("singleplayer"))
{ {
return launcher::mode::singleplayer; return launcher::mode::singleplayer;
} }
return launcher::mode::none; return launcher::mode::none;
} }
FARPROC load_binary(const launcher::mode mode) FARPROC load_binary(const launcher::mode mode)
{ {
loader loader(mode); loader loader(mode);
utils::nt::module self; utils::nt::module self;
loader.set_import_resolver([self](const std::string& module, const std::string& function) -> FARPROC loader.set_import_resolver([self](const std::string& module, const std::string& function) -> FARPROC
{ {
if (module == "steam_api.dll") if (module == "steam_api.dll")
{ {
return self.get_proc<FARPROC>(function); return self.get_proc<FARPROC>(function);
} }
else if (function == "ExitProcess") else if (function == "ExitProcess")
{ {
return FARPROC(exit_hook); return FARPROC(exit_hook);
} }
return FARPROC(module_loader::load_import(module, function)); return FARPROC(module_loader::load_import(module, function));
}); });
return loader.load(self); return loader.load(self);
} }
int main() int main()
{ {
FARPROC entry_point; FARPROC entry_point;
{ {
auto premature_shutdown = true; auto premature_shutdown = true;
const auto _ = gsl::finally([&premature_shutdown]() const auto _ = gsl::finally([&premature_shutdown]()
{ {
if (premature_shutdown) if (premature_shutdown)
{ {
module_loader::pre_destroy(); module_loader::pre_destroy();
} }
}); });
try try
{ {
#ifdef GENERATE_DIFFS #ifdef GENERATE_DIFFS
binary_loader::create(); binary_loader::create();
return 0; return 0;
#endif #endif
verify_tls(); verify_tls();
if (!module_loader::post_start()) return 0; if (!module_loader::post_start()) return 0;
auto mode = detect_mode_from_arguments(); auto mode = detect_mode_from_arguments();
if (mode == launcher::mode::none) if (mode == launcher::mode::none)
{ {
launcher launcher; launcher launcher;
mode = launcher.run(); mode = launcher.run();
if (mode == launcher::mode::none) return 0; if (mode == launcher::mode::none) return 0;
} }
entry_point = load_binary(mode); entry_point = load_binary(mode);
if (!entry_point) if (!entry_point)
{ {
throw std::runtime_error("Unable to load binary into memory"); throw std::runtime_error("Unable to load binary into memory");
} }
game::initialize(mode); game::initialize(mode);
if (!module_loader::post_load()) return 0; if (!module_loader::post_load()) return 0;
premature_shutdown = false; premature_shutdown = false;
} }
catch (std::exception& e) catch (std::exception& e)
{ {
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR); MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
return 1; return 1;
} }
} }
return entry_point(); return entry_point();
} }

View File

@ -1,90 +1,90 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "loader/module_loader.hpp" #include "loader/module_loader.hpp"
#include "utils/hook.hpp" #include "utils/hook.hpp"
#include "game/game.hpp" #include "game/game.hpp"
class ceg final : public module class ceg final : public module
{ {
public: public:
void post_load() override void post_load() override
{ {
// Only SP has CEG // Only SP has CEG
// CEG in MP has accidentally been removed due to CVE-2018-10718 // CEG in MP has accidentally been removed due to CVE-2018-10718
if (!game::is_sp()) return; if (!game::is_sp()) return;
utils::hook::signature signature(0x401000, 0x3E1000); utils::hook::signature signature(0x401000, 0x3E1000);
signature.add({ signature.add({
"\x56\xE8\x00\x00\x00\x00\x8B\xF0\xE8\x00\x00\x00\x00\x50\x56\xE8", "xx????xxx????xxx", [](char* address) "\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); utils::hook::set<DWORD>(address, 0xC301B0);
} }
}); });
// Generic killer caller. // Generic killer caller.
signature.add({ signature.add({
"\x55\x8B\xEC\x80\x7D\x08\x00\x75\x55", "xxxxxx?xx", [](char* address) "\x55\x8B\xEC\x80\x7D\x08\x00\x75\x55", "xxxxxx?xx", [](char* address)
{ {
utils::hook::set<DWORD>(address, 0xC301B0); utils::hook::set<DWORD>(address, 0xC301B0);
} }
}); });
// CEG initialization. // CEG initialization.
signature.add({ signature.add({
"\x55\x8B\xEC\x83\xEC\x18\x53\x56\x57\xE8\x00\x00\x00\x00", "xxxxxxxxxx????", [](char* address) "\x55\x8B\xEC\x83\xEC\x18\x53\x56\x57\xE8\x00\x00\x00\x00", "xxxxxxxxxx????", [](char* address)
{ {
utils::hook::set<BYTE>(address, 0xC3); utils::hook::set<BYTE>(address, 0xC3);
} }
}); });
// Some odd trap. // Some odd trap.
signature.add({ signature.add({
"\x55\x8B\xEC\x81\xEC\x00\x00\x00\x00\x53\x56\x57\x8B\x3D", "xxxxx??xxxxxxx", [](char* address) "\x55\x8B\xEC\x81\xEC\x00\x00\x00\x00\x53\x56\x57\x8B\x3D", "xxxxx??xxxxxxx", [](char* address)
{ {
utils::hook::set<DWORD>(address, 0xC301B0); utils::hook::set<DWORD>(address, 0xC301B0);
} }
}); });
// Custom shit // Custom shit
signature.add({ 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", "\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) "xxxx????x????xxx????xxx????x", [](char* address)
{ {
utils::hook::set<BYTE>(address, 0xC3); utils::hook::set<BYTE>(address, 0xC3);
} }
}); });
// hkcr guid check // hkcr guid check
signature.add({ signature.add({
"\x55\x8B\xEC\xB8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x84\xC0\x75\x06", "\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) "xxxx????x????x????xxxx", [](char* address)
{ {
utils::hook::nop(address + 0xD, 5); // Call utils::hook::nop(address + 0xD, 5); // Call
utils::hook::nop(address + 0x14, 2); // Jump utils::hook::nop(address + 0x14, 2); // Jump
} }
}); });
// hkcr guid check 2 // hkcr guid check 2
signature.add({ signature.add({
"\x55\x8B\xEC\x81\xEC\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x84\xC0\x75\x06", "xxxxx????x????xxxx", [ "\x55\x8B\xEC\x81\xEC\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x84\xC0\x75\x06", "xxxxx????x????xxxx", [
](char* address) ](char* address)
{ {
utils::hook::nop(address + 0x9, 5); // Call utils::hook::nop(address + 0x9, 5); // Call
utils::hook::nop(address + 0x10, 2); // Jump utils::hook::nop(address + 0x10, 2); // Jump
} }
}); });
signature.process(); signature.process();
// Function fixup // Function fixup
utils::hook(0x4CA310, game::native::DB_LoadXAssets, HOOK_JUMP).install()->quick(); utils::hook(0x4CA310, game::native::DB_LoadXAssets, HOOK_JUMP).install()->quick();
// Some value obfuscation // Some value obfuscation
utils::hook(0x493B81, 0x493BFC, HOOK_JUMP).install()->quick(); utils::hook(0x493B81, 0x493BFC, HOOK_JUMP).install()->quick();
// CEG uninitialization // CEG uninitialization
utils::hook::set<BYTE>(0x527110, 0xC3); utils::hook::set<BYTE>(0x527110, 0xC3);
} }
}; };
REGISTER_MODULE(ceg) REGISTER_MODULE(ceg)

View File

@ -1,115 +1,115 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "loader/module_loader.hpp" #include "loader/module_loader.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "scheduler.hpp" #include "scheduler.hpp"
class console final : public module class console final : public module
{ {
public: public:
console() console()
{ {
ShowWindow(GetConsoleWindow(), SW_HIDE); ShowWindow(GetConsoleWindow(), SW_HIDE);
_pipe(this->handles_, 1024, _O_TEXT); _pipe(this->handles_, 1024, _O_TEXT);
_dup2(this->handles_[1], 1); _dup2(this->handles_[1], 1);
_dup2(this->handles_[1], 2); _dup2(this->handles_[1], 2);
//setvbuf(stdout, nullptr, _IONBF, 0); //setvbuf(stdout, nullptr, _IONBF, 0);
//setvbuf(stderr, nullptr, _IONBF, 0); //setvbuf(stderr, nullptr, _IONBF, 0);
} }
void post_start() override void post_start() override
{ {
scheduler::on_frame(std::bind(&console::log_messages, this)); scheduler::on_frame(std::bind(&console::log_messages, this));
this->console_runner_ = std::thread(std::bind(&console::runner, this)); this->console_runner_ = std::thread(std::bind(&console::runner, this));
} }
void pre_destroy() override void pre_destroy() override
{ {
this->terminate_runner_ = true; this->terminate_runner_ = true;
printf("\r\n"); printf("\r\n");
_flushall(); _flushall();
_close(this->handles_[0]); _close(this->handles_[0]);
_close(this->handles_[1]); _close(this->handles_[1]);
if (this->console_runner_.joinable()) if (this->console_runner_.joinable())
{ {
this->console_runner_.join(); this->console_runner_.join();
} }
} }
void post_load() override void post_load() override
{ {
if (!game::is_dedi()) if (!game::is_dedi())
{ {
game::native::Sys_ShowConsole(); game::native::Sys_ShowConsole();
} }
std::lock_guard _(this->mutex_); std::lock_guard _(this->mutex_);
this->console_initialized_ = true; this->console_initialized_ = true;
} }
private: private:
bool console_initialized_ = false; bool console_initialized_ = false;
bool terminate_runner_ = false; bool terminate_runner_ = false;
std::mutex mutex_; std::mutex mutex_;
std::thread console_runner_; std::thread console_runner_;
std::queue<std::string> message_queue_; std::queue<std::string> message_queue_;
int handles_[2]{}; int handles_[2]{};
void log_messages() void log_messages()
{ {
while (this->console_initialized_ && !this->message_queue_.empty()) while (this->console_initialized_ && !this->message_queue_.empty())
{ {
std::queue<std::string> message_queue_copy; std::queue<std::string> message_queue_copy;
{ {
std::lock_guard _(this->mutex_); std::lock_guard _(this->mutex_);
message_queue_copy = this->message_queue_; message_queue_copy = this->message_queue_;
this->message_queue_ = {}; this->message_queue_ = {};
} }
while (!message_queue_copy.empty()) while (!message_queue_copy.empty())
{ {
log_message(message_queue_copy.front()); log_message(message_queue_copy.front());
message_queue_copy.pop(); message_queue_copy.pop();
} }
} }
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
} }
static void log_message(const std::string& message) static void log_message(const std::string& message)
{ {
OutputDebugStringA(message.data()); OutputDebugStringA(message.data());
game::native::Conbuf_AppendText(message.data()); game::native::Conbuf_AppendText(message.data());
} }
void runner() void runner()
{ {
char buffer[1024]; char buffer[1024];
while (!this->terminate_runner_ && this->handles_[0]) while (!this->terminate_runner_ && this->handles_[0])
{ {
const auto len = _read(this->handles_[0], buffer, sizeof(buffer)); const auto len = _read(this->handles_[0], buffer, sizeof(buffer));
if (len > 0) if (len > 0)
{ {
std::lock_guard _(this->mutex_); std::lock_guard _(this->mutex_);
this->message_queue_.push(std::string(buffer, len)); this->message_queue_.push(std::string(buffer, len));
} }
else else
{ {
std::this_thread::sleep_for(10ms); std::this_thread::sleep_for(10ms);
} }
} }
std::this_thread::yield(); std::this_thread::yield();
} }
}; };
REGISTER_MODULE(console) REGISTER_MODULE(console)

View File

@ -1,50 +1,50 @@
#include <std_include.hpp> #include <std_include.hpp>
#include <discord_rpc.h> #include <discord_rpc.h>
#include "loader/module_loader.hpp" #include "loader/module_loader.hpp"
#include "scheduler.hpp" #include "scheduler.hpp"
#include "game/game.hpp" #include "game/game.hpp"
class discord final : public module class discord final : public module
{ {
public: public:
void post_load() override void post_load() override
{ {
if (game::is_dedi()) return; if (game::is_dedi()) return;
DiscordEventHandlers handlers; DiscordEventHandlers handlers;
ZeroMemory(&handlers, sizeof(handlers)); ZeroMemory(&handlers, sizeof(handlers));
handlers.ready = ready; handlers.ready = ready;
handlers.errored = errored; handlers.errored = errored;
handlers.disconnected = errored; handlers.disconnected = errored;
handlers.joinGame = nullptr; handlers.joinGame = nullptr;
handlers.spectateGame = nullptr; handlers.spectateGame = nullptr;
handlers.joinRequest = nullptr; handlers.joinRequest = nullptr;
Discord_Initialize("531526691319971880", &handlers, 1, nullptr); Discord_Initialize("531526691319971880", &handlers, 1, nullptr);
scheduler::on_frame(Discord_RunCallbacks); scheduler::on_frame(Discord_RunCallbacks);
} }
void pre_destroy() override void pre_destroy() override
{ {
Discord_Shutdown(); Discord_Shutdown();
} }
private: private:
static void ready(const DiscordUser* request) static void ready(const DiscordUser* request)
{ {
DiscordRichPresence discord_presence; DiscordRichPresence discord_presence;
ZeroMemory(&discord_presence, sizeof(discord_presence)); ZeroMemory(&discord_presence, sizeof(discord_presence));
discord_presence.state = game::is_mp() ? "Multiplayer" : "Singleplayer"; discord_presence.state = game::is_mp() ? "Multiplayer" : "Singleplayer";
discord_presence.instance = 1; discord_presence.instance = 1;
Discord_UpdatePresence(&discord_presence); Discord_UpdatePresence(&discord_presence);
} }
static void errored(const int error_code, const char* message) static void errored(const int error_code, const char* message)
{ {
printf("Discord: (%i) %s", error_code, message); printf("Discord: (%i) %s", error_code, message);
} }
}; };
//REGISTER_MODULE(discord) //REGISTER_MODULE(discord)

View File

@ -1,60 +1,60 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "loader/module_loader.hpp" #include "loader/module_loader.hpp"
#include "game/structs.hpp" #include "game/structs.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "utils/hook.hpp" #include "utils/hook.hpp"
static __declspec(naked) void db_load_stub_client(game::native::XZoneInfo*, unsigned int, int) static __declspec(naked) void db_load_stub_client(game::native::XZoneInfo*, unsigned int, int)
{ {
__asm __asm
{ {
sub esp, 0Ch sub esp, 0Ch
mov eax, [esp + 18h] mov eax, [esp + 18h]
mov ecx, game::native::DB_LoadXAssets mov ecx, game::native::DB_LoadXAssets
add ecx, 7h add ecx, 7h
push ecx push ecx
retn retn
} }
} }
static __declspec(naked) void db_load_stub_server(game::native::XZoneInfo*, unsigned int, int) static __declspec(naked) void db_load_stub_server(game::native::XZoneInfo*, unsigned int, int)
{ {
__asm __asm
{ {
sub esp, 10h sub esp, 10h
mov eax, [esp + 1Ch] mov eax, [esp + 1Ch]
mov ecx, game::native::DB_LoadXAssets mov ecx, game::native::DB_LoadXAssets
add ecx, 7h add ecx, 7h
push ecx push ecx
retn retn
} }
} }
class fastfiles final : public module class fastfiles final : public module
{ {
public: public:
void post_load() override void post_load() override
{ {
utils::hook(game::native::DB_LoadXAssets, db_load_stub, HOOK_JUMP).install()->quick(); utils::hook(game::native::DB_LoadXAssets, db_load_stub, HOOK_JUMP).install()->quick();
} }
private: private:
static void db_load_stub(game::native::XZoneInfo* zone_info, const unsigned int zone_count, const int sync) 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) for (unsigned int i = 0; i < zone_count; ++i)
{ {
if (zone_info[i].name) if (zone_info[i].name)
{ {
printf("Loading FastFile: %s (0x%X | 0x%X)\n", zone_info[i].name, zone_info[i].allocFlags, printf("Loading FastFile: %s (0x%X | 0x%X)\n", zone_info[i].name, zone_info[i].allocFlags,
zone_info[i].freeFlags); zone_info[i].freeFlags);
} }
} }
if (game::is_dedi()) return db_load_stub_server(zone_info, zone_count, sync); 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); else return db_load_stub_client(zone_info, zone_count, sync);
} }
}; };
REGISTER_MODULE(fastfiles) REGISTER_MODULE(fastfiles)

View File

@ -1,37 +1,37 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "loader/module_loader.hpp" #include "loader/module_loader.hpp"
#include "utils/hook.hpp" #include "utils/hook.hpp"
#include "game/game.hpp" #include "game/game.hpp"
class fov final : public module class fov final : public module
{ {
public: public:
void post_load() override void post_load() override
{ {
if (game::is_dedi()) return; if (game::is_dedi()) return;
// Set dvar flag // Set dvar flag
utils::hook::set<BYTE>(SELECT_VALUE(0x4302C5, 0x455155, 0), 0x1 | (game::is_mp() ? 0x40 : 0)); utils::hook::set<BYTE>(SELECT_VALUE(0x4302C5, 0x455155, 0), 0x1 | (game::is_mp() ? 0x40 : 0));
if (game::is_mp()) if (game::is_mp())
{ {
// Set dvar limit // Set dvar limit
static const auto cg_fov_limit = 90.0f; static const auto cg_fov_limit = 90.0f;
utils::hook::set(0x455148, &cg_fov_limit); utils::hook::set(0x455148, &cg_fov_limit);
// Prevent value change via internal scripts // Prevent value change via internal scripts
utils::hook(0x4698BA, &set_server_command_dvar_stub, HOOK_CALL).install()->quick(); utils::hook(0x4698BA, &set_server_command_dvar_stub, HOOK_CALL).install()->quick();
} }
} }
private: private:
static void set_server_command_dvar_stub(const char* dvar, const char* value) static void set_server_command_dvar_stub(const char* dvar, const char* value)
{ {
if (strcmp(dvar, "cg_fov") != 0 || strcmp(value, "65") != 0) if (strcmp(dvar, "cg_fov") != 0 || strcmp(value, "65") != 0)
{ {
game::native::Dvar_SetFromStringByName(dvar, value); game::native::Dvar_SetFromStringByName(dvar, value);
} }
} }
}; };
REGISTER_MODULE(fov) REGISTER_MODULE(fov)

View File

@ -1,61 +1,61 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "loader/module_loader.hpp" #include "loader/module_loader.hpp"
#include "utils/hook.hpp" #include "utils/hook.hpp"
#include "game/game.hpp" #include "game/game.hpp"
class patches final : public module class patches final : public module
{ {
public: public:
void post_load() override void post_load() override
{ {
if (!game::is_dedi()) this->patch_clients(); if (!game::is_dedi()) this->patch_clients();
if (game::is_sp()) this->patch_sp(); if (game::is_sp()) this->patch_sp();
else if (game::is_mp()) this->patch_mp(); else if (game::is_mp()) this->patch_mp();
else if (game::is_dedi()) this->patch_dedi(); else if (game::is_dedi()) this->patch_dedi();
utils::hook(game::native::_longjmp, long_jump_stub, HOOK_JUMP).install()->quick(); utils::hook(game::native::_longjmp, long_jump_stub, HOOK_JUMP).install()->quick();
} }
private: private:
void patch_clients() const void patch_clients() const
{ {
// Remove improper quit check // Remove improper quit check
utils::hook::nop(SELECT_VALUE(0x53444A, 0x5CCDC0, 0), 9); utils::hook::nop(SELECT_VALUE(0x53444A, 0x5CCDC0, 0), 9);
// Ignore sdm files // Ignore sdm files
utils::hook::nop(SELECT_VALUE(0x4438BA, 0x6371EA, 0), 2); utils::hook::nop(SELECT_VALUE(0x4438BA, 0x6371EA, 0), 2);
} }
void patch_sp() const void patch_sp() const
{ {
// SP doesn't initialize WSA // SP doesn't initialize WSA
WSADATA wsa_data; WSADATA wsa_data;
WSAStartup(MAKEWORD(2, 2), &wsa_data); WSAStartup(MAKEWORD(2, 2), &wsa_data);
// Disable remote storage // Disable remote storage
utils::hook::set<BYTE>(0x663B5A, 0xEB); utils::hook::set<BYTE>(0x663B5A, 0xEB);
utils::hook::set<BYTE>(0x663C54, 0xEB); utils::hook::set<BYTE>(0x663C54, 0xEB);
} }
void patch_mp() const void patch_mp() const
{ {
} }
void patch_dedi() const void patch_dedi() const
{ {
} }
static __declspec(noreturn) void long_jump_stub(jmp_buf buf, const int value) noexcept(false) static __declspec(noreturn) void long_jump_stub(jmp_buf buf, const int value) noexcept(false)
{ {
#ifdef DEBUG #ifdef DEBUG
{ {
printf("Unwinding the stack...\n"); printf("Unwinding the stack...\n");
} }
#endif #endif
longjmp(buf, value); longjmp(buf, value);
} }
}; };
REGISTER_MODULE(patches) REGISTER_MODULE(patches)

View File

@ -1,162 +1,162 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "loader/module_loader.hpp" #include "loader/module_loader.hpp"
#include "utils/hook.hpp" #include "utils/hook.hpp"
#include "utils/io.hpp" #include "utils/io.hpp"
#include "game/scripting/context.hpp" #include "game/scripting/context.hpp"
#include "scheduler.hpp" #include "scheduler.hpp"
class scripting final : public module class scripting final : public module
{ {
public: public:
void post_load() override void post_load() override
{ {
start_hook_.initialize(SELECT_VALUE(0x50C575, 0x50D4F2, 0x48A026), &start_execution_stub, HOOK_CALL) // start_hook_.initialize(SELECT_VALUE(0x50C575, 0x50D4F2, 0x48A026), &start_execution_stub, HOOK_CALL) //
->install() // ->install() //
->quick(); ->quick();
stop_hook_.initialize(SELECT_VALUE(0x528B04, 0x569E46, 0x4F03FA), &stop_execution_stub, HOOK_CALL) // stop_hook_.initialize(SELECT_VALUE(0x528B04, 0x569E46, 0x4F03FA), &stop_execution_stub, HOOK_CALL) //
->install() // ->install() //
->quick(); ->quick();
utils::hook(SELECT_VALUE(0x4F9706, 0x5772A0, 0x4FAB88), &frame_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(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(0x6109F3, 0x56B637, 0x4EDFF7), &vm_notify_stub, HOOK_CALL).install()->quick();
utils::hook(SELECT_VALUE(0x6128BE, 0x56D541, 0x4EFAF9), &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()) if (game::is_sp())
{ {
utils::hook(0x50C57E, &frame_stub, HOOK_CALL).install()->quick(); utils::hook(0x50C57E, &frame_stub, HOOK_CALL).install()->quick();
utils::hook(0x6523A3, &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(0x5145D2, &frame_stub, HOOK_CALL).install()->quick();
utils::hook(0x610970, &vm_notify_stub, HOOK_JUMP).install()->quick(); utils::hook(0x610970, &vm_notify_stub, HOOK_JUMP).install()->quick();
} }
} }
void pre_destroy() override void pre_destroy() override
{ {
this->scripts_.clear(); this->scripts_.clear();
} }
private: private:
std::vector<std::unique_ptr<game::scripting::context>> scripts_; std::vector<std::unique_ptr<game::scripting::context>> scripts_;
void load_scripts() void load_scripts()
{ {
const auto scripts = utils::io::list_files("open-iw5/scripts/"); const auto scripts = utils::io::list_files("open-iw5/scripts/");
for (const auto& script : scripts) for (const auto& script : scripts)
{ {
if (script.substr(script.find_last_of('.') + 1) == "chai") if (script.substr(script.find_last_of('.') + 1) == "chai")
{ {
try try
{ {
auto context = std::make_unique<game::scripting::context>(); auto context = std::make_unique<game::scripting::context>();
context->get_chai()->eval_file(script); context->get_chai()->eval_file(script);
this->scripts_.push_back(std::move(context)); this->scripts_.push_back(std::move(context));
} }
catch (chaiscript::exception::eval_error& e) catch (chaiscript::exception::eval_error& e)
{ {
throw std::runtime_error(e.pretty_print()); throw std::runtime_error(e.pretty_print());
} }
} }
} }
} }
void start_execution() void start_execution()
{ {
try try
{ {
this->load_scripts(); this->load_scripts();
} }
catch (std::exception& e) catch (std::exception& e)
{ {
propagate_error(e); propagate_error(e);
} }
} }
void stop_execution() void stop_execution()
{ {
this->scripts_.clear(); this->scripts_.clear();
} }
void run_frame() void run_frame()
{ {
for (const auto& script : this->scripts_) for (const auto& script : this->scripts_)
{ {
script->get_scheduler()->run_frame(); script->get_scheduler()->run_frame();
} }
} }
void dispatch(game::scripting::event* event) void dispatch(game::scripting::event* event)
{ {
for (const auto& script : this->scripts_) for (const auto& script : this->scripts_)
{ {
script->get_event_handler()->dispatch(event); script->get_event_handler()->dispatch(event);
} }
} }
static utils::hook start_hook_; static utils::hook start_hook_;
static utils::hook stop_hook_; static utils::hook stop_hook_;
static void propagate_error(const std::exception& e) static void propagate_error(const std::exception& e)
{ {
printf("\n******* Script execution error *******\n"); printf("\n******* Script execution error *******\n");
printf("%s\n", e.what()); printf("%s\n", e.what());
printf("**************************************\n\n"); printf("**************************************\n\n");
scheduler::error("Script execution error\n(see console for actual details)\n", 5); scheduler::error("Script execution error\n(see console for actual details)\n", 5);
} }
static void start_execution_stub() static void start_execution_stub()
{ {
module_loader::get<scripting>()->start_execution(); module_loader::get<scripting>()->start_execution();
reinterpret_cast<void(*)()>(start_hook_.get_original())(); reinterpret_cast<void(*)()>(start_hook_.get_original())();
} }
static void stop_execution_stub() static void stop_execution_stub()
{ {
module_loader::get<scripting>()->stop_execution(); module_loader::get<scripting>()->stop_execution();
reinterpret_cast<void(*)()>(stop_hook_.get_original())(); reinterpret_cast<void(*)()>(stop_hook_.get_original())();
} }
static void vm_notify_stub(const unsigned int notify_id, const unsigned short type, static void vm_notify_stub(const unsigned int notify_id, const unsigned short type,
game::native::VariableValue* stack) game::native::VariableValue* stack)
{ {
try try
{ {
game::scripting::event e; game::scripting::event e;
e.name = game::native::SL_ConvertToString(type); e.name = game::native::SL_ConvertToString(type);
e.entity_id = notify_id; e.entity_id = notify_id;
if (e.name == "touch") return; // Skip that for now if (e.name == "touch") return; // Skip that for now
//printf("%X: %s\n", e.entity_id, e.name.data()); //printf("%X: %s\n", e.entity_id, e.name.data());
for (auto value = stack; value->type != game::native::SCRIPT_END; --value) for (auto value = stack; value->type != game::native::SCRIPT_END; --value)
{ {
e.arguments.emplace_back(*value); e.arguments.emplace_back(*value);
} }
module_loader::get<scripting>()->dispatch(&e); module_loader::get<scripting>()->dispatch(&e);
} }
catch (std::exception& e) catch (std::exception& e)
{ {
propagate_error(e); propagate_error(e);
} }
game::native::VM_Notify(notify_id, type, stack); game::native::VM_Notify(notify_id, type, stack);
} }
static int frame_stub(int a1, int a2) static int frame_stub(int a1, int a2)
{ {
module_loader::get<scripting>()->run_frame(); module_loader::get<scripting>()->run_frame();
return game::native::G_RunFrame(a1, a2); return game::native::G_RunFrame(a1, a2);
} }
}; };
utils::hook scripting::start_hook_; utils::hook scripting::start_hook_;
utils::hook scripting::stop_hook_; utils::hook scripting::stop_hook_;
REGISTER_MODULE(scripting) REGISTER_MODULE(scripting)

View File

@ -1,25 +1,25 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "loader/module_loader.hpp" #include "loader/module_loader.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "utils/hook.hpp" #include "utils/hook.hpp"
class security final : public module class security final : public module
{ {
public: public:
void post_load() override void post_load() override
{ {
if(game::is_mp()) if(game::is_mp())
{ {
utils::hook(0x4AECD4, read_p2p_auth_ticket_stub, HOOK_JUMP).install()->quick(); utils::hook(0x4AECD4, read_p2p_auth_ticket_stub, HOOK_JUMP).install()->quick();
} }
} }
private: private:
static void read_p2p_auth_ticket_stub(game::native::msg_t* msg, void* data, const int len) static void read_p2p_auth_ticket_stub(game::native::msg_t* msg, void* data, const int len)
{ {
if (len < 0) return; if (len < 0) return;
return game::native::MSG_ReadData(msg, data, std::min(len, 200)); return game::native::MSG_ReadData(msg, data, std::min(len, 200));
} }
}; };
REGISTER_MODULE(security) REGISTER_MODULE(security)

View File

@ -1,178 +1,178 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "loader/module_loader.hpp" #include "loader/module_loader.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "utils/nt.hpp" #include "utils/nt.hpp"
#include "steam/steam.hpp" #include "steam/steam.hpp"
#include "steam/interface.hpp" #include "steam/interface.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#include "scheduler.hpp" #include "scheduler.hpp"
class steam_proxy final : public module class steam_proxy final : public module
{ {
public: public:
void post_start() override void post_start() override
{ {
if (game::is_dedi()) return; if (game::is_dedi()) return;
this->run_mod(); this->run_mod();
this->load_client(); this->load_client();
this->clean_up_on_error(); this->clean_up_on_error();
} }
void post_load() override void post_load() override
{ {
if (game::is_dedi()) return; if (game::is_dedi()) return;
try try
{ {
if (game::is_sp()) if (game::is_sp())
{ {
this->start_mod("Open-IW5 Singleplayer", 42680); this->start_mod("Open-IW5 Singleplayer", 42680);
} }
else if (game::is_mp()) else if (game::is_mp())
{ {
this->start_mod("Open-IW5 Multiplayer", 42690); this->start_mod("Open-IW5 Multiplayer", 42690);
} }
} }
catch (std::exception& e) catch (std::exception& e)
{ {
printf("Steam: %s\n", e.what()); printf("Steam: %s\n", e.what());
} }
} }
void pre_destroy() override void pre_destroy() override
{ {
if (this->steam_client_module_) if (this->steam_client_module_)
{ {
if (this->steam_pipe_) if (this->steam_pipe_)
{ {
if (this->global_user_) if (this->global_user_)
{ {
this->steam_client_module_.invoke<void>("Steam_ReleaseUser", this->steam_pipe_, 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_); this->steam_client_module_.invoke<bool>("Steam_BReleaseSteamPipe", this->steam_pipe_);
} }
} }
} }
private: private:
utils::nt::module steam_client_module_; utils::nt::module steam_client_module_;
steam::interface client_engine_; steam::interface client_engine_;
steam::interface client_user_; steam::interface client_user_;
steam::interface client_utils_; steam::interface client_utils_;
void* steam_pipe_ = nullptr; void* steam_pipe_ = nullptr;
void* global_user_ = nullptr; void* global_user_ = nullptr;
void run_mod() const void run_mod() const
{ {
const auto command = "-proc "; const auto command = "-proc ";
const char* parent_proc = strstr(GetCommandLineA(), command); const char* parent_proc = strstr(GetCommandLineA(), command);
if (parent_proc) if (parent_proc)
{ {
const auto pid = atoi(parent_proc + strlen(command)); const auto pid = atoi(parent_proc + strlen(command));
const auto process_handle = OpenProcess(SYNCHRONIZE, FALSE, pid); const auto process_handle = OpenProcess(SYNCHRONIZE, FALSE, pid);
if (process_handle && process_handle != INVALID_HANDLE_VALUE) if (process_handle && process_handle != INVALID_HANDLE_VALUE)
{ {
WaitForSingleObject(process_handle, INFINITE); WaitForSingleObject(process_handle, INFINITE);
CloseHandle(process_handle); CloseHandle(process_handle);
} }
module_loader::trigger_premature_shutdown(); module_loader::trigger_premature_shutdown();
} }
} }
void* load_client_engine() const void* load_client_engine() const
{ {
if (!this->steam_client_module_) return nullptr; if (!this->steam_client_module_) return nullptr;
for (auto i = 1; i > 0; ++i) for (auto i = 1; i > 0; ++i)
{ {
std::string name = utils::string::va("CLIENTENGINE_INTERFACE_VERSION%03i", i); std::string name = utils::string::va("CLIENTENGINE_INTERFACE_VERSION%03i", i);
const auto client_engine = this->steam_client_module_ const auto client_engine = this->steam_client_module_
.invoke<void*>("CreateInterface", name.data(), nullptr); .invoke<void*>("CreateInterface", name.data(), nullptr);
if (client_engine) return client_engine; if (client_engine) return client_engine;
} }
return nullptr; return nullptr;
} }
void load_client() void load_client()
{ {
const auto steam_path = ::steam::get_steam_install_directory(); const auto steam_path = ::steam::get_steam_install_directory();
if (steam_path.empty()) return; if (steam_path.empty()) return;
utils::nt::module::load(steam_path + "tier0_s.dll"); utils::nt::module::load(steam_path + "tier0_s.dll");
utils::nt::module::load(steam_path + "vstdlib_s.dll"); utils::nt::module::load(steam_path + "vstdlib_s.dll");
this->steam_client_module_ = utils::nt::module::load(steam_path + "steamclient.dll"); this->steam_client_module_ = utils::nt::module::load(steam_path + "steamclient.dll");
if (!this->steam_client_module_) return; if (!this->steam_client_module_) return;
this->client_engine_ = load_client_engine(); this->client_engine_ = load_client_engine();
if (!this->client_engine_) return; if (!this->client_engine_) return;
this->steam_pipe_ = this->steam_client_module_.invoke<void*>("Steam_CreateSteamPipe"); 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->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_, this->client_user_ = this->client_engine_.invoke<void*>(8, this->steam_pipe_, this->global_user_,
"CLIENTUSER_INTERFACE_VERSION001"); // GetIClientUser "CLIENTUSER_INTERFACE_VERSION001"); // GetIClientUser
this->client_utils_ = this->client_engine_.invoke<void*>(13, this->steam_pipe_, this->client_utils_ = this->client_engine_.invoke<void*>(13, this->steam_pipe_,
"CLIENTUTILS_INTERFACE_VERSION001"); // GetIClientUtils "CLIENTUTILS_INTERFACE_VERSION001"); // GetIClientUtils
} }
void start_mod(const std::string& title, size_t app_id) void start_mod(const std::string& title, size_t app_id)
{ {
if (!this->client_utils_ || !this->client_user_) return; if (!this->client_utils_ || !this->client_user_) return;
if (!this->client_user_.invoke<bool>("BIsSubscribedApp", app_id)) if (!this->client_user_.invoke<bool>("BIsSubscribedApp", app_id))
{ {
app_id = 480; // Spacewar app_id = 480; // Spacewar
} }
this->client_utils_.invoke<void>("SetAppIDForCurrentPipe", app_id, false); this->client_utils_.invoke<void>("SetAppIDForCurrentPipe", app_id, false);
utils::nt::module self; utils::nt::module self;
const auto path = self.get_path(); const auto path = self.get_path();
char our_directory[MAX_PATH] = {0}; char our_directory[MAX_PATH] = {0};
GetCurrentDirectoryA(sizeof(our_directory), our_directory); GetCurrentDirectoryA(sizeof(our_directory), our_directory);
const std::string cmdline = utils::string::va("\"%s\" -proc %d", path.data(), GetCurrentProcessId()); const std::string cmdline = utils::string::va("\"%s\" -proc %d", path.data(), GetCurrentProcessId());
game_id game_id; game_id game_id;
game_id.raw.type = 1; // k_EGameIDTypeGameMod game_id.raw.type = 1; // k_EGameIDTypeGameMod
game_id.raw.app_id = app_id & 0xFFFFFF; game_id.raw.app_id = app_id & 0xFFFFFF;
const auto mod_id = "OIW5"; const auto mod_id = "OIW5";
game_id.raw.mod_id = *reinterpret_cast<const unsigned int*>(mod_id) | 0x80000000; 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, this->client_user_.invoke<bool>("SpawnProcess", self.get_path().data(), cmdline.data(), 0, our_directory,
game_id.bits, title.data(), app_id, 0, 0); game_id.bits, title.data(), app_id, 0, 0);
} }
void clean_up_on_error() void clean_up_on_error()
{ {
if (this->steam_client_module_ if (this->steam_client_module_
&& this->steam_pipe_ && this->steam_pipe_
&& this->global_user_ && this->global_user_
&& this->steam_client_module_.invoke<bool>("Steam_BConnected", this->global_user_, this->steam_pipe_) && 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_)) && 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)); scheduler::once(std::bind(&steam_proxy::clean_up_on_error, this));
return; return;
} }
this->client_engine_ = nullptr; this->client_engine_ = nullptr;
this->client_user_ = nullptr; this->client_user_ = nullptr;
this->client_utils_ = nullptr; this->client_utils_ = nullptr;
this->steam_pipe_ = nullptr; this->steam_pipe_ = nullptr;
this->global_user_ = nullptr; this->global_user_ = nullptr;
this->steam_client_module_ = utils::nt::module{nullptr}; this->steam_client_module_ = utils::nt::module{nullptr};
} }
}; };
//REGISTER_MODULE(steam_proxy) //REGISTER_MODULE(steam_proxy)

View File

@ -1,16 +1,16 @@
#pragma once #pragma once
#define BINARY_SP 300 #define BINARY_SP 300
#define BINARY_MP 301 #define BINARY_MP 301
#define DW_HEATMAP 302 #define DW_HEATMAP 302
#define DW_MOTD 303 #define DW_MOTD 303
#define DW_IMG 304 #define DW_IMG 304
#define DW_WAD 305 #define DW_WAD 305
#define DW_PLAYLIST 306 #define DW_PLAYLIST 306
#define DW_CONFIG 307 #define DW_CONFIG 307
#define DW_IOTD_TXT 308 #define DW_IOTD_TXT 308
#define DW_IOTD_IMG 309 #define DW_IOTD_IMG 309
#define MENU_MAIN 310 #define MENU_MAIN 310
#define MENU_SETTINGS 311 #define MENU_SETTINGS 311

View File

@ -1,117 +1,117 @@
// Microsoft Visual C++ generated resource script. // Microsoft Visual C++ generated resource script.
// //
#pragma code_page(65001) #pragma code_page(65001)
#define APSTUDIO_READONLY_SYMBOLS #define APSTUDIO_READONLY_SYMBOLS
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Generated from the TEXTINCLUDE 2 resource. // Generated from the TEXTINCLUDE 2 resource.
// //
#include "windows.h" #include "windows.h"
#include "resource.hpp" #include "resource.hpp"
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS #undef APSTUDIO_READONLY_SYMBOLS
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// English (United States) resources // English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// TEXTINCLUDE // TEXTINCLUDE
// //
1 TEXTINCLUDE 1 TEXTINCLUDE
BEGIN BEGIN
"#include ""windows.h""\r\n" "#include ""windows.h""\r\n"
"\0" "\0"
END END
2 TEXTINCLUDE 2 TEXTINCLUDE
BEGIN BEGIN
"\r\n" "\r\n"
"\0" "\0"
END END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Version // Version
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0 FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0 PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
#else #else
FILEFLAGS 0x0L FILEFLAGS 0x0L
#endif #endif
FILEOS 0x40004L FILEOS 0x40004L
FILETYPE VFT_DLL FILETYPE VFT_DLL
FILESUBTYPE 0x0L FILESUBTYPE 0x0L
BEGIN BEGIN
BLOCK "StringFileInfo" BLOCK "StringFileInfo"
BEGIN BEGIN
BLOCK "040904b0" BLOCK "040904b0"
BEGIN BEGIN
VALUE "CompanyName", "momo5502" VALUE "CompanyName", "momo5502"
VALUE "FileDescription", "Open-IW5" VALUE "FileDescription", "Open-IW5"
VALUE "FileVersion", "1.0.0.0" VALUE "FileVersion", "1.0.0.0"
VALUE "InternalName", "Open-IW5" VALUE "InternalName", "Open-IW5"
VALUE "LegalCopyright", "All rights reserved." VALUE "LegalCopyright", "All rights reserved."
VALUE "OriginalFilename", "open-iw5.exe" VALUE "OriginalFilename", "open-iw5.exe"
VALUE "ProductName", "open-iw5" VALUE "ProductName", "open-iw5"
VALUE "ProductVersion", "1.0.0.0" VALUE "ProductVersion", "1.0.0.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
BEGIN BEGIN
VALUE "Translation", 0x409, 1200 VALUE "Translation", 0x409, 1200
END END
END END
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Binary Data // Binary Data
// //
102 ICON "resources/icon.ico" 102 ICON "resources/icon.ico"
BINARY_SP RCDATA "resources/iw5sp.exe.diff" BINARY_SP RCDATA "resources/iw5sp.exe.diff"
BINARY_MP RCDATA "resources/iw5mp.exe.diff" BINARY_MP RCDATA "resources/iw5mp.exe.diff"
DW_HEATMAP RCDATA "resources/dw/heatmap.raw" DW_HEATMAP RCDATA "resources/dw/heatmap.raw"
DW_MOTD RCDATA "resources/dw/motd-english.txt" DW_MOTD RCDATA "resources/dw/motd-english.txt"
DW_IMG RCDATA "resources/dw/online_mp.img" DW_IMG RCDATA "resources/dw/online_mp.img"
DW_WAD RCDATA "resources/dw/online_tu14_mp_english.wad" DW_WAD RCDATA "resources/dw/online_tu14_mp_english.wad"
DW_PLAYLIST RCDATA "resources/dw/playlists.aggr" DW_PLAYLIST RCDATA "resources/dw/playlists.aggr"
DW_CONFIG RCDATA "resources/dw/social_tu1.cfg" DW_CONFIG RCDATA "resources/dw/social_tu1.cfg"
DW_IOTD_TXT RCDATA "resources/dw/iotd-english.txt" DW_IOTD_TXT RCDATA "resources/dw/iotd-english.txt"
DW_IOTD_IMG RCDATA "resources/dw/iotd-english.jpg" DW_IOTD_IMG RCDATA "resources/dw/iotd-english.jpg"
MENU_MAIN RCDATA "resources/main.html" MENU_MAIN RCDATA "resources/main.html"
MENU_SETTINGS RCDATA "resources/settings.html" MENU_SETTINGS RCDATA "resources/settings.html"
#endif // English (United States) resources #endif // English (United States) resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED #ifndef APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Generated from the TEXTINCLUDE 3 resource. // Generated from the TEXTINCLUDE 3 resource.
// //
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED #endif // not APSTUDIO_INVOKED

File diff suppressed because one or more lines are too long

View File

@ -1,44 +1,44 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Open-IW5 Settings</title> <title>Open-IW5 Settings</title>
<style> <style>
* { * {
user-select: none; user-select: none;
-ms-user-select: none; -ms-user-select: none;
cursor: default; cursor: default;
} }
html, html,
body { body {
margin: 0; margin: 0;
background-color: #2D2D2D; background-color: #2D2D2D;
color: white; color: white;
font-family: "Segoe UI Light", "Segoe UI", "Lucida Sans", Arial, sans-serif; font-family: "Segoe UI Light", "Segoe UI", "Lucida Sans", Arial, sans-serif;
font-style: normal; font-style: normal;
font-weight: lighter; font-weight: lighter;
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
} }
.content { .content {
text-align: center; text-align: center;
} }
</style> </style>
</head> </head>
<body> <body>
<div class="content"> <div class="content">
<h1>No settings, yet!</h1> <h1>No settings, yet!</h1>
</div> </div>
</body> </body>
</html> </html>

View File

@ -1,143 +1,143 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "steam/steam.hpp" #include "steam/steam.hpp"
#include "module/dw.hpp" #include "module/dw.hpp"
namespace steam namespace steam
{ {
std::string auth_ticket; std::string auth_ticket;
int user::GetHSteamUser() int user::GetHSteamUser()
{ {
return NULL; return NULL;
} }
bool user::LoggedOn() bool user::LoggedOn()
{ {
return true; return true;
} }
steam_id user::GetSteamID() steam_id user::GetSteamID()
{ {
steam_id id; steam_id id;
id.bits = 0x110000100000000 | (0x1377 & ~0x80000000); id.bits = 0x110000100000000 | (0x1377 & ~0x80000000);
return id; return id;
} }
int user::InitiateGameConnection(void* pAuthBlob, int cbMaxAuthBlob, steam_id steamIDGameServer, int user::InitiateGameConnection(void* pAuthBlob, int cbMaxAuthBlob, steam_id steamIDGameServer,
unsigned int unIPServer, unsigned short usPortServer, bool bSecure) unsigned int unIPServer, unsigned short usPortServer, bool bSecure)
{ {
return 0; return 0;
} }
void user::TerminateGameConnection(unsigned int unIPServer, unsigned short usPortServer) void user::TerminateGameConnection(unsigned int unIPServer, unsigned short usPortServer)
{ {
} }
void user::TrackAppUsageEvent(steam_id gameID, int eAppUsageEvent, const char* pchExtraInfo) void user::TrackAppUsageEvent(steam_id gameID, int eAppUsageEvent, const char* pchExtraInfo)
{ {
} }
bool user::GetUserDataFolder(char* pchBuffer, int cubBuffer) bool user::GetUserDataFolder(char* pchBuffer, int cubBuffer)
{ {
return false; return false;
} }
void user::StartVoiceRecording() void user::StartVoiceRecording()
{ {
} }
void user::StopVoiceRecording() void user::StopVoiceRecording()
{ {
} }
int user::GetAvailableVoice(unsigned int* pcbCompressed, unsigned int* pcbUncompressed, int user::GetAvailableVoice(unsigned int* pcbCompressed, unsigned int* pcbUncompressed,
unsigned int nUncompressedVoiceDesiredSampleRate) unsigned int nUncompressedVoiceDesiredSampleRate)
{ {
return 0; return 0;
} }
int user::GetVoice(bool bWantCompressed, void* pDestBuffer, unsigned int cbDestBufferSize, int user::GetVoice(bool bWantCompressed, void* pDestBuffer, unsigned int cbDestBufferSize,
unsigned int* nBytesWritten, bool bWantUncompressed, void* pUncompressedDestBuffer, unsigned int* nBytesWritten, bool bWantUncompressed, void* pUncompressedDestBuffer,
unsigned int cbUncompressedDestBufferSize, unsigned int* nUncompressBytesWritten, unsigned int cbUncompressedDestBufferSize, unsigned int* nUncompressBytesWritten,
unsigned int nUncompressedVoiceDesiredSampleRate) unsigned int nUncompressedVoiceDesiredSampleRate)
{ {
return 0; return 0;
} }
int user::DecompressVoice(void* pCompressed, unsigned int cbCompressed, void* pDestBuffer, int user::DecompressVoice(void* pCompressed, unsigned int cbCompressed, void* pDestBuffer,
unsigned int cbDestBufferSize, unsigned int* nBytesWritten) unsigned int cbDestBufferSize, unsigned int* nBytesWritten)
{ {
return 0; return 0;
} }
unsigned int user::GetVoiceOptimalSampleRate() unsigned int user::GetVoiceOptimalSampleRate()
{ {
return 0; return 0;
} }
unsigned int user::GetAuthSessionTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket) unsigned int user::GetAuthSessionTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket)
{ {
return 0; return 0;
} }
int user::BeginAuthSession(const void* pAuthTicket, int cbAuthTicket, steam_id steamID) int user::BeginAuthSession(const void* pAuthTicket, int cbAuthTicket, steam_id steamID)
{ {
return 0; return 0;
} }
void user::EndAuthSession(steam_id steamID) void user::EndAuthSession(steam_id steamID)
{ {
} }
void user::CancelAuthTicket(unsigned int hAuthTicket) void user::CancelAuthTicket(unsigned int hAuthTicket)
{ {
} }
unsigned int user::UserHasLicenseForApp(steam_id steamID, unsigned int appID) unsigned int user::UserHasLicenseForApp(steam_id steamID, unsigned int appID)
{ {
return 0; return 0;
} }
bool user::BIsBehindNAT() bool user::BIsBehindNAT()
{ {
return false; return false;
} }
void user::AdvertiseGame(steam_id steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer) void user::AdvertiseGame(steam_id steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer)
{ {
} }
unsigned __int64 user::RequestEncryptedAppTicket(void* pUserData, int cbUserData) unsigned __int64 user::RequestEncryptedAppTicket(void* pUserData, int cbUserData)
{ {
// Generate the authentication ticket // Generate the authentication ticket
const auto id = this->GetSteamID(); const auto id = this->GetSteamID();
auth_ticket = "Open-IW5"; auth_ticket = "Open-IW5";
auth_ticket.resize(32); auth_ticket.resize(32);
auth_ticket.append(reinterpret_cast<char*>(pUserData), cbUserData); auth_ticket.append(reinterpret_cast<char*>(pUserData), cbUserData);
auth_ticket.append(reinterpret_cast<const char*>(&id.bits), sizeof(id.bits)); auth_ticket.append(reinterpret_cast<const char*>(&id.bits), sizeof(id.bits));
// Create the call response // Create the call response
const auto result = callbacks::register_call(); const auto result = callbacks::register_call();
auto retvals = static_cast<encrypted_app_ticket_response*>(calloc(1, sizeof(encrypted_app_ticket_response))); auto retvals = static_cast<encrypted_app_ticket_response*>(calloc(1, sizeof(encrypted_app_ticket_response)));
//::Utils::Memory::AllocateArray<EncryptedAppTicketResponse>(); //::Utils::Memory::AllocateArray<EncryptedAppTicketResponse>();
retvals->m_e_result = 1; retvals->m_e_result = 1;
// Return the call response // Return the call response
callbacks::return_call(retvals, sizeof(encrypted_app_ticket_response), callbacks::return_call(retvals, sizeof(encrypted_app_ticket_response),
encrypted_app_ticket_response::callback_id, result); encrypted_app_ticket_response::callback_id, result);
return result; return result;
} }
bool user::GetEncryptedAppTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket) bool user::GetEncryptedAppTicket(void* pTicket, int cbMaxTicket, unsigned int* pcbTicket)
{ {
if (cbMaxTicket < 0 || auth_ticket.empty()) return false; if (cbMaxTicket < 0 || auth_ticket.empty()) return false;
const auto size = std::min(size_t(cbMaxTicket), auth_ticket.size()); const auto size = std::min(size_t(cbMaxTicket), auth_ticket.size());
std::memcpy(pTicket, auth_ticket.data(), size); std::memcpy(pTicket, auth_ticket.data(), size);
*pcbTicket = size; *pcbTicket = size;
return true; return true;
} }
} }

Binary file not shown.