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

No settings, yet!

-
- - + + + + + + + Open-IW5 Settings + + + + + +
+

No settings, yet!

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