[IPC] Use iw4x as worker process instead of creating a separate binary
This commit is contained in:
parent
fc0bf1acc1
commit
4e84c297e4
@ -33,6 +33,5 @@
|
|||||||
| `--disable-bitmessage` | Disable use of BitMessage completely. |
|
| `--disable-bitmessage` | Disable use of BitMessage completely. |
|
||||||
| `--disable-node-log` | Disable debugging messages for Nodes in Debug builds. |
|
| `--disable-node-log` | Disable debugging messages for Nodes in Debug builds. |
|
||||||
| `--disable-base128` | Disable base128 encoding for minidumps. |
|
| `--disable-base128` | Disable base128 encoding for minidumps. |
|
||||||
| `--disable-steam-game` | Disable Steam's in-game setting. |
|
|
||||||
| `--no-new-structure` | Do not use new virtual path structure (separating headers and source files). |
|
| `--no-new-structure` | Do not use new virtual path structure (separating headers and source files). |
|
||||||
| `--enable-dxsdk` | Enable DirectX SDK (required for GfxMap exporting). |
|
| `--enable-dxsdk` | Enable DirectX SDK (required for GfxMap exporting). |
|
||||||
|
122
premake5.lua
122
premake5.lua
@ -88,11 +88,6 @@ newoption {
|
|||||||
description = "Disable base128 encoding for minidumps."
|
description = "Disable base128 encoding for minidumps."
|
||||||
}
|
}
|
||||||
|
|
||||||
newoption {
|
|
||||||
trigger = "disable-steam-game",
|
|
||||||
description = "Disable Steam's in-game setting."
|
|
||||||
}
|
|
||||||
|
|
||||||
newoption {
|
newoption {
|
||||||
trigger = "enable-dxsdk",
|
trigger = "enable-dxsdk",
|
||||||
description = "Enable DirectX SDK (required for GfxMap exporting)."
|
description = "Enable DirectX SDK (required for GfxMap exporting)."
|
||||||
@ -307,9 +302,6 @@ workspace "iw4x"
|
|||||||
"./src/**.cpp",
|
"./src/**.cpp",
|
||||||
--"./src/**.proto",
|
--"./src/**.proto",
|
||||||
}
|
}
|
||||||
removefiles {
|
|
||||||
"./src/Worker/**.*",
|
|
||||||
}
|
|
||||||
includedirs {
|
includedirs {
|
||||||
"%{prj.location}/src",
|
"%{prj.location}/src",
|
||||||
"./src",
|
"./src",
|
||||||
@ -349,9 +341,6 @@ workspace "iw4x"
|
|||||||
if _OPTIONS["disable-base128"] then
|
if _OPTIONS["disable-base128"] then
|
||||||
defines { "DISABLE_BASE128" }
|
defines { "DISABLE_BASE128" }
|
||||||
end
|
end
|
||||||
if _OPTIONS["disable-steam-game"] then
|
|
||||||
defines { "DISABLE_STEAM_GAME" }
|
|
||||||
end
|
|
||||||
if _OPTIONS["enable-dxsdk"] then
|
if _OPTIONS["enable-dxsdk"] then
|
||||||
defines { "ENABLE_DXSDK" }
|
defines { "ENABLE_DXSDK" }
|
||||||
includedirs { "%DXSDK_DIR%Include" }
|
includedirs { "%DXSDK_DIR%Include" }
|
||||||
@ -479,117 +468,6 @@ workspace "iw4x"
|
|||||||
}
|
}
|
||||||
filter {}
|
filter {}
|
||||||
]]
|
]]
|
||||||
|
|
||||||
project "iw4xworker"
|
|
||||||
language "C++"
|
|
||||||
flags { "C++14" }
|
|
||||||
files {
|
|
||||||
"./src/Worker/**.rc",
|
|
||||||
"./src/Worker/**.hpp",
|
|
||||||
"./src/Worker/**.cpp",
|
|
||||||
"./src/Utils/**.hpp",
|
|
||||||
"./src/Utils/**.cpp",
|
|
||||||
--"./src/**.proto",
|
|
||||||
}
|
|
||||||
removefiles {
|
|
||||||
"./src/Utils/CSV.*",
|
|
||||||
"./src/Utils/Cache.*",
|
|
||||||
"./src/Utils/Stream.*",
|
|
||||||
"./src/Utils/Hooking.*",
|
|
||||||
"./src/Utils/InfoString.*",
|
|
||||||
"./src/Utils/Cryptography.*",
|
|
||||||
}
|
|
||||||
includedirs {
|
|
||||||
"%{prj.location}/src",
|
|
||||||
--"./src",
|
|
||||||
"./src/Worker",
|
|
||||||
}
|
|
||||||
resincludedirs {
|
|
||||||
"$(ProjectDir)src/Worker" -- fix for VS IDE
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Pre-compiled header
|
|
||||||
pchheader "STDInclude.hpp" -- must be exactly same as used in #include directives
|
|
||||||
pchsource "src/Worker/STDInclude.cpp" -- real path
|
|
||||||
buildoptions { "/Zm200" }
|
|
||||||
|
|
||||||
protobuf.import()
|
|
||||||
zlib.import()
|
|
||||||
boost.import()
|
|
||||||
|
|
||||||
-- fix vpaths for protobuf sources
|
|
||||||
vpaths
|
|
||||||
{
|
|
||||||
["*"] = { "./src/Worker/**" },
|
|
||||||
--["Proto/Generated"] = { "**.pb.*" }, -- meh.
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Virtual paths
|
|
||||||
if not _OPTIONS["no-new-structure"] then
|
|
||||||
vpaths
|
|
||||||
{
|
|
||||||
["Headers/*"] = { "./src/Worker/**.hpp" },
|
|
||||||
["Headers/Utils/*"] = { "./src/Utils/**.hpp" },
|
|
||||||
["Sources/*"] = { "./src/Worker/**.cpp" },
|
|
||||||
["Sources/Utils/*"] = { "./src/Utils/**.cpp" },
|
|
||||||
["Resource/*"] = { "./src/Worker/**.rc" },
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vpaths
|
|
||||||
{
|
|
||||||
["Utils/*"] = { "./src/Utils/**" },
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
vpaths
|
|
||||||
{
|
|
||||||
["Docs/*"] = { "**.txt","**.md" },
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Pre-build
|
|
||||||
prebuildcommands
|
|
||||||
{
|
|
||||||
"pushd %{_MAIN_SCRIPT_DIR}",
|
|
||||||
"tools\\premake5 generate-buildinfo",
|
|
||||||
"popd",
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Post-build
|
|
||||||
if _OPTIONS["copy-to"] then
|
|
||||||
saneCopyToPath = string.gsub(_OPTIONS["copy-to"] .. "\\", "\\\\", "\\")
|
|
||||||
postbuildcommands {
|
|
||||||
"if not exist \"" .. saneCopyToPath .. "\" mkdir \"" .. saneCopyToPath .. "iw4x\\\"",
|
|
||||||
}
|
|
||||||
|
|
||||||
if _OPTIONS["copy-pdb"] then
|
|
||||||
postbuildcommands {
|
|
||||||
"copy /y \"$(TargetDir)*.pdb\" \"" .. saneCopyToPath .. "iw4x\\\"",
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- This has to be the last one, as otherwise VisualStudio will succeed building even if copying fails
|
|
||||||
postbuildcommands {
|
|
||||||
"copy /y \"$(TargetDir)*.exe\" \"" .. saneCopyToPath .. "iw4x\\\"",
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Specific configurations
|
|
||||||
flags { "UndefinedIdentifiers", "ExtraWarnings" }
|
|
||||||
|
|
||||||
if symbols ~= nil then
|
|
||||||
symbols "On"
|
|
||||||
else
|
|
||||||
flags { "Symbols" }
|
|
||||||
end
|
|
||||||
|
|
||||||
kind "ConsoleApp"
|
|
||||||
configuration "Release*"
|
|
||||||
kind "WindowedApp"
|
|
||||||
flags {
|
|
||||||
"FatalCompileWarnings",
|
|
||||||
"FatalLinkWarnings",
|
|
||||||
}
|
|
||||||
configuration {}
|
|
||||||
|
|
||||||
group "External dependencies"
|
group "External dependencies"
|
||||||
if not _OPTIONS["disable-bitmessage"] then
|
if not _OPTIONS["disable-bitmessage"] then
|
||||||
|
@ -236,8 +236,7 @@ namespace Components
|
|||||||
IPCPipe::Write("ping", "");
|
IPCPipe::Write("ping", "");
|
||||||
});
|
});
|
||||||
|
|
||||||
static Utils::IPC::Channel channel("iw4xChannel");
|
static Utils::IPC::BidirectionalChannel channel("iw4xChannel", !Worker::IsWorker());
|
||||||
static Utils::IPC::Channel channel2("iw4xChannel2");
|
|
||||||
channel.send("Hello world!");
|
channel.send("Hello world!");
|
||||||
|
|
||||||
Command::Add("ipcchan", [](Command::Params* params)
|
Command::Add("ipcchan", [](Command::Params* params)
|
||||||
@ -245,10 +244,32 @@ namespace Components
|
|||||||
channel.send(params->join(1));
|
channel.send(params->join(1));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Command::Add("ipcchantest", [](Command::Params*)
|
||||||
|
{
|
||||||
|
std::string buffer;
|
||||||
|
buffer.reserve(2048);
|
||||||
|
|
||||||
|
for(int i = 0; i < 1020; ++i)
|
||||||
|
{
|
||||||
|
buffer.append("a", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append("lolsnakerules!");
|
||||||
|
|
||||||
|
for (int i = 0; i < 1020; ++i)
|
||||||
|
{
|
||||||
|
buffer.append("a", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append("lolsnakerules!");
|
||||||
|
|
||||||
|
channel.send(buffer);
|
||||||
|
});
|
||||||
|
|
||||||
QuickPatch::OnFrame([]()
|
QuickPatch::OnFrame([]()
|
||||||
{
|
{
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
if(channel2.receive(&buffer))
|
if(channel.receive(&buffer))
|
||||||
{
|
{
|
||||||
Logger::Print("Data received: %s\n", buffer.data());
|
Logger::Print("Data received: %s\n", buffer.data());
|
||||||
}
|
}
|
||||||
@ -261,7 +282,7 @@ namespace Components
|
|||||||
ZeroMemory(&pInfo, sizeof(pInfo));
|
ZeroMemory(&pInfo, sizeof(pInfo));
|
||||||
sInfo.cb = sizeof(sInfo);
|
sInfo.cb = sizeof(sInfo);
|
||||||
|
|
||||||
CreateProcessA("iw4x/iw4xworker.exe", const_cast<char*>(Utils::String::VA("-parentProc %d", GetCurrentProcessId())), nullptr, nullptr, false, NULL, nullptr, nullptr, &sInfo, &pInfo);
|
CreateProcessA("iw4x.exe", const_cast<char*>(Utils::String::VA("-parent %d", GetCurrentProcessId())), nullptr, nullptr, false, NULL, nullptr, nullptr, &sInfo, &pInfo);
|
||||||
|
|
||||||
if (pInfo.hThread && pInfo.hThread != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hThread);
|
if (pInfo.hThread && pInfo.hThread != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hThread);
|
||||||
if (pInfo.hProcess && pInfo.hProcess != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hProcess);
|
if (pInfo.hProcess && pInfo.hProcess != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hProcess);
|
||||||
|
43
src/Main.cpp
43
src/Main.cpp
@ -20,28 +20,43 @@ namespace Main
|
|||||||
Main::EntryPointHook.uninstall();
|
Main::EntryPointHook.uninstall();
|
||||||
|
|
||||||
Main::SetEnvironment();
|
Main::SetEnvironment();
|
||||||
|
|
||||||
Utils::Cryptography::Initialize();
|
Utils::Cryptography::Initialize();
|
||||||
Components::Loader::Initialize();
|
|
||||||
|
if(Worker::IsWorker())
|
||||||
|
{
|
||||||
|
Worker::Initialize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Components::Loader::Initialize();
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||||
if (Components::Loader::PerformingUnitTests())
|
if (Components::Loader::PerformingUnitTests())
|
||||||
{
|
{
|
||||||
DWORD result = (Components::Loader::PerformUnitTests() ? 0 : -1);
|
DWORD result = (Components::Loader::PerformUnitTests() ? 0 : -1);
|
||||||
Components::Loader::Uninitialize();
|
Components::Loader::Uninitialize();
|
||||||
ExitProcess(result);
|
ExitProcess(result);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (Components::Flags::HasFlag("tests"))
|
if (Components::Flags::HasFlag("tests"))
|
||||||
{
|
{
|
||||||
Components::Logger::Print("Unit tests are disabled outside the debug environment!\n");
|
Components::Logger::Print("Unit tests are disabled outside the debug environment!\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Uninitialize()
|
void Uninitialize()
|
||||||
{
|
{
|
||||||
Components::Loader::Uninitialize();
|
if(Worker::IsWorker())
|
||||||
|
{
|
||||||
|
Worker::Uninitialize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Components::Loader::Uninitialize();
|
||||||
|
}
|
||||||
|
|
||||||
Utils::Cache::Uninitialize();
|
Utils::Cache::Uninitialize();
|
||||||
google::protobuf::ShutdownProtobufLibrary();
|
google::protobuf::ShutdownProtobufLibrary();
|
||||||
}
|
}
|
||||||
@ -51,8 +66,6 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*l
|
|||||||
{
|
{
|
||||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
Steam::Proxy::RunMod();
|
|
||||||
|
|
||||||
// Ensure we're working with our desired binary
|
// Ensure we're working with our desired binary
|
||||||
if (Utils::Hook::Get<DWORD>(0x4C0FFF) != 0x6824748B)
|
if (Utils::Hook::Get<DWORD>(0x4C0FFF) != 0x6824748B)
|
||||||
{
|
{
|
||||||
|
@ -117,6 +117,7 @@ template <size_t S> class Sizer { };
|
|||||||
#include "Utils/Stream.hpp"
|
#include "Utils/Stream.hpp"
|
||||||
|
|
||||||
#include "Components/Loader.hpp"
|
#include "Components/Loader.hpp"
|
||||||
|
#include "Worker/Worker.hpp"
|
||||||
|
|
||||||
// Libraries
|
// Libraries
|
||||||
#pragma comment(lib, "Winmm.lib")
|
#pragma comment(lib, "Winmm.lib")
|
||||||
|
@ -4,9 +4,9 @@ namespace Utils
|
|||||||
{
|
{
|
||||||
namespace IPC
|
namespace IPC
|
||||||
{
|
{
|
||||||
Channel::Channel(std::string _name, int queueSize, int bufferSize) : name(_name)
|
Channel::Channel(std::string _name, int queueSize, int bufferSize, bool creator) : name(_name)
|
||||||
{
|
{
|
||||||
//boost::interprocess::message_queue::remove(this->name.data());
|
if(creator) boost::interprocess::message_queue::remove(this->name.data());
|
||||||
queue.reset(new boost::interprocess::message_queue(boost::interprocess::open_or_create, this->name.data(), queueSize, bufferSize + sizeof(Channel::Header)));
|
queue.reset(new boost::interprocess::message_queue(boost::interprocess::open_or_create, this->name.data(), queueSize, bufferSize + sizeof(Channel::Header)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ namespace Utils
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
this->queue->receive(const_cast<char*>(packet.data()), packet.size(), recvd_size, priority);
|
if (!this->queue->try_receive(const_cast<char*>(packet.data()), packet.size(), recvd_size, priority)) return false;
|
||||||
|
|
||||||
if (header->packetId != mainHeader.packetId || header->totalSize != mainHeader.totalSize || header->fragmentPart != (++part))
|
if (header->packetId != mainHeader.packetId || header->totalSize != mainHeader.totalSize || header->fragmentPart != (++part))
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ namespace Utils
|
|||||||
class Channel
|
class Channel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Channel(std::string _name, int queueSize = 100, int bufferSize = 20);
|
Channel(std::string _name, int queueSize = 100, int bufferSize = 1024, bool creator = false);
|
||||||
~Channel();
|
~Channel();
|
||||||
|
|
||||||
bool receive(std::string* data);
|
bool receive(std::string* data);
|
||||||
@ -51,5 +51,43 @@ namespace Utils
|
|||||||
std::string packet;
|
std::string packet;
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BidirectionalChannel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BidirectionalChannel(std::string name, bool server, int queueSize = 100, int bufferSize = 1024) : isServer(server),
|
||||||
|
channel1(name, queueSize, bufferSize, server),
|
||||||
|
channel2(name + "2", queueSize, bufferSize, server)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool receive(std::string* data)
|
||||||
|
{
|
||||||
|
if(this->isServer)
|
||||||
|
{
|
||||||
|
return channel1.receive(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return channel2.receive(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(std::string data)
|
||||||
|
{
|
||||||
|
if (this->isServer)
|
||||||
|
{
|
||||||
|
return channel2.send(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return channel1.send(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const bool isServer;
|
||||||
|
Channel channel1;
|
||||||
|
Channel channel2;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
#include "STDInclude.hpp"
|
|
||||||
#include <conio.h>
|
|
||||||
|
|
||||||
void worker(bool* terminator)
|
|
||||||
{
|
|
||||||
printf("Worker started\n");
|
|
||||||
Utils::IPC::Channel channel("iw4xChannel");
|
|
||||||
Utils::IPC::Channel channel2("iw4xChannel2");
|
|
||||||
|
|
||||||
while(!*terminator)
|
|
||||||
{
|
|
||||||
std::string buffer;
|
|
||||||
if(channel.receive(&buffer))
|
|
||||||
{
|
|
||||||
printf("Data received: %s\n", buffer.data());
|
|
||||||
channel2.send("OK " + buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(1ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Terminating worker\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
bool terminator = false;
|
|
||||||
char* command = "-parentProc ";
|
|
||||||
char* parentProc = strstr(GetCommandLineA(), command);
|
|
||||||
|
|
||||||
if (!parentProc)
|
|
||||||
{
|
|
||||||
printf("No parent process argument found\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
parentProc += strlen(command);
|
|
||||||
int pid = atoi(parentProc);
|
|
||||||
|
|
||||||
printf("Attaching to process %d...\n", pid);
|
|
||||||
|
|
||||||
HANDLE processHandle = OpenProcess(SYNCHRONIZE, FALSE, pid);
|
|
||||||
if (!processHandle || processHandle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
printf("Unable to attach to parent process\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Successfully attached to parent process\n");
|
|
||||||
printf("Starting worker...\n");
|
|
||||||
|
|
||||||
std::thread runner(worker, &terminator);
|
|
||||||
|
|
||||||
WaitForSingleObject(processHandle, INFINITE);
|
|
||||||
CloseHandle(processHandle);
|
|
||||||
|
|
||||||
terminator = true;
|
|
||||||
|
|
||||||
printf("Awaiting worker termination...\n");
|
|
||||||
if (runner.joinable()) runner.join();
|
|
||||||
printf("Worker terminated\n");
|
|
||||||
|
|
||||||
//_getch();
|
|
||||||
|
|
||||||
google::protobuf::ShutdownProtobufLibrary();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,99 +0,0 @@
|
|||||||
// Microsoft Visual C++ generated resource script.
|
|
||||||
//
|
|
||||||
#pragma code_page(65001)
|
|
||||||
|
|
||||||
#include "STDInclude.hpp"
|
|
||||||
|
|
||||||
#define APSTUDIO_READONLY_SYMBOLS
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 2 resource.
|
|
||||||
//
|
|
||||||
#include "windows.h"
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#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 VERSION_RC
|
|
||||||
PRODUCTVERSION VERSION_RC
|
|
||||||
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", "IW4x"
|
|
||||||
#ifdef _DEBUG
|
|
||||||
VALUE "FileDescription", "IW4 client modification (DEBUG)"
|
|
||||||
#else
|
|
||||||
VALUE "FileDescription", "IW4 client modification"
|
|
||||||
#endif
|
|
||||||
VALUE "FileVersion", SHORTVERSION
|
|
||||||
VALUE "InternalName", "iw4x"
|
|
||||||
VALUE "LegalCopyright", "No rights reserved."
|
|
||||||
VALUE "OriginalFilename", "iw4x.dll"
|
|
||||||
VALUE "ProductName", "IW4x"
|
|
||||||
VALUE "ProductVersion", SHORTVERSION
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", 0x409, 1200
|
|
||||||
END
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif // English (United States) resources
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef APSTUDIO_INVOKED
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 3 resource.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#endif // not APSTUDIO_INVOKED
|
|
||||||
|
|
60
src/Worker/Runner.cpp
Normal file
60
src/Worker/Runner.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "STDInclude.hpp"
|
||||||
|
|
||||||
|
namespace Worker
|
||||||
|
{
|
||||||
|
Runner::Runner(int pid) : processId(pid), terminate(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Runner::~Runner()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runner::run()
|
||||||
|
{
|
||||||
|
HANDLE processHandle = OpenProcess(SYNCHRONIZE, FALSE, this->processId);
|
||||||
|
if (!processHandle || processHandle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
printf("Unable to attach to parent process\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Successfully attached to parent process\n");
|
||||||
|
printf("Starting worker...\n");
|
||||||
|
|
||||||
|
std::thread workerThread(&Runner::worker, this);
|
||||||
|
|
||||||
|
WaitForSingleObject(processHandle, INFINITE);
|
||||||
|
CloseHandle(processHandle);
|
||||||
|
|
||||||
|
this->terminate = true;
|
||||||
|
printf("Awaiting worker termination...\n");
|
||||||
|
if (workerThread.joinable()) workerThread.join();
|
||||||
|
printf("Worker terminated\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runner::worker()
|
||||||
|
{
|
||||||
|
printf("Worker started\n");
|
||||||
|
Utils::IPC::BidirectionalChannel channel("iw4xChannel", !Worker::IsWorker());
|
||||||
|
|
||||||
|
while (!this->terminate)
|
||||||
|
{
|
||||||
|
Steam::Proxy::RunFrame();
|
||||||
|
|
||||||
|
std::string buffer;
|
||||||
|
if (channel.receive(&buffer))
|
||||||
|
{
|
||||||
|
printf("Data received: %s\n", buffer.data());
|
||||||
|
channel.send("OK " + buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Terminating worker\n");
|
||||||
|
}
|
||||||
|
}
|
19
src/Worker/Runner.hpp
Normal file
19
src/Worker/Runner.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Worker
|
||||||
|
{
|
||||||
|
class Runner
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Runner(int pid);
|
||||||
|
~Runner();
|
||||||
|
|
||||||
|
void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void worker();
|
||||||
|
|
||||||
|
int processId;
|
||||||
|
bool terminate;
|
||||||
|
};
|
||||||
|
}
|
@ -1,77 +0,0 @@
|
|||||||
#include "STDInclude.hpp"
|
|
||||||
|
|
||||||
// Rename sections
|
|
||||||
#ifndef DEBUG
|
|
||||||
#pragma comment(linker, "/merge:.text=.UPX0")
|
|
||||||
#pragma comment(linker, "/merge:.data=.UPX1")
|
|
||||||
#pragma comment(linker, "/merge:.rdata=.UPX2")
|
|
||||||
#pragma comment(linker, "/merge:.tls=.UPX3")
|
|
||||||
#pragma comment(linker, "/merge:.gfids=.UPX4")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
|
||||||
|
|
||||||
// Do necessary assertions here
|
|
||||||
// Some compilers treat them differently which causes a size mismatch
|
|
||||||
|
|
||||||
// WinAPI types
|
|
||||||
AssertSize(DWORD, 4);
|
|
||||||
AssertSize(WORD, 2);
|
|
||||||
AssertSize(BYTE, 1);
|
|
||||||
|
|
||||||
// 128 bit integers (only x64)
|
|
||||||
//AssertSize(__int128, 16);
|
|
||||||
//AssertSize(unsigned __int128, 16);
|
|
||||||
|
|
||||||
// 64 bit integers
|
|
||||||
AssertSize(__int64, 8);
|
|
||||||
AssertSize(unsigned __int64, 8);
|
|
||||||
AssertSize(long long, 8);
|
|
||||||
AssertSize(unsigned long long, 8);
|
|
||||||
AssertSize(int64_t, 8);
|
|
||||||
AssertSize(uint64_t, 8);
|
|
||||||
AssertSize(std::int64_t, 8);
|
|
||||||
AssertSize(std::uint64_t, 8);
|
|
||||||
|
|
||||||
// 32 bit integers
|
|
||||||
AssertSize(__int32, 4);
|
|
||||||
AssertSize(unsigned __int32, 4);
|
|
||||||
AssertSize(int, 4);
|
|
||||||
AssertSize(unsigned int, 4);
|
|
||||||
AssertSize(int32_t, 4);
|
|
||||||
AssertSize(uint32_t, 4);
|
|
||||||
AssertSize(std::int32_t, 4);
|
|
||||||
AssertSize(std::uint32_t, 4);
|
|
||||||
|
|
||||||
// 16 bit integers
|
|
||||||
AssertSize(__int16, 2);
|
|
||||||
AssertSize(unsigned __int16, 2);
|
|
||||||
AssertSize(short, 2);
|
|
||||||
AssertSize(unsigned short, 2);
|
|
||||||
AssertSize(int16_t, 2);
|
|
||||||
AssertSize(uint16_t, 2);
|
|
||||||
AssertSize(std::int16_t, 2);
|
|
||||||
AssertSize(std::uint16_t, 2);
|
|
||||||
|
|
||||||
// 8 bit integers
|
|
||||||
AssertSize(bool, 1);
|
|
||||||
AssertSize(__int8, 1);
|
|
||||||
AssertSize(unsigned __int8, 1);
|
|
||||||
AssertSize(char, 1);
|
|
||||||
AssertSize(unsigned char, 1);
|
|
||||||
AssertSize(int8_t, 1);
|
|
||||||
AssertSize(uint8_t, 1);
|
|
||||||
AssertSize(std::int8_t, 1);
|
|
||||||
AssertSize(std::uint8_t, 1);
|
|
||||||
|
|
||||||
// Ensure pointers are 4 bytes in size (32-bit)
|
|
||||||
static_assert(sizeof(intptr_t) == 4 && sizeof(void*) == 4 && sizeof(size_t) == 4, "This doesn't seem to be a 32-bit environment!");
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
// Disable telemetry data logging
|
|
||||||
void __cdecl __vcrt_initialize_telemetry_provider() {}
|
|
||||||
void __cdecl __telemetry_main_invoke_trigger() {}
|
|
||||||
void __cdecl __telemetry_main_return_trigger() {}
|
|
||||||
void __cdecl __vcrt_uninitialize_telemetry_provider() {}
|
|
||||||
};
|
|
@ -1,126 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// Version number
|
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
#ifndef RC_INVOKED
|
|
||||||
|
|
||||||
#define VC_EXTRALEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
|
|
||||||
// Requires Visual Leak Detector plugin: http://vld.codeplex.com/
|
|
||||||
//#include <vld.h>
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <timeapi.h>
|
|
||||||
#include <shellapi.h>
|
|
||||||
#include <Wininet.h>
|
|
||||||
#include <d3d9.h>
|
|
||||||
#include <Aclapi.h>
|
|
||||||
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable: 4996)
|
|
||||||
#include <xutility>
|
|
||||||
#pragma warning(pop)
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <cctype>
|
|
||||||
#include <regex>
|
|
||||||
#include <thread>
|
|
||||||
#include <future>
|
|
||||||
#include <queue>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
// Experimental C++17 features
|
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
// Usefull for debugging
|
|
||||||
template <size_t S> class Sizer { };
|
|
||||||
#define BindNum(x, y) Sizer<x> y;
|
|
||||||
#define SizeOf(x, y) BindNum(sizeof(x), y)
|
|
||||||
#define OffsetOf(x, y, z) BindNum(offsetof(x, y), z)
|
|
||||||
|
|
||||||
// Submodules
|
|
||||||
// Ignore the warnings, it's no our code!
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable: 4005)
|
|
||||||
#pragma warning(disable: 4100)
|
|
||||||
#pragma warning(disable: 4389)
|
|
||||||
#pragma warning(disable: 4702)
|
|
||||||
#pragma warning(disable: 4996) // _CRT_SECURE_NO_WARNINGS
|
|
||||||
#pragma warning(disable: 6001)
|
|
||||||
#pragma warning(disable: 6011)
|
|
||||||
#pragma warning(disable: 6031)
|
|
||||||
#pragma warning(disable: 6255)
|
|
||||||
#pragma warning(disable: 6258)
|
|
||||||
#pragma warning(disable: 6386)
|
|
||||||
#pragma warning(disable: 6387)
|
|
||||||
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
#ifdef max
|
|
||||||
#undef max
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef min
|
|
||||||
#undef min
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Protobuf
|
|
||||||
#include "proto/network.pb.h"
|
|
||||||
#include "proto/party.pb.h"
|
|
||||||
#include "proto/auth.pb.h"
|
|
||||||
#include "proto/node.pb.h"
|
|
||||||
#include "proto/rcon.pb.h"
|
|
||||||
|
|
||||||
#pragma warning(pop)
|
|
||||||
|
|
||||||
#include "../Utils/IO.hpp"
|
|
||||||
#include "../Utils/IPC.hpp"
|
|
||||||
#include "../Utils/Time.hpp"
|
|
||||||
#include "../Utils/Chain.hpp"
|
|
||||||
#include "../Utils/Utils.hpp"
|
|
||||||
#include "../Utils/WebIO.hpp"
|
|
||||||
#include "../Utils/Memory.hpp"
|
|
||||||
#include "../Utils/String.hpp"
|
|
||||||
#include "../Utils/Library.hpp"
|
|
||||||
#include "../Utils/Compression.hpp"
|
|
||||||
|
|
||||||
// Libraries
|
|
||||||
#pragma comment(lib, "Winmm.lib")
|
|
||||||
#pragma comment(lib, "Crypt32.lib")
|
|
||||||
#pragma comment(lib, "Ws2_32.lib")
|
|
||||||
#pragma comment(lib, "d3d9.lib")
|
|
||||||
#pragma comment(lib, "Wininet.lib")
|
|
||||||
#pragma comment(lib, "shlwapi.lib")
|
|
||||||
#pragma comment(lib, "Urlmon.lib")
|
|
||||||
#pragma comment(lib, "Advapi32.lib")
|
|
||||||
#pragma comment(lib, "rpcrt4.lib")
|
|
||||||
|
|
||||||
// Enable additional literals
|
|
||||||
using namespace std::literals;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define STRINGIZE_(x) #x
|
|
||||||
#define STRINGIZE(x) STRINGIZE_(x)
|
|
||||||
|
|
||||||
#define AssertSize(x, size) static_assert(sizeof(x) == size, STRINGIZE(x) " structure has an invalid size.")
|
|
||||||
#define AssertOffset(x, y, offset) static_assert(offsetof(x, y) == offset, STRINGIZE(x) "::" STRINGIZE(y) " is not at the right offset.")
|
|
||||||
|
|
||||||
// Resource stuff
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
|
||||||
// Defines below make accessing the resources from the code easier.
|
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Enables custom map code
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define ENABLE_EXPERIMENTAL_MAP_CODE
|
|
||||||
#endif
|
|
65
src/Worker/Worker.cpp
Normal file
65
src/Worker/Worker.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include "STDInclude.hpp"
|
||||||
|
|
||||||
|
namespace Worker
|
||||||
|
{
|
||||||
|
int ProcessId;
|
||||||
|
|
||||||
|
int __stdcall EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, char* /*lpCmdLine*/, int /*nCmdShow*/)
|
||||||
|
{
|
||||||
|
Runner runner(Worker::ProcessId);
|
||||||
|
runner.run();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize()
|
||||||
|
{
|
||||||
|
if(!Steam::Proxy::Inititalize())
|
||||||
|
{
|
||||||
|
printf("Failed to initialize worker!\n");
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
SetConsoleTitleA("IW4x Worker");
|
||||||
|
#else
|
||||||
|
FreeConsole();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Utils::Hook(0x6BABA1, Worker::EntryPoint, HOOK_CALL).install()->quick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uninitialize()
|
||||||
|
{
|
||||||
|
Steam::Proxy::Uninititalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseWorkerFlag()
|
||||||
|
{
|
||||||
|
char* command = "-parent ";
|
||||||
|
char* parentProc = strstr(GetCommandLineA(), command);
|
||||||
|
|
||||||
|
if (parentProc)
|
||||||
|
{
|
||||||
|
parentProc += strlen(command);
|
||||||
|
Worker::ProcessId = atoi(parentProc);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsWorker()
|
||||||
|
{
|
||||||
|
static Utils::Value<bool> flag;
|
||||||
|
|
||||||
|
if (!flag.isValid())
|
||||||
|
{
|
||||||
|
flag.set(Worker::ParseWorkerFlag());
|
||||||
|
}
|
||||||
|
|
||||||
|
return flag.get();
|
||||||
|
}
|
||||||
|
}
|
11
src/Worker/Worker.hpp
Normal file
11
src/Worker/Worker.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Worker
|
||||||
|
{
|
||||||
|
void Initialize();
|
||||||
|
void Uninitialize();
|
||||||
|
|
||||||
|
bool IsWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "Runner.hpp"
|
Loading…
Reference in New Issue
Block a user