mirror of
https://gitlab.com/Syroot/Worms.git
synced 2025-01-13 07:18:00 +03:00
Extend fkNetcode with settings and better error handling.
This commit is contained in:
parent
71c8f33ea7
commit
180a61a147
@ -1,4 +1,3 @@
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ void fkAttach()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf_s<MAX_PATH>(buffer, "Could not load module %s.", findFileData.cFileName);
|
sprintf_s(buffer, "Could not load module %s.", findFileData.cFileName);
|
||||||
MessageBox(NULL, buffer, "FrontendKit", MB_ICONWARNING);
|
MessageBox(NULL, buffer, "FrontendKit", MB_ICONWARNING);
|
||||||
}
|
}
|
||||||
} while (FindNextFile(hFindFile, &findFileData));
|
} while (FindNextFile(hFindFile, &findFileData));
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
typedef struct PEInfo
|
typedef struct PEInfo
|
||||||
|
38
src/tool/fkNetcode/fkConfig.cpp
Normal file
38
src/tool/fkNetcode/fkConfig.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "fkConfig.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace fk
|
||||||
|
{
|
||||||
|
Config::Config(LPCSTR fileName)
|
||||||
|
{
|
||||||
|
DWORD length = GetModuleFileName(NULL, _filePath, MAX_PATH);
|
||||||
|
strcpy_s(strrchr(_filePath, '\\') + 1, MAX_PATH, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::get(LPCSTR category, LPCSTR key, BOOL& result, UINT fallback) const
|
||||||
|
{
|
||||||
|
result = GetPrivateProfileInt(category, key, fallback, _filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::get(LPCSTR category, LPCSTR key, UINT& result, UINT fallback) const
|
||||||
|
{
|
||||||
|
result = GetPrivateProfileInt(category, key, fallback, _filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::get(LPCSTR category, LPCSTR key, LPSTR result, INT resultLength, LPCSTR fallback) const
|
||||||
|
{
|
||||||
|
GetPrivateProfileString(category, key, fallback, result, resultLength, _filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::set(LPCSTR category, LPCSTR key, UINT value) const
|
||||||
|
{
|
||||||
|
CHAR buffer[32];
|
||||||
|
sprintf_s(buffer, "%d", value);
|
||||||
|
WritePrivateProfileString(category, key, buffer, _filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::set(LPCSTR category, LPCSTR key, LPCSTR value) const
|
||||||
|
{
|
||||||
|
WritePrivateProfileString(category, key, value, _filePath);
|
||||||
|
}
|
||||||
|
}
|
20
src/tool/fkNetcode/fkConfig.h
Normal file
20
src/tool/fkNetcode/fkConfig.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
namespace fk
|
||||||
|
{
|
||||||
|
class Config
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Config(LPCSTR fileName);
|
||||||
|
|
||||||
|
void get(LPCSTR category, LPCSTR key, BOOL& result, UINT fallback) const;
|
||||||
|
void get(LPCSTR category, LPCSTR key, UINT& result, UINT fallback) const;
|
||||||
|
void get(LPCSTR category, LPCSTR key, LPSTR result, INT resultLength, LPCSTR fallback = NULL) const;
|
||||||
|
void set(LPCSTR category, LPCSTR key, UINT value) const;
|
||||||
|
void set(LPCSTR category, LPCSTR key, LPCSTR value) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CHAR _filePath[MAX_PATH];
|
||||||
|
};
|
||||||
|
}
|
@ -87,14 +87,23 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="fkConfig.cpp" />
|
||||||
|
<ClCompile Include="fkPatch.cpp" />
|
||||||
|
<ClCompile Include="fkUtils.cpp" />
|
||||||
|
<ClCompile Include="fkWinHandle.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
<ClCompile Include="misc_tools.cpp" />
|
|
||||||
<ClCompile Include="PEInfo.cpp" />
|
<ClCompile Include="PEInfo.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="misc_tools.h" />
|
<ClInclude Include="fkConfig.h" />
|
||||||
|
<ClInclude Include="fkWinHandle.h" />
|
||||||
|
<ClInclude Include="fkPatch.h" />
|
||||||
|
<ClInclude Include="fkUtils.h" />
|
||||||
<ClInclude Include="PEInfo.h" />
|
<ClInclude Include="PEInfo.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="fkPatch.inl" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
28
src/tool/fkNetcode/fkPatch.cpp
Normal file
28
src/tool/fkNetcode/fkPatch.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "fkPatch.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace fk
|
||||||
|
{
|
||||||
|
Patch::Patch(LPVOID lpAddress, SIZE_T dwSize)
|
||||||
|
: _lpAddress(static_cast<LPBYTE>(lpAddress))
|
||||||
|
, _dwSize(dwSize)
|
||||||
|
, dwPosition(0)
|
||||||
|
{
|
||||||
|
if (!_lpAddress || !_dwSize)
|
||||||
|
throw std::invalid_argument("Address and size must not be 0.");
|
||||||
|
if (!VirtualProtect(_lpAddress, _dwSize, PAGE_EXECUTE_READWRITE, &_flOldProtect))
|
||||||
|
throw std::exception("VirtualProtect failed, call GetLastError for more info.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Patch::~Patch()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Patch::close() const
|
||||||
|
{
|
||||||
|
DWORD oldProtect;
|
||||||
|
if (!VirtualProtect(_lpAddress, _dwSize, _flOldProtect, &oldProtect))
|
||||||
|
throw std::exception("VirtualProtect failed, call GetLastError for more info.");
|
||||||
|
}
|
||||||
|
};
|
24
src/tool/fkNetcode/fkPatch.h
Normal file
24
src/tool/fkNetcode/fkPatch.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
namespace fk
|
||||||
|
{
|
||||||
|
struct Patch
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DWORD dwPosition;
|
||||||
|
|
||||||
|
Patch(LPVOID lpAddress, SIZE_T dwSize);
|
||||||
|
~Patch();
|
||||||
|
|
||||||
|
void close() const;
|
||||||
|
template <class T> void write(const T& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
LPBYTE _lpAddress;
|
||||||
|
SIZE_T _dwSize;
|
||||||
|
DWORD _flOldProtect;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "fkPatch.inl"
|
10
src/tool/fkNetcode/fkPatch.inl
Normal file
10
src/tool/fkNetcode/fkPatch.inl
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace fk
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
void Patch::write(const T& value)
|
||||||
|
{
|
||||||
|
memcpy_s(_lpAddress + dwPosition, sizeof(T), &value, sizeof(T));
|
||||||
|
dwPosition += sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
89
src/tool/fkNetcode/fkUtils.cpp
Normal file
89
src/tool/fkNetcode/fkUtils.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include "fkUtils.h"
|
||||||
|
#include "fkPatch.h"
|
||||||
|
|
||||||
|
namespace fk
|
||||||
|
{
|
||||||
|
int getGameVersion(DWORD timeDateStamp)
|
||||||
|
{
|
||||||
|
switch (timeDateStamp)
|
||||||
|
{
|
||||||
|
case 0x3528DAFA: return GAME_VERSION_BR;
|
||||||
|
case 0x3528DCB1: return GAME_VERSION_EN;
|
||||||
|
case 0x3528DB52: return GAME_VERSION_GE;
|
||||||
|
case 0x3528DA98: return GAME_VERSION_NA;
|
||||||
|
case 0x3528DBDA: return GAME_VERSION_SA;
|
||||||
|
case 0x3587BE19: return GAME_VERSION_TRY;
|
||||||
|
}
|
||||||
|
return GAME_VERSION_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void throwLastError()
|
||||||
|
{
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
if (error == ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LPTSTR buffer = NULL;
|
||||||
|
const DWORD cchMsg = FormatMessageA(
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL,
|
||||||
|
error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>(&buffer), 0, NULL);
|
||||||
|
if (cchMsg > 0)
|
||||||
|
{
|
||||||
|
std::string message(buffer);
|
||||||
|
LocalFree(buffer);
|
||||||
|
throw std::exception(message.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHAR buffer[32];
|
||||||
|
sprintf_s(buffer, "Error code 0x%08X.", error);
|
||||||
|
throw std::exception(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void patchNops(ULONG dwAddr, SIZE_T dwPatchSize)
|
||||||
|
{
|
||||||
|
fk::Patch patch(reinterpret_cast<void*>(dwAddr), dwPatchSize);
|
||||||
|
while (dwPatchSize--)
|
||||||
|
patch.write<BYTE>(0x90);
|
||||||
|
}
|
||||||
|
|
||||||
|
void patchJump(PVOID pDest, SIZE_T dwPatchSize, PVOID pCallee, DWORD dwJumpType)
|
||||||
|
{
|
||||||
|
fk::Patch patch(pDest, dwPatchSize);
|
||||||
|
|
||||||
|
if (dwPatchSize >= 5 && pDest)
|
||||||
|
{
|
||||||
|
BYTE OpSize, OpCode;
|
||||||
|
switch (dwJumpType)
|
||||||
|
{
|
||||||
|
case IJ_PUSHRET: OpSize = 6; OpCode = 0x68; break;
|
||||||
|
case IJ_FARJUMP: OpSize = 7; OpCode = 0xEA; break;
|
||||||
|
case IJ_FARCALL: OpSize = 7; OpCode = 0x9A; break;
|
||||||
|
case IJ_CALL: OpSize = 5; OpCode = 0xE8; break;
|
||||||
|
default: OpSize = 5; OpCode = 0xE9; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwPatchSize < OpSize)
|
||||||
|
throw std::exception("Not enough space to patch opcode.");
|
||||||
|
|
||||||
|
patch.write(OpCode);
|
||||||
|
switch (OpSize)
|
||||||
|
{
|
||||||
|
case 7:
|
||||||
|
patch.write((ULONG)pCallee);
|
||||||
|
patch.write<WORD>(0x23);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
patch.write((ULONG)pCallee);
|
||||||
|
patch.write<BYTE>(0xC3);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
patch.write((ULONG)pCallee - (ULONG)pDest - 5);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (DWORD i = OpSize; i < dwPatchSize; i++)
|
||||||
|
patch.write<BYTE>(0x90);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
src/tool/fkNetcode/fkUtils.h
Normal file
32
src/tool/fkNetcode/fkUtils.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
namespace fk
|
||||||
|
{
|
||||||
|
enum GameVersion
|
||||||
|
{
|
||||||
|
GAME_VERSION_NONE = -1,
|
||||||
|
GAME_VERSION_BR, // 1.05 Br
|
||||||
|
GAME_VERSION_EN, // 1.05 Du, En, Fr, It, Po, Sp, Sw
|
||||||
|
GAME_VERSION_GE, // 1.05
|
||||||
|
GAME_VERSION_NA, // 1.05
|
||||||
|
GAME_VERSION_SA, // 1.05
|
||||||
|
GAME_VERSION_TRY // 1.07 Trymedia
|
||||||
|
};
|
||||||
|
|
||||||
|
enum InsertJump
|
||||||
|
{
|
||||||
|
IJ_JUMP, // Insert a jump (0xE9) with patchJump
|
||||||
|
IJ_CALL, // Insert a call (0xE8) with patchJump
|
||||||
|
IJ_FARJUMP, // Insert a farjump (0xEA) with patchJump
|
||||||
|
IJ_FARCALL, // Insert a farcall (0x9A) with patchJump
|
||||||
|
IJ_PUSHRET, // Insert a pushret with patchJump
|
||||||
|
};
|
||||||
|
|
||||||
|
int getGameVersion(DWORD timeDateStamp);
|
||||||
|
void throwLastError();
|
||||||
|
|
||||||
|
void patchNops(ULONG dwAddr, SIZE_T dwPatchSize);
|
||||||
|
void patchJump(PVOID pDest, SIZE_T dwPatchSize, PVOID pCallee, DWORD dwJumpType = IJ_JUMP);
|
||||||
|
}
|
20
src/tool/fkNetcode/fkWinHandle.cpp
Normal file
20
src/tool/fkNetcode/fkWinHandle.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "fkWinHandle.h"
|
||||||
|
#include "fkUtils.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace fk
|
||||||
|
{
|
||||||
|
WinHandle::WinHandle(HANDLE handle, BOOL(__stdcall* closeProc)(HANDLE))
|
||||||
|
: _handle(handle)
|
||||||
|
, _closeProc(closeProc)
|
||||||
|
{
|
||||||
|
if (!_handle || _handle == INVALID_HANDLE_VALUE)
|
||||||
|
fk::throwLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
WinHandle::~WinHandle()
|
||||||
|
{
|
||||||
|
if (_handle)
|
||||||
|
_closeProc(_handle);
|
||||||
|
}
|
||||||
|
}
|
19
src/tool/fkNetcode/fkWinHandle.h
Normal file
19
src/tool/fkNetcode/fkWinHandle.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
namespace fk
|
||||||
|
{
|
||||||
|
struct WinHandle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WinHandle(HANDLE handle, BOOL(__stdcall* closeProc)(HANDLE));
|
||||||
|
~WinHandle();
|
||||||
|
|
||||||
|
operator bool() { return _handle; }
|
||||||
|
operator HANDLE() { return _handle; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
HANDLE _handle;
|
||||||
|
BOOL(__stdcall* _closeProc)(HANDLE);
|
||||||
|
};
|
||||||
|
}
|
@ -1,77 +1,101 @@
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <iostream>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <WinInet.h>
|
#include <WinInet.h>
|
||||||
|
#include "fkConfig.h"
|
||||||
|
#include "fkUtils.h"
|
||||||
|
#include "fkWinHandle.h"
|
||||||
#include "PEInfo.h"
|
#include "PEInfo.h"
|
||||||
#include "misc_tools.h"
|
|
||||||
|
|
||||||
|
CHAR cfgFallbackIP[16];
|
||||||
|
CHAR cfgServiceUrl[MAX_PATH];
|
||||||
|
BOOL cfgShowErrors;
|
||||||
PEInfo pe;
|
PEInfo pe;
|
||||||
CHAR szFoundIP[16] = {};
|
CHAR resolvedIP[16] = {};
|
||||||
|
|
||||||
enum GameRegion
|
void configure()
|
||||||
{
|
{
|
||||||
GAME_REGION_NONE = -1,
|
fk::Config config("fkNetcode.ini");
|
||||||
GAME_REGION_BR,
|
|
||||||
GAME_REGION_EN, // Du, En, Fr, It, Po, Sp, Sw have the same executable
|
|
||||||
GAME_REGION_GE,
|
|
||||||
GAME_REGION_NA,
|
|
||||||
GAME_REGION_SA
|
|
||||||
};
|
|
||||||
|
|
||||||
int getRegion()
|
// Load INI settings.
|
||||||
|
config.get("AddressResolval", "FallbackIP", cfgFallbackIP, 16);
|
||||||
|
config.get("AddressResolval", "ServiceUrl", cfgServiceUrl, MAX_PATH, "http://ip.syroot.com");
|
||||||
|
config.get("AddressResolval", "ShowErrors", cfgShowErrors, TRUE);
|
||||||
|
|
||||||
|
// Ensure INI file has been created with default setting.
|
||||||
|
config.set("AddressResolval", "FallbackIP", cfgFallbackIP);
|
||||||
|
config.set("AddressResolval", "ServiceUrl", cfgServiceUrl);
|
||||||
|
config.set("AddressResolval", "ShowErrors", cfgShowErrors);
|
||||||
|
|
||||||
|
// Validate fallback IP.
|
||||||
|
BYTE b;
|
||||||
|
if (*cfgFallbackIP && sscanf_s(cfgFallbackIP, "%hhu.%hhu.%hhu.%hhu", &b, &b, &b, &b) != 4)
|
||||||
{
|
{
|
||||||
switch (pe.FH->TimeDateStamp)
|
*cfgFallbackIP = NULL;
|
||||||
{
|
MessageBox(NULL, "Invalid fallback IP setting in fkNetcode.ini has been ignored.", "fkNetcode", MB_ICONWARNING);
|
||||||
case 0x3528DAFA: return GAME_REGION_BR;
|
|
||||||
case 0x3528DCB1: return GAME_REGION_EN;
|
|
||||||
case 0x3528DB52: return GAME_REGION_GE;
|
|
||||||
case 0x3528DA98: return GAME_REGION_NA;
|
|
||||||
case 0x3528DBDA: return GAME_REGION_SA;
|
|
||||||
}
|
}
|
||||||
return GAME_REGION_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool __stdcall getLabelIP(LPSTR buffer, int bufferLength)
|
void resolveIP(LPTSTR buffer)
|
||||||
{
|
{
|
||||||
if (!szFoundIP[0])
|
if (!*resolvedIP)
|
||||||
{
|
{
|
||||||
// Initially resolve the external IP through a web service.
|
// Initially resolve the external IP through a web service.
|
||||||
HINTERNET hInternet = 0, hFile = 0;
|
fk::WinHandle hInternet(InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0), InternetCloseHandle);
|
||||||
DWORD bytesRead = 0;
|
fk::WinHandle hFile(InternetOpenUrl(hInternet, cfgServiceUrl, NULL, 0,
|
||||||
CHAR buffer[16];
|
INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD, NULL), InternetCloseHandle);
|
||||||
|
|
||||||
if ((hInternet = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0))
|
DWORD responseLength = 0;
|
||||||
&& (hFile = InternetOpenUrl(hInternet, "http://ip.syroot.com", NULL, 0,
|
CHAR response[16];
|
||||||
INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD, NULL))
|
if (!InternetReadFile(hFile, response, 16, &responseLength))
|
||||||
&& InternetReadFile(hFile, buffer, 16, &bytesRead) && bytesRead >= 8)
|
fk::throwLastError();
|
||||||
|
if (responseLength < 8)
|
||||||
|
throw std::exception("Response was too short.");
|
||||||
|
|
||||||
|
response[responseLength] = '\0';
|
||||||
|
BYTE temp;
|
||||||
|
if (sscanf_s(response, "%hhu.%hhu.%hhu.%hhu", &temp, &temp, &temp, &temp) != 4)
|
||||||
|
throw std::exception("Response could not be parsed.");
|
||||||
|
|
||||||
|
lstrcpy(resolvedIP, response);
|
||||||
|
}
|
||||||
|
lstrcpy(buffer, resolvedIP);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __stdcall patchResolveIP(LPSTR buffer, int bufferLength)
|
||||||
{
|
{
|
||||||
buffer[bytesRead] = '\0';
|
try
|
||||||
uint8_t temp;
|
|
||||||
if (sscanf_s(buffer, "%hhu.%hhu.%hhu.%hhu", &temp, &temp, &temp, &temp) == 4)
|
|
||||||
lstrcpy(szFoundIP, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hFile) InternetCloseHandle(hFile);
|
|
||||||
if (hInternet) InternetCloseHandle(hInternet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the detected IP.
|
|
||||||
lstrcpy(buffer, szFoundIP);
|
|
||||||
return buffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void applyPatches()
|
|
||||||
{
|
{
|
||||||
// Replace NAT IP detection with web service.
|
resolveIP(buffer);
|
||||||
InsertJump((PVOID)pe.Offset(0x00001799), 5, &getLabelIP, IJ_JUMP);
|
}
|
||||||
|
catch (std::exception& ex)
|
||||||
|
{
|
||||||
|
lstrcpy(buffer, *cfgFallbackIP ? cfgFallbackIP : "0.0.0.0");
|
||||||
|
if (cfgShowErrors)
|
||||||
|
{
|
||||||
|
CHAR message[512];
|
||||||
|
sprintf_s(message, "Could not resolve your IP address. %s", ex.what());
|
||||||
|
MessageBox(NULL, message, "fkNetcode", MB_ICONWARNING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true; // not used
|
||||||
|
}
|
||||||
|
|
||||||
// Prevent overriding the resolved IP when connecting to server.
|
void patch(int gameVersion)
|
||||||
PatchMemNop(pe.Offset(0x00053E96), 5); // writes user name
|
{
|
||||||
PatchMemNop(pe.Offset(0x00054993), 5); // writes NAT IP
|
fk::patchJump((PVOID)pe.Offset(0x00001799), 5, &patchResolveIP, fk::IJ_JUMP); // replace IP resolve with web service
|
||||||
|
|
||||||
// Remove useless sleeps.
|
if (gameVersion == fk::GAME_VERSION_TRY)
|
||||||
PatchMemNop(pe.Offset(0x00054935), 11);
|
{
|
||||||
|
fk::patchNops(pe.Offset(0x00053B96), 5); // prevent overriding IP with user name
|
||||||
|
fk::patchNops(pe.Offset(0x00054693), 5); // prevent overriding IP with NAT IP
|
||||||
|
fk::patchNops(pe.Offset(0x00054635), 11); // useless sleep when connecting to server
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fk::patchNops(pe.Offset(0x00053E96), 5); // prevent overriding IP with user name
|
||||||
|
fk::patchNops(pe.Offset(0x00054935), 11); // useless sleep when connecting to server
|
||||||
|
fk::patchNops(pe.Offset(0x00054993), 5); // prevent overriding IP with NAT IP
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HMODULE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
BOOL WINAPI DllMain(HMODULE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
@ -79,15 +103,19 @@ BOOL WINAPI DllMain(HMODULE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||||||
switch (fdwReason)
|
switch (fdwReason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
if (getRegion() == GAME_REGION_NONE)
|
|
||||||
{
|
{
|
||||||
MessageBox(NULL, "fkNetcode is incompatible with your game version or region and will not be able to "
|
int version = fk::getGameVersion(pe.FH->TimeDateStamp);
|
||||||
"resolve your external IP address. Please install the Worms 2 1.05 patch or delete this module to "
|
if (version == fk::GAME_VERSION_NONE)
|
||||||
"remove this warning.", "fkNetcode", MB_ICONWARNING);
|
{
|
||||||
|
MessageBox(NULL, "fkNetcode is incompatible with your game version. Please run the 1.05 patch or "
|
||||||
|
"1.07 release of Worms 2. Otherwise, you can delete the module to remove this warning.",
|
||||||
|
"fkNetcode", MB_ICONWARNING);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
applyPatches();
|
configure();
|
||||||
|
patch(version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
#include <Windows.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "misc_tools.h"
|
|
||||||
|
|
||||||
BOOL WritePrivateProfileIntA(LPCSTR lpAppName, LPCSTR lpKeyName, int nInteger, LPCSTR lpFileName)
|
|
||||||
{
|
|
||||||
CHAR lpString[32];
|
|
||||||
sprintf_s(lpString, "%d", nInteger);
|
|
||||||
return WritePrivateProfileStringA(lpAppName, lpKeyName, lpString, lpFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
LPSTR GetPathUnderModuleA(HMODULE hModule, LPSTR OutBuf, LPCSTR FileName)
|
|
||||||
{
|
|
||||||
GetModuleFileNameA(hModule, OutBuf, MAX_PATH);
|
|
||||||
CHAR* dirend = strrchr(OutBuf, '\\') + 1;
|
|
||||||
strcpy_s(dirend, MAX_PATH, FileName);
|
|
||||||
return OutBuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL __stdcall PatchMemData(ULONG dwAddr, ULONG dwBufLen, PVOID pNewData, ULONG dwDataLen)
|
|
||||||
{
|
|
||||||
if (!dwDataLen || !pNewData || !dwAddr)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
DWORD dwLastProtection;
|
|
||||||
if (!VirtualProtect((void*)dwAddr, dwDataLen, PAGE_EXECUTE_READWRITE, &dwLastProtection))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memcpy_s((PVOID)dwAddr, dwBufLen, pNewData, dwDataLen);
|
|
||||||
|
|
||||||
return VirtualProtect((void*)dwAddr, dwDataLen, dwLastProtection, &dwLastProtection);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL __stdcall PatchMemQword(ULONG dwAddr, QWORD qNewValue) { return PatchMemData(dwAddr, 8, &qNewValue, 8); }
|
|
||||||
BOOL __stdcall PatchMemDword(ULONG dwAddr, DWORD dwNewValue) { return PatchMemData(dwAddr, 4, &dwNewValue, 4); }
|
|
||||||
BOOL __stdcall PatchMemWord(ULONG dwAddr, WORD wNewValue) { return PatchMemData(dwAddr, 2, &wNewValue, 2); }
|
|
||||||
BOOL __stdcall PatchMemByte(ULONG dwAddr, BYTE bNewValue) { return PatchMemData(dwAddr, 1, &bNewValue, 1); }
|
|
||||||
BOOL __stdcall PatchMemFloat(ULONG dwAddr, FLOAT fNewValue)
|
|
||||||
{
|
|
||||||
DWORD dwLastProtection;
|
|
||||||
if (!VirtualProtect((void*)dwAddr, sizeof(FLOAT), PAGE_EXECUTE_READWRITE, &dwLastProtection))
|
|
||||||
return 0;
|
|
||||||
*(FLOAT*)dwAddr = fNewValue;
|
|
||||||
return VirtualProtect((void*)dwAddr, sizeof(FLOAT), dwLastProtection, &dwLastProtection);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL __stdcall PatchMemNop(ULONG dwAddr, DWORD dwPatchSize)
|
|
||||||
{
|
|
||||||
while (dwPatchSize-- && PatchMemByte(dwAddr++, 0x90));
|
|
||||||
return dwPatchSize == 0;
|
|
||||||
}
|
|
||||||
BOOL __stdcall InsertJump(PVOID pDest, DWORD dwPatchSize, PVOID pCallee, DWORD dwJumpType)
|
|
||||||
{
|
|
||||||
if (dwPatchSize >= 5 && pDest)
|
|
||||||
{
|
|
||||||
DWORD OpSize, OpCode;
|
|
||||||
switch (dwJumpType)
|
|
||||||
{
|
|
||||||
case IJ_PUSHRET: OpSize = 6; OpCode = 0x68; break;
|
|
||||||
case IJ_FARJUMP: OpSize = 7; OpCode = 0xEA; break;
|
|
||||||
case IJ_FARCALL: OpSize = 7; OpCode = 0x9A; break;
|
|
||||||
case IJ_CALL: OpSize = 5; OpCode = 0xE8; break;
|
|
||||||
default: OpSize = 5; OpCode = 0xE9; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dwPatchSize < OpSize)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
PatchMemByte((ULONG)pDest, (BYTE)OpCode);
|
|
||||||
|
|
||||||
switch (OpSize)
|
|
||||||
{
|
|
||||||
case 7:
|
|
||||||
PatchMemDword((ULONG)pDest + 1, (ULONG)pCallee);
|
|
||||||
PatchMemWord((ULONG)pDest + 5, 0x23);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
PatchMemDword((ULONG)pDest + 1, (ULONG)pCallee);
|
|
||||||
PatchMemByte((ULONG)pDest + 5, 0xC3);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PatchMemDword((ULONG)pDest + 1, (ULONG)pCallee - (ULONG)pDest - 5);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ULONG i = OpSize; i < dwPatchSize; i++)
|
|
||||||
PatchMemByte((ULONG)pDest + i, 0x90);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
typedef unsigned long long QWORD;
|
|
||||||
typedef QWORD *PQWORD, *LPQWORD;
|
|
||||||
|
|
||||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
|
||||||
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
|
|
||||||
|
|
||||||
#define IJ_JUMP 0 //Insert a jump (0xE9) with InsertJump
|
|
||||||
#define IJ_CALL 1 //Insert a call (0xE8) with InsertJump
|
|
||||||
#define IJ_FARJUMP 2 //Insert a farjump (0xEA) with InsertJump
|
|
||||||
#define IJ_FARCALL 3 //Insert a farcall (0x9A) with InsertJump
|
|
||||||
#define IJ_PUSHRET 4 //Insert a pushret with InsertJump
|
|
||||||
|
|
||||||
BOOL WritePrivateProfileIntA(LPCSTR lpAppName, LPCSTR lpKeyName, int nInteger, LPCSTR lpFileName);
|
|
||||||
LPSTR GetPathUnderModuleA(HMODULE hModule, LPSTR OutBuf, LPCSTR FileName);
|
|
||||||
|
|
||||||
BOOL __stdcall PatchMemData(ULONG dwAddr, ULONG dwBufLen, PVOID pNewData, ULONG dwDataLen);
|
|
||||||
BOOL __stdcall PatchMemQword(ULONG dwAddr, QWORD qNewValue);
|
|
||||||
BOOL __stdcall PatchMemDword(ULONG dwAddr, DWORD dwNewValue);
|
|
||||||
BOOL __stdcall PatchMemWord(ULONG dwAddr, WORD wNewValue);
|
|
||||||
BOOL __stdcall PatchMemByte(ULONG dwAddr, BYTE bNewValue);
|
|
||||||
BOOL __stdcall PatchMemFloat(ULONG dwAddr, FLOAT fNewValue);
|
|
||||||
|
|
||||||
BOOL __stdcall PatchMemNop(ULONG dwAddr, DWORD dwPatchSize);
|
|
||||||
|
|
||||||
BOOL __stdcall InsertJump(PVOID pDest, DWORD dwPatchSize, PVOID pCallee, DWORD dwJumpType = IJ_JUMP);
|
|
Loading…
x
Reference in New Issue
Block a user