iw4x-client/src/Components/Modules/ConnectProtocol.cpp

244 lines
4.9 KiB
C++
Raw Normal View History

2022-02-27 07:53:44 -05:00
#include <STDInclude.hpp>
2017-01-19 16:23:59 -05:00
namespace Components
{
bool ConnectProtocol::Evaluated = false;
std::string ConnectProtocol::ConnectString;
bool ConnectProtocol::IsEvaluated()
{
return Evaluated;
2017-01-19 16:23:59 -05:00
}
bool ConnectProtocol::Used()
{
if (!IsEvaluated())
2017-01-19 16:23:59 -05:00
{
EvaluateProtocol();
2017-01-19 16:23:59 -05:00
}
return (!ConnectString.empty());
2017-01-19 16:23:59 -05:00
}
bool ConnectProtocol::InstallProtocol()
{
2017-01-20 08:36:52 -05:00
HKEY hKey = nullptr;
2017-01-19 16:23:59 -05:00
std::string data;
char ownPth[MAX_PATH]{};
char workdir[MAX_PATH]{};
2017-01-19 16:23:59 -05:00
DWORD dwsize = MAX_PATH;
HMODULE hModule = GetModuleHandleA(nullptr);
2017-01-19 16:23:59 -05:00
2017-01-20 08:36:52 -05:00
if (hModule != nullptr)
2017-01-19 16:23:59 -05:00
{
if (GetModuleFileNameA(hModule, ownPth, MAX_PATH) == ERROR)
{
return false;
}
if (GetModuleFileNameA(hModule, workdir, MAX_PATH) == ERROR)
{
return false;
}
else
{
auto* endPtr = std::strstr(workdir, "iw4x.exe");
2017-01-20 08:36:52 -05:00
if (endPtr != nullptr)
2017-01-19 16:23:59 -05:00
{
*endPtr = 0;
}
else
{
return false;
}
}
}
else
{
return false;
}
SetCurrentDirectoryA(workdir);
LONG openRes = RegOpenKeyExA(HKEY_CURRENT_USER, "SOFTWARE\\Classes\\iw4x\\shell\\open\\command", 0, KEY_ALL_ACCESS, &hKey);
if (openRes == ERROR_SUCCESS)
{
char regred[MAX_PATH]{};
2017-01-19 16:23:59 -05:00
// Check if the game has been moved.
openRes = RegQueryValueExA(hKey, nullptr, nullptr, nullptr, reinterpret_cast<BYTE*>(regred), &dwsize);
2017-01-19 16:23:59 -05:00
if (openRes == ERROR_SUCCESS)
{
auto* endPtr = std::strstr(regred, "\" \"%1\"");
if (endPtr != nullptr)
2017-01-19 16:23:59 -05:00
{
*endPtr = 0;
}
else
{
return false;
}
RegCloseKey(hKey);
if (std::strcmp(regred + 1, ownPth) != 0)
2017-01-19 16:23:59 -05:00
{
2017-01-20 08:36:52 -05:00
RegDeleteKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Classes\\iw4x");
2017-01-19 16:23:59 -05:00
}
else
{
return true;
}
}
else
{
2017-01-20 08:36:52 -05:00
RegDeleteKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Classes\\iw4x");
2017-01-19 16:23:59 -05:00
}
}
else
{
2017-01-20 08:36:52 -05:00
RegDeleteKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Classes\\iw4x");
2017-01-19 16:23:59 -05:00
}
// Open SOFTWARE\\Classes
openRes = RegOpenKeyExA(HKEY_CURRENT_USER, "SOFTWARE\\Classes", 0, KEY_ALL_ACCESS, &hKey);
if (openRes != ERROR_SUCCESS)
{
return false;
}
// Create SOFTWARE\\Classes\\iw4x
openRes = RegCreateKeyExA(hKey, "iw4x", 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nullptr, &hKey, nullptr);
2017-01-19 16:23:59 -05:00
if (openRes != ERROR_SUCCESS)
{
return false;
}
// Write URL:IW4x Protocol
data = "URL:IW4x Protocol";
openRes = RegSetValueExA(hKey, "URL Protocol", 0, REG_SZ, reinterpret_cast<const BYTE*>(data.data()), data.size() + 1);
if (openRes != ERROR_SUCCESS)
{
RegCloseKey(hKey);
return false;
}
// Create SOFTWARE\\Classes\\iw4x\\DefaultIcon
openRes = RegCreateKeyExA(hKey, "DefaultIcon", 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nullptr, &hKey, nullptr);
2017-01-19 16:23:59 -05:00
if (openRes != ERROR_SUCCESS)
{
return false;
}
data = Utils::String::VA("%s,1", ownPth);
openRes = RegSetValueExA(hKey, nullptr, 0, REG_SZ, reinterpret_cast<const BYTE*>(data.data()), data.size() + 1);
2017-01-19 16:23:59 -05:00
RegCloseKey(hKey);
if (openRes != ERROR_SUCCESS)
{
RegCloseKey(hKey);
return false;
}
openRes = RegOpenKeyExA(HKEY_CURRENT_USER, "SOFTWARE\\Classes\\iw4x", 0, KEY_ALL_ACCESS, &hKey);
if (openRes != ERROR_SUCCESS)
{
return false;
}
openRes = RegCreateKeyExA(hKey, "shell\\open\\command", 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nullptr, &hKey, nullptr);
2017-01-19 16:23:59 -05:00
if (openRes != ERROR_SUCCESS)
{
return false;
}
data = Utils::String::VA("\"%s\" \"%s\"", ownPth, "%1");
openRes = RegSetValueExA(hKey, nullptr, 0, REG_SZ, reinterpret_cast<const BYTE*>(data.data()), data.size() + 1);
2017-01-19 16:23:59 -05:00
RegCloseKey(hKey);
if (openRes != ERROR_SUCCESS)
{
return false;
}
return true;
}
void ConnectProtocol::EvaluateProtocol()
{
if (Evaluated) return;
Evaluated = true;
2017-01-19 16:23:59 -05:00
std::string cmdLine = GetCommandLineA();
auto pos = cmdLine.find("iw4x://");
if (pos != std::string::npos)
{
cmdLine = cmdLine.substr(pos + 7);
pos = cmdLine.find_first_of('/');
2017-01-19 16:23:59 -05:00
if (pos != std::string::npos)
{
cmdLine = cmdLine.substr(0, pos);
}
ConnectString = cmdLine;
2017-01-19 16:23:59 -05:00
}
}
void ConnectProtocol::Invocation()
{
if (Used())
2017-01-19 16:23:59 -05:00
{
Command::Execute(std::format("connect {}", ConnectString), false);
2017-01-19 16:23:59 -05:00
}
}
ConnectProtocol::ConnectProtocol()
{
if (Dedicated::IsEnabled()) return;
2017-01-19 16:23:59 -05:00
// IPC handler
2018-12-17 08:29:18 -05:00
IPCPipe::On("connect", [](const std::string& data)
{
Command::Execute(std::format("connect {}", data), false);
});
2017-01-19 16:23:59 -05:00
// Invocation handler
Scheduler::OnGameInitialized(Invocation, Scheduler::Pipeline::MAIN);
2017-01-19 16:23:59 -05:00
InstallProtocol();
EvaluateProtocol();
2017-01-19 16:23:59 -05:00
// Fire protocol handlers
// Make sure this happens after the pipe-initialization!
if (Used())
2017-01-19 16:23:59 -05:00
{
if (!Singleton::IsFirstInstance())
{
IPCPipe::Write("connect", ConnectString);
2017-01-19 16:23:59 -05:00
ExitProcess(0);
}
else
{
// Only skip intro here, invocation will be done later.
Utils::Hook::Set<std::uint8_t>(0x60BECF, 0xEB);
2017-05-31 12:12:22 -04:00
2022-06-16 10:15:26 -04:00
Scheduler::Once([]
2017-05-31 12:12:22 -04:00
{
Command::Execute("openmenu popup_reconnectingtoparty", false);
}, Scheduler::Pipeline::CLIENT, 8s);
2017-01-19 16:23:59 -05:00
}
}
}
}