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

535 lines
12 KiB
C++
Raw Normal View History

2015-12-29 17:13:23 -05:00
#include "..\..\STDInclude.hpp"
#include <psapi.h>
namespace Components
{
2016-01-03 13:29:22 -05:00
#define MAX_PROCESSES 1024
2015-12-29 17:13:23 -05:00
int evaluated = 0;
//Declarations SendMessage stuff
DWORD proc_id = 0, proc_win_id = 0;
HWND console, con_in;
bool ConnectProtocol::InstallProtocol()
{
HKEY hKey;
LPCTSTR sk = TEXT("SOFTWARE\\Classes\\iw4x\\shell\\open\\command");
LPCTSTR data = "URL:iw4x Protocol";
LPCTSTR value = TEXT("URL Protocol");
2016-01-03 13:29:22 -05:00
char ownPth[MAX_PATH] = {0};
char workdir[MAX_PATH] = {0};
char regred[MAX_PATH] = {0};
2015-12-29 17:13:23 -05:00
DWORD dwsize = MAX_PATH;
2016-01-03 13:29:22 -05:00
HMODULE hModule = GetModuleHandle(NULL);
2015-12-29 17:13:23 -05:00
if (hModule != NULL)
{
2016-01-03 13:29:22 -05:00
if (GetModuleFileName(hModule, ownPth, MAX_PATH) == ERROR)
{
OutputDebugString("ownPth = Error");
return false;
}
if (GetModuleFileName(hModule, workdir, MAX_PATH) == ERROR)
{
OutputDebugString("workdir = Error");
return false;
}
else
{
char* endPtr = strstr(workdir, "iw4x.exe");
if (endPtr != NULL)
{
*endPtr = 0;
}
else
{
return false;
}
}
//OutputDebugString(Utils::VA("EXE Path: %s", ownPth));
2015-12-29 17:13:23 -05:00
}
else
{
2016-01-03 13:29:22 -05:00
//OutputDebugString(Utils::VA("Cant get executable path"));
2015-12-29 17:13:23 -05:00
return false;
}
2016-01-03 13:29:22 -05:00
/*OutputDebugString(Utils::VA("EXE Path: %s", ownPth));
OutputDebugString(Utils::VA("EXE Path2: %s", workdir));*/
2015-12-29 17:13:23 -05:00
SetCurrentDirectory(workdir);
LONG openRes = RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey);
if (openRes == ERROR_SUCCESS)
{
//Insert Check of the Key Value here, so the protocol will work even if the game was moved.
openRes = RegQueryValueEx(hKey, 0, 0, 0, LPBYTE(regred), &dwsize);
if (openRes == ERROR_SUCCESS)
{
char* endPt = strstr(regred, "\" \"%1\"");
2016-01-03 13:29:22 -05:00
if (endPt != NULL)
{
*endPt = 0;
}
else
{
OutputDebugString("endPt = Null");
return false;
}
2015-12-29 17:13:23 -05:00
char* regredPtr = regred;
regredPtr++;
////DBG(("Reg Read1: %s", regredPtr));
RegCloseKey(hKey);
if (strcmp(regredPtr, ownPth))
{
////DBG("Protocol changed, reinstall");
2016-01-03 13:29:22 -05:00
//sk = TEXT("SOFTWARE\\Classes\\iw4x");
//openRes = RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey);
//if (openRes == ERROR_SUCCESS)
//{
// ////DBG("Protocol is corrupted, reinstall");
// RegDeleteKey(hKey, 0);
// RegCloseKey(hKey);
//}
2015-12-29 17:13:23 -05:00
sk = TEXT("SOFTWARE\\Classes\\iw4x");
2016-01-03 13:29:22 -05:00
openRes = RegDeleteKey(HKEY_CURRENT_USER, sk);
if (openRes != ERROR_SUCCESS)
2015-12-29 17:13:23 -05:00
{
////DBG("Protocol is corrupted, reinstall");
2016-01-03 13:29:22 -05:00
//RegCloseKey(hKey);
2015-12-29 17:13:23 -05:00
2016-01-03 13:29:22 -05:00
}
2015-12-29 17:13:23 -05:00
}
else{
////DBG("Protocol is already installed");
return true;
}
}
else{
2016-01-03 13:29:22 -05:00
//openRes = RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey);
//if (openRes == ERROR_SUCCESS)
//{
// ////DBG("Protocol is corrupted, reinstall");
// RegDeleteKey(hKey, 0);
// RegCloseKey(hKey);
//}
sk = TEXT("SOFTWARE\\Classes\\iw4x");
openRes = RegDeleteKey(HKEY_CURRENT_USER, sk);
if (openRes != ERROR_SUCCESS)
2015-12-29 17:13:23 -05:00
{
////DBG("Protocol is corrupted, reinstall");
2016-01-03 13:29:22 -05:00
//RegCloseKey(hKey);
2015-12-29 17:13:23 -05:00
}
}
2016-01-03 13:29:22 -05:00
//////DBG("Protocol is already installed");
//return true;
2015-12-29 17:13:23 -05:00
}
else
{
sk = TEXT("SOFTWARE\\Classes\\iw4x");
2016-01-03 13:29:22 -05:00
openRes = RegDeleteKey(HKEY_CURRENT_USER, sk);
if (openRes != ERROR_SUCCESS)
2015-12-29 17:13:23 -05:00
{
////DBG("Protocol is corrupted, reinstall");
2016-01-03 13:29:22 -05:00
//return false;
//RegCloseKey(hKey);
2015-12-29 17:13:23 -05:00
}
}
sk = TEXT("SOFTWARE\\Classes");
data = "URL:iw4x Protocol";
value = TEXT("URL Protocol");
openRes = RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey);
if (openRes == ERROR_SUCCESS)
{
////DBG("Success opening SOFTWARE\\Classes.");
sk = TEXT("iw4x");
openRes = RegCreateKeyEx(hKey, sk, 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hKey, 0);
if (openRes == ERROR_SUCCESS)
{
////DBG("Success creating SOFTWARE\\Classes\\iw3mp.");
openRes = RegSetValueEx(hKey, value, 0, REG_SZ, (LPBYTE)data, strlen(data) + 1);
if (openRes == ERROR_SUCCESS)
{
////DBG("Success writing URL:iw4x Protocol");
data = TEXT("");
openRes = RegSetValueEx(hKey, value, 0, REG_SZ, (LPBYTE)data, strlen(data) + 1);
if (openRes == ERROR_SUCCESS)
{
////DBG("Success writing URL Protocol");
sk = TEXT("DefaultIcon");
openRes = RegCreateKeyEx(hKey, sk, 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hKey, 0);
if (openRes == ERROR_SUCCESS)
{
////DBG("Success creating SOFTWARE\\Classes\\iw3mp\\DefaultIcon");
data = Utils::VA("%s,1", ownPth);
openRes = RegSetValueEx(hKey, 0, 0, REG_SZ, (LPBYTE)data, strlen(data) + 1);
if (openRes == ERROR_SUCCESS)
{
openRes = RegCloseKey(hKey);
if (openRes == ERROR_SUCCESS)
{
sk = TEXT("SOFTWARE\\Classes\\iw4x");
openRes = RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey);
if (openRes == ERROR_SUCCESS)
{
sk = TEXT("shell\\open\\command");
openRes = RegCreateKeyEx(hKey, sk, 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hKey, 0);
if (openRes == ERROR_SUCCESS)
{
data = Utils::VA("\"%s\" \"%s\"", ownPth, "%1");
////DBG(("Command is %s", data));
openRes = RegSetValueEx(hKey, 0, 0, REG_SZ, (LPBYTE)data, strlen(data) + 1);
if (openRes == ERROR_SUCCESS)
{
RegCloseKey(hKey);
}
else
{
////DBG("Error writing shell command to registry");
RegCloseKey(hKey);
return false;
}
}
else
{
////DBG("Error creating Key shell\\open\\command");
2016-01-03 13:29:22 -05:00
//RegCloseKey(hKey);
2015-12-29 17:13:23 -05:00
return false;
}
}
else
{
////DBG("Error opening SOFTWARE\\Classes\\iw3mp");
2016-01-03 13:29:22 -05:00
//RegCloseKey(hKey);
2015-12-29 17:13:23 -05:00
return false;
}
}
else
{
////DBG("Error closing DefaultIcon Key");
RegCloseKey(hKey);
return false;
}
}
else
{
////DBG("Error writing EXE Path,1 to DefaultIcon Key");
RegCloseKey(hKey);
return false;
}
}
else
{
////DBG("Error creating subkey DefaultIcon");
2016-01-03 13:29:22 -05:00
//RegCloseKey(hKey);
2015-12-29 17:13:23 -05:00
return false;
}
}
else
{
////DBG("Error writing URL Protocol");
RegCloseKey(hKey);
return false;
}
}
else
{
////DBG("Error writing URL:iw4x Protocol Code: %d", openRes);
RegCloseKey(hKey);
return false;
}
}
else
{
////DBG("Error creating key SOFTWARE\\Classes\\iw3mp");
2016-01-03 13:29:22 -05:00
//RegCloseKey(hKey);
2015-12-29 17:13:23 -05:00
return false;
}
}
else
{
////DBG("Error opening key.");
return false;
}
return true;
}
void ConnectProtocol::EvaluateProtocol()
{
if (evaluated) return;
evaluated = 1;
2016-01-03 13:29:22 -05:00
OutputDebugString("Evaluated = 1");
char* args = GetCommandLine();
OutputDebugString("GetCommandLine");
2015-12-29 17:13:23 -05:00
char* substr = strstr(args, "iw4x://");
if (!substr || substr == args)
{
2016-01-03 13:29:22 -05:00
OutputDebugString("substr==args");
OutputDebugString(substr);
OutputDebugString("substr==args");
OutputDebugString(args);
2015-12-29 17:13:23 -05:00
return;
}
2016-01-03 13:29:22 -05:00
substr += 7;
2015-12-29 17:13:23 -05:00
char* substr2 = strstr(substr, "/");
2016-01-03 13:29:22 -05:00
if (substr2 != NULL)
{
*substr2 = 0;
}
else
{
OutputDebugString("substr2 = NULL");
return;
}
2015-12-29 17:13:23 -05:00
2016-01-03 13:29:22 -05:00
////DBG(("Connecting to: %s", substr));
OutputDebugString(Utils::VA("connect %s", substr));
Command::Execute(Utils::VA("connect %s;", substr), true);
2015-12-29 17:13:23 -05:00
}
BOOL ConnectProtocol::InvokeConnect()
{
char* args = GetCommandLineA();
char* substr = strstr(args, "iw4x://");
////DBG("Mutex give us a Handle = %d", mutex);
////DBG("Last Error = %d", GetLastError());
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
if (!substr || substr == args)
{
// Not started using the protocol
return FALSE;
}
//Now we have to get the Window Handle of the Console and the Handle of the Input field
////DBG("The Game is already running");
FindEditHandle("iw4x.exe");
2016-01-03 13:29:22 -05:00
2015-12-29 17:13:23 -05:00
substr += 7;
char* substr2 = strstr(substr, "/");
2016-01-03 13:29:22 -05:00
if (substr2 != NULL)
{
*substr2 = 0;
}
else
{
return false;
}
2015-12-29 17:13:23 -05:00
if (proc_id != 0)
{
if (con_in != NULL)
{
SendMessageA(con_in, WM_SETTEXT, NULL, (LPARAM)Utils::VA("connect %s;", substr));
SendMessageA(con_in, WM_CHAR, 0xD, 0);
}
}
else
{
return FALSE;
////DBG("Did not find Process by Name iw4x");
}
////DBG("Exit this Instance");
return TRUE;
2016-01-03 13:29:22 -05:00
2015-12-29 17:13:23 -05:00
}
else
{
if (substr && substr != args)
{
// Skip intro
*(BYTE*)0x60BECF = 0xEB;
return FALSE;
}
return FALSE;
}
return FALSE;
}
ConnectProtocol::ConnectProtocol()
{
2016-01-03 13:29:22 -05:00
OutputDebugString("Installing Protocol");
2015-12-29 17:13:23 -05:00
ConnectProtocol::InstallProtocol();
2016-01-03 13:29:22 -05:00
ConnectProtocol::EvaluateProtocol();
2015-12-29 17:13:23 -05:00
}
//Send Connect Command to running iw4x instance
2015-12-30 09:37:53 -05:00
BOOL CALLBACK ConnectProtocol::EnumWindowsProc(__in HWND hWnd, __in LPARAM lParam) {
2015-12-29 17:13:23 -05:00
DWORD id = GetWindowThreadProcessId(hWnd, &id);
DWORD id2 = GetWindowThreadProcessId(FindWindowFromProcessId(proc_id), &id2);
//DBG("process id: %d %d Real ID: %d", id, id2, proc_id);
if (id == id2)
{
//printf("THEY MATCH!process id: %d\n", id);
char buffer[256];
GetWindowText(hWnd, (LPSTR)buffer, 255);
char* endPtr = strstr(buffer, "Console");
if (endPtr != 0)
{
//DBG(("Got Process Window Handle: %d, Window Text = %s", hWnd, buffer));
console = hWnd;
EnumChildWindows(console, EnumChildProc, NULL);
return FALSE;
}
}
else{
//DBG(("Got no Process Window Handle!!!!!!!!!!!!"));
}
return TRUE;
}
2015-12-30 09:37:53 -05:00
BOOL CALLBACK ConnectProtocol::EnumChildProc(HWND hwnd, LPARAM lParam) {
2015-12-29 17:13:23 -05:00
char buffer[256];
GetClassName(hwnd, (LPSTR)buffer, 255);
char* endPtr = strstr(buffer, "Edit");
if (endPtr != 0)
{
con_in = hwnd;
//DBG("Got Handle of Edit Field: %d", hwnd);
return FALSE;
}
return TRUE;
}
struct EnumData {
DWORD dwProcessId;
HWND hWnd;
};
2015-12-30 09:37:53 -05:00
BOOL CALLBACK ConnectProtocol::EnumProc(HWND hWnd, LPARAM lParam) {
2015-12-29 17:13:23 -05:00
// Retrieve storage location for communication data
EnumData& ed = *(EnumData*)lParam;
DWORD dwProcessId = 0x0;
// Query process ID for hWnd
GetWindowThreadProcessId(hWnd, &dwProcessId);
// Apply filter - if you want to implement additional restrictions,
// this is the place to do so.
if (ed.dwProcessId == dwProcessId) {
// Found a window matching the process ID
ed.hWnd = hWnd;
// Report success
SetLastError(ERROR_SUCCESS);
// Stop enumeration
return FALSE;
}
// Continue enumeration
return TRUE;
}
2015-12-30 09:37:53 -05:00
void ConnectProtocol::FindEditHandle(__in_z LPCTSTR lpcszFileName)
2015-12-29 17:13:23 -05:00
{
LPDWORD lpdwProcessIds;
LPTSTR lpszBaseName;
HANDLE hProcess;
DWORD i, cdwProcesses, dwProcessId = 0;
lpdwProcessIds = (LPDWORD)HeapAlloc(GetProcessHeap(), 0, MAX_PROCESSES*sizeof(DWORD));
if (lpdwProcessIds != NULL)
{
if (EnumProcesses(lpdwProcessIds, MAX_PROCESSES*sizeof(DWORD), &cdwProcesses))
{
lpszBaseName = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(TCHAR));
if (lpszBaseName != NULL)
{
cdwProcesses /= sizeof(DWORD);
for (i = 0; i < cdwProcesses; i++)
{
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, lpdwProcessIds[i]);
if (hProcess != NULL)
{
if (GetModuleBaseName(hProcess, NULL, lpszBaseName, MAX_PATH) > 0)
{
//DBG(("Process Name = %s", lpszBaseName));
if (!lstrcmpi(lpszBaseName, lpcszFileName))
{
//DBG("Stage 8");
dwProcessId = lpdwProcessIds[i];
CloseHandle(hProcess);
proc_id = dwProcessId;
2015-12-30 09:37:53 -05:00
EnumWindows(EnumWindowsProc, NULL);
2015-12-29 17:13:23 -05:00
if (con_in != NULL)
{
break;
}
}
}
CloseHandle(hProcess);
}
}
HeapFree(GetProcessHeap(), 0, (LPVOID)lpszBaseName);
}
}
HeapFree(GetProcessHeap(), 0, (LPVOID)lpdwProcessIds);
}
//DBG("Return %d", dwProcessId);
//return dwProcessId;
}
// Main entry
2015-12-30 09:37:53 -05:00
HWND ConnectProtocol::FindWindowFromProcessId(DWORD dwProcessId) {
2015-12-29 17:13:23 -05:00
EnumData ed = { dwProcessId };
if (!EnumWindows(EnumProc, (LPARAM)&ed) &&
(GetLastError() == ERROR_SUCCESS)) {
return ed.hWnd;
}
return NULL;
}
// Helper method for convenience
2015-12-30 09:37:53 -05:00
HWND ConnectProtocol::FindWindowFromProcess(HANDLE hProcess) {
2015-12-29 17:13:23 -05:00
return FindWindowFromProcessId(GetProcessId(hProcess));
}
}