ReGameDLL_CS/regamedll/testsuite/testsuite.cpp
2015-06-30 15:46:07 +06:00

515 lines
17 KiB
C++

#include "precompiled.h"
/* ============================================================================
external function hooks
============================================================================*/
uint32 __cdecl time_hooked(uint32* pTime)
{
return CRegamedllPlatformHolder::get()->time(pTime);
}
struct tm* __cdecl localtime_hooked(uint32* pTime)
{
if (pTime == NULL)
regamedll_syserror("%s: pTime is NULL", __FUNCTION__);
return CRegamedllPlatformHolder::get()->localtime(*pTime);
}
void __cdecl srand_hooked(uint32 seed)
{
CRegamedllPlatformHolder::get()->srand(seed);
}
int __cdecl rand_hooked()
{
return CRegamedllPlatformHolder::get()->rand();
}
void WINAPI Sleep_hooked(DWORD msec)
{
CRegamedllPlatformHolder::get()->Sleep(msec);
}
BOOL WINAPI QueryPerfCounter_hooked(LARGE_INTEGER* counter)
{
return CRegamedllPlatformHolder::get()->QueryPerfCounter(counter);
}
BOOL WINAPI QueryPerfFreq_hooked(LARGE_INTEGER* freq)
{
return CRegamedllPlatformHolder::get()->QueryPerfFreq(freq);
}
DWORD WINAPI GetTickCount_hooked()
{
return CRegamedllPlatformHolder::get()->GetTickCount();
}
void WINAPI GetLocalTime_hooked(LPSYSTEMTIME time)
{
CRegamedllPlatformHolder::get()->GetLocalTime(time);
}
void WINAPI GetSystemTime_hooked(LPSYSTEMTIME time)
{
CRegamedllPlatformHolder::get()->GetSystemTime(time);
}
void WINAPI GetTimeZoneInfo_hooked(LPTIME_ZONE_INFORMATION tzinfo)
{
CRegamedllPlatformHolder::get()->GetTimeZoneInfo(tzinfo);
}
SOCKET __stdcall socket_hooked(int af, int type, int protocol)
{
return CRegamedllPlatformHolder::get()->socket(af, type, protocol);
}
int __stdcall ioctlsocket_hooked(SOCKET s, long cmd, u_long *argp)
{
return CRegamedllPlatformHolder::get()->ioctlsocket(s, cmd, argp);
}
int __stdcall setsockopt_hooked(SOCKET s, int level, int optname, const char* optval, int optlen)
{
return CRegamedllPlatformHolder::get()->setsockopt(s, level, optname, optval, optlen);
}
int __stdcall closesocket_hooked(SOCKET s)
{
return CRegamedllPlatformHolder::get()->closesocket(s);
}
int __stdcall recvfrom_hooked(SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int *fromlen)
{
return CRegamedllPlatformHolder::get()->recvfrom(s, buf, len, flags, from, fromlen);
}
int __stdcall sendto_hooked(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen)
{
return CRegamedllPlatformHolder::get()->sendto(s, buf, len, flags, to, tolen);
}
int __stdcall bind_hooked(SOCKET s, const struct sockaddr* addr, int namelen)
{
return CRegamedllPlatformHolder::get()->bind(s, addr, namelen);
}
int __stdcall getsockname_hooked(SOCKET s, struct sockaddr* name, int* namelen)
{
return CRegamedllPlatformHolder::get()->getsockname(s, name, namelen);
}
int __stdcall WSAGetLastError_hooked()
{
return CRegamedllPlatformHolder::get()->WSAGetLastError();
}
struct hostent* __stdcall gethostbyname_hooked(const char *name)
{
return CRegamedllPlatformHolder::get()->gethostbyname(name);
}
int __stdcall gethostname_hooked(char *name, int namelen)
{
return CRegamedllPlatformHolder::get()->gethostname(name, namelen);
}
void __cdecl SteamAPI_SetMiniDumpComment_hooked(const char *pchMsg)
{
regamedll_syserror("%s: not implemented", __FUNCTION__);
}
void __cdecl SteamAPI_WriteMiniDump_hooked(uint32 uStructuredExceptionCode, void* pvExceptionInfo, uint32 uBuildID)
{
regamedll_syserror("%s: not implemented", __FUNCTION__);
}
void __cdecl SteamAPI_RegisterCallback_hooked(class CCallbackBase *pCallback, int iCallback)
{
return CRegamedllPlatformHolder::get()->SteamAPI_RegisterCallback(pCallback, iCallback);
}
void __cdecl SteamAPI_RunCallbacks_hooked()
{
CRegamedllPlatformHolder::get()->SteamAPI_RunCallbacks();
}
bool __cdecl SteamAPI_Init_hooked()
{
return CRegamedllPlatformHolder::get()->SteamAPI_Init();
}
ISteamUser* __cdecl SteamUser_hooked()
{
regamedll_syserror("%s: not implemented", __FUNCTION__);
return NULL;
}
ISteamFriends* __cdecl SteamFriends_hooked()
{
regamedll_syserror("%s: not implemented", __FUNCTION__);
return NULL;
}
void __cdecl SteamGameServer_RunCallbacks_hooked()
{
CRegamedllPlatformHolder::get()->SteamGameServer_RunCallbacks();
}
void __cdecl SteamAPI_Shutdown_hooked()
{
regamedll_syserror("%s: not implemented", __FUNCTION__);
}
void __cdecl SteamGameServer_Shutdown_hooked()
{
CRegamedllPlatformHolder::get()->SteamGameServer_Shutdown();
}
bool __cdecl SteamGameServer_Init_hooked(uint32 unIP, uint16 usSteamPort, uint16 usGamePort, uint16 usQueryPort, EServerMode eServerMode, const char *pchVersionString)
{
return CRegamedllPlatformHolder::get()->SteamGameServer_Init(unIP, usSteamPort, usGamePort, usQueryPort, eServerMode, pchVersionString);
}
void __cdecl SteamAPI_UnregisterCallback_hooked(class CCallbackBase *pCallback)
{
CRegamedllPlatformHolder::get()->SteamAPI_UnregisterCallback(pCallback);
}
ISteamGameServer* __cdecl SteamGameServer_hooked()
{
return CRegamedllPlatformHolder::get()->SteamGameServer();
}
void __cdecl SteamAPI_SetBreakpadAppID_hooked(uint32 unAppID)
{
CRegamedllPlatformHolder::get()->SteamAPI_SetBreakpadAppID(unAppID);
}
void __cdecl SteamAPI_RegisterCallResult_hooked(class CCallbackBase *pCallback, SteamAPICall_t hAPICall)
{
regamedll_syserror("%s: not implemented", __FUNCTION__);
}
ISteamHTTP* __cdecl SteamHTTP_hooked()
{
regamedll_syserror("%s: not implemented", __FUNCTION__);
return NULL;
}
void __cdecl SteamAPI_UnregisterCallResult_hooked(class CCallbackBase *pCallback, SteamAPICall_t hAPICall)
{
CRegamedllPlatformHolder::get()->SteamAPI_UnregisterCallResult(pCallback, hAPICall);
}
ISteamApps* __cdecl SteamApps_hooked()
{
return CRegamedllPlatformHolder::get()->SteamApps();
}
void __cdecl SteamAPI_UseBreakpadCrashHandler_hooked(char const *pchVersion, char const *pchDate, char const *pchTime, bool bFullMemoryDumps, void *pvContext, PFNPreMinidumpCallback m_pfnPreMinidumpCallback)
{
CRegamedllPlatformHolder::get()->SteamAPI_UseBreakpadCrashHandler(pchVersion, pchDate, pchTime, bFullMemoryDumps, pvContext, m_pfnPreMinidumpCallback);
}
/* ============================================================================
Hooks installation
============================================================================*/
HMODULE getModuleHandleOrDie(const char* moduleName) {
HMODULE res = GetModuleHandleA(moduleName);
if (res == NULL) {
regamedll_syserror("getModuleHandleOrDie(): module not found: '%s'", moduleName);
}
return res;
}
void* getProcAddressOrDie(HMODULE hModule, const char* procName) {
void* res = GetProcAddress(hModule, procName);
if (res == NULL) {
regamedll_syserror("getProcAddressOrDie(): procedure not found: '%s'", procName);
}
return res;
}
void InstallImportTableHook(PIMAGE_THUNK_DATA thunk, void* func)
{
DWORD oldProtect;
VirtualProtect(thunk, 4, PAGE_READWRITE, &oldProtect);
thunk->u1.Function = (DWORD)func;
}
void TestSuite_InstallHooks(const Module* engine) {
HMODULE hKernel32 = getModuleHandleOrDie("kernel32.dll");
HMODULE hWinSock32 = getModuleHandleOrDie("wsock32.dll");
HMODULE hSteamApi = getModuleHandleOrDie("steam_api.dll");
void* QueryPerfCounter_addr = getProcAddressOrDie(hKernel32, "QueryPerformanceCounter");
void* QueryPerfFreq_addr = getProcAddressOrDie(hKernel32, "QueryPerformanceFrequency");
void* Sleep_addr = getProcAddressOrDie(hKernel32, "Sleep");
void* GetTickCount_addr = getProcAddressOrDie(hKernel32, "GetTickCount");
void* GetLocalTime_addr = getProcAddressOrDie(hKernel32, "GetLocalTime");
void* GetSystemTime_addr = getProcAddressOrDie(hKernel32, "GetSystemTime");
void* GetTimeZoneInformation_addr = getProcAddressOrDie(hKernel32, "GetTimeZoneInformation");
void* socket_addr = getProcAddressOrDie(hWinSock32, "socket");
void* ioctlsocket_addr = getProcAddressOrDie(hWinSock32, "ioctlsocket");
void* setsockopt_addr = getProcAddressOrDie(hWinSock32, "setsockopt");
void* closesocket_addr = getProcAddressOrDie(hWinSock32, "closesocket");
void* recvfrom_addr = getProcAddressOrDie(hWinSock32, "recvfrom");
void* sendto_addr = getProcAddressOrDie(hWinSock32, "sendto");
void* bind_addr = getProcAddressOrDie(hWinSock32, "bind");
void* getsockname_addr = getProcAddressOrDie(hWinSock32, "getsockname");
void* gethostname_addr = getProcAddressOrDie(hWinSock32, "gethostname");
void* gethostbyname_addr = getProcAddressOrDie(hWinSock32, "gethostbyname");
void* WSAGetLastError_addr = getProcAddressOrDie(hWinSock32, "WSAGetLastError");
void* SteamAPI_SetMiniDumpComment_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_SetMiniDumpComment");
void* SteamAPI_WriteMiniDump_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_WriteMiniDump");
void* SteamAPI_RegisterCallback_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_RegisterCallback");
void* SteamAPI_RunCallbacks_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_RunCallbacks");
void* SteamAPI_Init_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_Init");
void* SteamUser_addr = getProcAddressOrDie(hSteamApi, "SteamUser");
void* SteamFriends_addr = getProcAddressOrDie(hSteamApi, "SteamFriends");
void* SteamGameServer_RunCallbacks_addr = getProcAddressOrDie(hSteamApi, "SteamGameServer_RunCallbacks");
void* SteamAPI_Shutdown_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_Shutdown");
void* SteamGameServer_Shutdown_addr = getProcAddressOrDie(hSteamApi, "SteamGameServer_Shutdown");
void* SteamGameServer_Init_addr = getProcAddressOrDie(hSteamApi, "SteamGameServer_Init");
void* SteamAPI_UnregisterCallback_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_UnregisterCallback");
void* SteamGameServer_addr = getProcAddressOrDie(hSteamApi, "SteamGameServer");
void* SteamAPI_SetBreakpadAppID_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_SetBreakpadAppID");
void* SteamAPI_RegisterCallResult_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_RegisterCallResult");
void* SteamHTTP_addr = getProcAddressOrDie(hSteamApi, "SteamHTTP");
void* SteamAPI_UnregisterCallResult_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_UnregisterCallResult");
void* SteamApps_addr = getProcAddressOrDie(hSteamApi, "SteamApps");
void* SteamAPI_UseBreakpadCrashHandler_addr = getProcAddressOrDie(hSteamApi, "SteamAPI_UseBreakpadCrashHandler");
PIMAGE_DOS_HEADER peHeader = (PIMAGE_DOS_HEADER)engine->base;
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)(engine->base + peHeader->e_lfanew);
PIMAGE_IMPORT_DESCRIPTOR impDesc = (PIMAGE_IMPORT_DESCRIPTOR)(ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + engine->base);
for (; impDesc->Name; impDesc++)
{
const char* libName = (const char*)(engine->base + impDesc->Name);
bool isKernel32 = !_stricmp("kernel32.dll", libName);
bool isWSock32 = !_stricmp("wsock32.dll", libName);
bool isSteamApi = !_stricmp("steam_api.dll", libName);
PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)(engine->base + impDesc->FirstThunk);
for (; thunk->u1.Function; ++thunk)
{
void* fptr = (void**)(thunk->u1.Function);
if (isKernel32)
{
if (fptr == Sleep_addr)
{
InstallImportTableHook(thunk, &Sleep_hooked);
}
else if (fptr == QueryPerfCounter_addr)
{
InstallImportTableHook(thunk, &QueryPerfCounter_hooked);
}
else if (fptr == QueryPerfFreq_addr)
{
InstallImportTableHook(thunk, &QueryPerfFreq_hooked);
}
else if (fptr == GetTickCount_addr)
{
InstallImportTableHook(thunk, &GetTickCount_hooked);
}
else if (fptr == GetLocalTime_addr)
{
InstallImportTableHook(thunk, &GetLocalTime_hooked);
}
else if (fptr == GetSystemTime_addr)
{
InstallImportTableHook(thunk, &GetSystemTime_hooked);
}
else if (fptr == GetTimeZoneInformation_addr)
{
InstallImportTableHook(thunk, &GetTimeZoneInfo_hooked);
}
}
else if (isWSock32)
{
if (fptr == socket_addr)
{
InstallImportTableHook(thunk, &socket_hooked);
}
else if (fptr == ioctlsocket_addr) {
InstallImportTableHook(thunk, &ioctlsocket_hooked);
}
else if (fptr == setsockopt_addr) {
InstallImportTableHook(thunk, &setsockopt_hooked);
}
else if (fptr == closesocket_addr) {
InstallImportTableHook(thunk, &closesocket_hooked);
}
else if (fptr == recvfrom_addr) {
InstallImportTableHook(thunk, &recvfrom_hooked);
}
else if (fptr == sendto_addr) {
InstallImportTableHook(thunk, &sendto_hooked);
}
else if (fptr == bind_addr) {
InstallImportTableHook(thunk, &bind_hooked);
}
else if (fptr == getsockname_addr) {
InstallImportTableHook(thunk, &getsockname_hooked);
}
else if (fptr == WSAGetLastError_addr) {
InstallImportTableHook(thunk, &WSAGetLastError_hooked);
}
else if (fptr == gethostbyname_addr) {
InstallImportTableHook(thunk, &gethostbyname_hooked);
}
else if (fptr == gethostname_addr) {
InstallImportTableHook(thunk, &gethostname_hooked);
}
}
else if (isSteamApi)
{
if (fptr == SteamAPI_SetMiniDumpComment_addr)
{
InstallImportTableHook(thunk, &SteamAPI_SetMiniDumpComment_hooked);
}
else if (fptr == SteamAPI_WriteMiniDump_addr)
{
InstallImportTableHook(thunk, &SteamAPI_WriteMiniDump_hooked);
}
else if (fptr == SteamAPI_RegisterCallback_addr)
{
InstallImportTableHook(thunk, &SteamAPI_RegisterCallback_hooked);
}
else if (fptr == SteamAPI_RunCallbacks_addr)
{
InstallImportTableHook(thunk, &SteamAPI_RunCallbacks_hooked);
}
else if (fptr == SteamAPI_Init_addr)
{
InstallImportTableHook(thunk, &SteamAPI_Init_hooked);
}
else if (fptr == SteamUser_addr)
{
InstallImportTableHook(thunk, &SteamUser_hooked);
}
else if (fptr == SteamFriends_addr)
{
InstallImportTableHook(thunk, &SteamFriends_hooked);
}
else if (fptr == SteamGameServer_RunCallbacks_addr)
{
InstallImportTableHook(thunk, &SteamGameServer_RunCallbacks_hooked);
}
else if (fptr == SteamAPI_Shutdown_addr)
{
InstallImportTableHook(thunk, &SteamAPI_Shutdown_hooked);
}
else if (fptr == SteamGameServer_Shutdown_addr)
{
InstallImportTableHook(thunk, &SteamGameServer_Shutdown_hooked);
}
else if (fptr == SteamGameServer_Init_addr)
{
InstallImportTableHook(thunk, &SteamGameServer_Init_hooked);
}
else if (fptr == SteamAPI_UnregisterCallback_addr)
{
InstallImportTableHook(thunk, &SteamAPI_UnregisterCallback_hooked);
}
else if (fptr == SteamGameServer_addr)
{
InstallImportTableHook(thunk, &SteamGameServer_hooked);
}
else if (fptr == SteamAPI_SetBreakpadAppID_addr)
{
InstallImportTableHook(thunk, &SteamAPI_SetBreakpadAppID_hooked);
}
else if (fptr == SteamAPI_RegisterCallResult_addr)
{
InstallImportTableHook(thunk, &SteamAPI_RegisterCallResult_hooked);
}
else if (fptr == SteamHTTP_addr)
{
InstallImportTableHook(thunk, &SteamHTTP_hooked);
}
else if (fptr == SteamAPI_UnregisterCallResult_addr)
{
InstallImportTableHook(thunk, &SteamAPI_UnregisterCallResult_hooked);
}
else if (fptr == SteamApps_addr)
{
InstallImportTableHook(thunk, &SteamApps_hooked);
}
else if (fptr == SteamAPI_UseBreakpadCrashHandler_addr)
{
InstallImportTableHook(thunk, &SteamAPI_UseBreakpadCrashHandler_hooked);
}
}
}
}
}
void TestSuite_InstallCStdHooks(const AddressRef* funcRefs) {
const AddressRef* curFunc = funcRefs;
FunctionHook fhook;
while (curFunc->symbolName)
{
if (!strcmp("time", curFunc->symbolName)) {
fhook.originalAddress = curFunc->originalAddress;
fhook.handlerFunc = (size_t) &time_hooked;
HookFunction(NULL, &fhook);
}
else if (!strcmp("localtime", curFunc->symbolName)) {
fhook.originalAddress = curFunc->originalAddress;
fhook.handlerFunc = (size_t)&localtime_hooked;
HookFunction(NULL, &fhook);
}
else if (!strcmp("srand", curFunc->symbolName)) {
fhook.originalAddress = curFunc->originalAddress;
fhook.handlerFunc = (size_t)&srand_hooked;
HookFunction(NULL, &fhook);
}
else if (!strcmp("rand", curFunc->symbolName)) {
fhook.originalAddress = curFunc->originalAddress;
fhook.handlerFunc = (size_t)&rand_hooked;
HookFunction(NULL, &fhook);
}
curFunc++;
}
}
void TestSuite_Init(const Module* engine, const Module* executable, const AddressRef* funcRefs) {
bool needInstallImportTableHooks = false;
if (g_ReGameDLLRuntimeConfig.testPlayerMode == TPM_RECORD)
{
CRegamedllPlatformHolder::set(new CRecordingEngExtInterceptor(g_ReGameDLLRuntimeConfig.testRecordingFileName, CRegamedllPlatformHolder::get()));
needInstallImportTableHooks = true;
}
else if (g_ReGameDLLRuntimeConfig.testPlayerMode == TPM_PLAY)
{
CRegamedllPlatformHolder::set(new CPlayingEngExtInterceptor(g_ReGameDLLRuntimeConfig.testRecordingFileName, true));
needInstallImportTableHooks = true;
}
if (needInstallImportTableHooks) {
if (engine != NULL) {
TestSuite_InstallHooks(engine);
}
TestSuite_InstallHooks(executable);
if (funcRefs != NULL) {
TestSuite_InstallCStdHooks(funcRefs);
}
}
}