2022-02-27 07:53:44 -05:00
|
|
|
#include <STDInclude.hpp>
|
2022-12-26 07:07:24 -05:00
|
|
|
#include "ConnectProtocol.hpp"
|
2017-01-19 16:23:59 -05:00
|
|
|
|
|
|
|
namespace Components
|
|
|
|
{
|
|
|
|
bool ConnectProtocol::Evaluated = false;
|
|
|
|
std::string ConnectProtocol::ConnectString;
|
|
|
|
|
|
|
|
bool ConnectProtocol::IsEvaluated()
|
|
|
|
{
|
2022-12-11 12:54:24 -05:00
|
|
|
return Evaluated;
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ConnectProtocol::Used()
|
|
|
|
{
|
2022-12-11 12:54:24 -05:00
|
|
|
if (!IsEvaluated())
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
2022-12-11 12:54:24 -05:00
|
|
|
EvaluateProtocol();
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
|
2022-12-11 12:54:24 -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;
|
|
|
|
|
2022-12-11 12:54:24 -05:00
|
|
|
char ownPth[MAX_PATH]{};
|
|
|
|
char workdir[MAX_PATH]{};
|
2017-01-19 16:23:59 -05:00
|
|
|
|
|
|
|
DWORD dwsize = MAX_PATH;
|
2022-09-08 11:11:54 -04:00
|
|
|
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
|
|
|
|
{
|
2022-09-08 11:11:54 -04:00
|
|
|
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)
|
|
|
|
{
|
2022-12-11 12:54:24 -05:00
|
|
|
char regred[MAX_PATH]{};
|
2017-01-19 16:23:59 -05:00
|
|
|
|
|
|
|
// Check if the game has been moved.
|
2017-01-20 16:41:03 -05:00
|
|
|
openRes = RegQueryValueExA(hKey, nullptr, nullptr, nullptr, reinterpret_cast<BYTE*>(regred), &dwsize);
|
2017-01-19 16:23:59 -05:00
|
|
|
if (openRes == ERROR_SUCCESS)
|
|
|
|
{
|
2022-12-11 12:54:24 -05:00
|
|
|
auto* endPtr = std::strstr(regred, "\" \"%1\"");
|
2017-01-20 16:41:03 -05:00
|
|
|
if (endPtr != nullptr)
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
|
|
|
*endPtr = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegCloseKey(hKey);
|
2022-12-11 12:54:24 -05:00
|
|
|
|
|
|
|
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
|
2017-01-20 16:41:03 -05:00
|
|
|
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
|
2017-01-20 16:41:03 -05:00
|
|
|
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);
|
2017-01-20 16:41:03 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-01-20 16:41:03 -05:00
|
|
|
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");
|
2017-01-20 16:41:03 -05:00
|
|
|
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()
|
|
|
|
{
|
2022-12-11 12:54:24 -05:00
|
|
|
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);
|
2022-09-08 11:11:54 -04:00
|
|
|
pos = cmdLine.find_first_of('/');
|
2017-01-19 16:23:59 -05:00
|
|
|
|
|
|
|
if (pos != std::string::npos)
|
|
|
|
{
|
|
|
|
cmdLine = cmdLine.substr(0, pos);
|
|
|
|
}
|
|
|
|
|
2022-12-11 12:54:24 -05:00
|
|
|
ConnectString = cmdLine;
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConnectProtocol::Invocation()
|
|
|
|
{
|
2022-12-11 12:54:24 -05:00
|
|
|
if (Used())
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
2022-12-11 12:54:24 -05:00
|
|
|
Command::Execute(std::format("connect {}", ConnectString), false);
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ConnectProtocol::ConnectProtocol()
|
|
|
|
{
|
2017-02-21 15:49:42 -05:00
|
|
|
if (Dedicated::IsEnabled()) return;
|
2017-02-21 15:39:40 -05:00
|
|
|
|
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)
|
2017-01-27 17:09:32 -05:00
|
|
|
{
|
2022-12-11 12:54:24 -05:00
|
|
|
Command::Execute(std::format("connect {}", data), false);
|
2017-01-27 17:09:32 -05:00
|
|
|
});
|
2017-01-19 16:23:59 -05:00
|
|
|
|
|
|
|
// Invocation handler
|
2022-12-11 12:54:24 -05:00
|
|
|
Scheduler::OnGameInitialized(Invocation, Scheduler::Pipeline::MAIN);
|
2017-01-19 16:23:59 -05:00
|
|
|
|
2022-12-11 12:54:24 -05:00
|
|
|
InstallProtocol();
|
|
|
|
EvaluateProtocol();
|
2017-01-19 16:23:59 -05:00
|
|
|
|
|
|
|
// Fire protocol handlers
|
|
|
|
// Make sure this happens after the pipe-initialization!
|
2022-12-11 12:54:24 -05:00
|
|
|
if (Used())
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
|
|
|
if (!Singleton::IsFirstInstance())
|
|
|
|
{
|
2022-12-11 12:54:24 -05:00
|
|
|
IPCPipe::Write("connect", ConnectString);
|
2017-01-19 16:23:59 -05:00
|
|
|
ExitProcess(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Only skip intro here, invocation will be done later.
|
2022-12-11 12:54:24 -05:00
|
|
|
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);
|
2022-05-05 10:03:14 -04:00
|
|
|
}, Scheduler::Pipeline::CLIENT, 8s);
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|