Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <stdarg.h>
#include <windows.h>
#include "detours.h"
#include "stub_mm.h"
StubPlugin g_StubPlugin;
HMODULE gSocket_ws2;
HMODULE gSocket_wsock32;
BOOL gbHook = FALSE;
#define A2S_INFO_REPLY "\xFF\xFF\xFF\xFF\x49"
typedef int (WINAPI *sendto_t)(SOCKET, const char* , int, int , const sockaddr*, int);
//origin ws2_32.dll recvfrom callback
sendto_t sendto_ws2;
//origin wsock32.dll recvfrom callback
sendto_t sendto_wsock32;
char* trimbuf(char *str)
{
char *ibuf = str;
int i = 0;
if (str == NULL)
return NULL;
for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf)
;
i = strlen(ibuf);
if (str != ibuf)
memmove(str, ibuf, i);
str[i] = 0;
while (--i >= 0)
{
if (!isspace(ibuf[i]))
break;
}
ibuf[++i] = 0;
return str;
}
void GetGameDir(char *gamedir, size_t maxlen)
{
const char *gamepath = g_SMAPI->GetBaseDir();
size_t len = strlen(gamepath);
for (size_t i = len - 1; i < len; i--)
{
if (gamepath[i] == '\\')
{
strncpy(gamedir, &gamepath[++i], maxlen);
break;
}
}
}
bool IsNewMapName(LPCSTR lpOriginalMapName, LPCH NewName, size_t maxlen)
{
LPCSTR NEWNAME_INI = "NewMapName.ini";
char buf[1024];
char gamedir[256];
char *cl;
char *vl;
int line = 0;
sprintf(buf, "%s", NEWNAME_INI);
FILE *fp = fopen(buf, "r");
if (fp == NULL)
{
GetGameDir(gamedir, sizeof(gamedir));
sprintf(buf, "%s/%s", gamedir, NEWNAME_INI);
fp = fopen(buf, "r");
if (fp == NULL)
{
printf("Could open file \"%s\"\n", NEWNAME_INI);
return false;
}
}
while (fgets(buf, sizeof(buf), fp))
{
if (line++ == 0)
{
if (strlen(buf) > 3 && buf[0] == -17 && buf[1] == -69 && buf[2] == -65)
{
strcpy(buf, &buf[3]);
}
}
cl = trimbuf(buf);
if (strlen(cl) == 0 || cl[0] == ';' || (cl[0] == '/' && cl[1] == '/') )
continue;
vl = strchr(cl, '=');
if (vl == NULL)
continue;
*(vl++) = 0;
cl = trimbuf(cl);
vl = trimbuf(vl);
if (!stricmp(cl, lpOriginalMapName))
{
strncpy(NewName, vl, maxlen);
fclose(fp);
return true;
}
}
fclose(fp);
NewName[0] = '\0';
return false;
}
int GetStr(char *buffer, int &index, char *output, size_t maxlen)
{
int len = 0;
if((len = lstrlen(&buffer[index])) > (int)maxlen)
{
if(lstrcpyn(output, &buffer[index], maxlen) == 0)
{
return FALSE;
}
buffer[index + maxlen] = 0;
}else if(buffer[index]!=0){
if(lstrcpyn(output, &buffer[index], len + 1)==0)
{
return FALSE;
}
}else{
output[0] = 0;
}
index += len + 1;
return len;
}
int WINAPI newsendto_ws2(SOCKET s, const char* buf, int len, int flags, const sockaddr* to, int tolen)
{
if(len > 5)
{
if(memcmp(A2S_INFO_REPLY, buf, 5) == 0)
{
//printf("sendto buffer %s\n", buf);
BYTE packet[1024];
TCHAR *cache, ServerName[256], MapName[32];
cache = (TCHAR*)malloc(len);
int id = 5, stringlen = 0, m_len = 0, ret = 0;
memset(packet, 0, sizeof(packet));
memset(cache, 0, len);
memcpy(cache, buf, len);
GetStr(cache, id, ServerName, sizeof(ServerName));
GetStr(cache, id, MapName, sizeof(MapName));
if (IsNewMapName(MapName, MapName, sizeof(MapName)))
{
*(DWORD*)packet = -1;
packet[4] = 0x49;
m_len = 5;
stringlen = sprintf((char*)&packet[m_len], ServerName);
m_len += stringlen + 1;
stringlen = sprintf((char*)&packet[m_len], MapName);
m_len += stringlen + 1;
memcpy((void*)&packet[m_len], (const void*)&cache[id], len - id + 1);
m_len += (len - id) + 1;
free(cache);
ret = sendto_ws2(s, (const char*)packet, m_len, flags, to, tolen);
return ret;
}
}
}
return sendto_ws2(s, buf, len, flags, to, tolen);
}
int WINAPI newsendto_wsock32(SOCKET s, const char* buf, int len, int flags, const sockaddr* to, int tolen)
{
if(len > 5)
{
if(memcmp(A2S_INFO_REPLY, buf, 5) == 0)
{
//printf("sendto buffer %s\n", buf);
BYTE packet[1024];
TCHAR *cache, ServerName[256], MapName[32];
cache = (TCHAR*)malloc(len);
int id = 5, stringlen = 0, m_len = 0, ret = 0;
memset(packet, 0, sizeof(packet));
memset(cache, 0, len);
memcpy(cache, buf, len);
GetStr(cache, id, ServerName, sizeof(ServerName));
GetStr(cache, id, MapName, sizeof(MapName));
if (IsNewMapName(MapName, MapName, sizeof(MapName)))
{
*(DWORD*)packet = -1;
packet[4] = 0x49;
m_len = 5;
stringlen = sprintf((char*)&packet[m_len], ServerName);
m_len += stringlen + 1;
stringlen = sprintf((char*)&packet[m_len], MapName);
m_len += stringlen + 1;
memcpy((void*)&packet[m_len], (const void*)&cache[id], len - id + 1);
m_len += (len - id) + 1;
free(cache);
ret = sendto_wsock32(s, (const char*)packet, m_len, flags, to, tolen);
return ret;
}
}
}
return sendto_wsock32(s, buf, len, flags, to, tolen);
}
IServerGameDLL *server = NULL;
PLUGIN_EXPOSE(StubPlugin, g_StubPlugin);
bool StubPlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
{
PLUGIN_SAVEVARS();
/* Make sure we build on MM:S 1.4 */
#if defined METAMOD_PLAPI_VERSION
GET_V_IFACE_ANY(GetServerFactory, server, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL);
#else
GET_V_IFACE_ANY(serverFactory, server, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL);
#endif
gSocket_ws2 = LoadLibrary("ws2_32.dll");
gSocket_wsock32 = LoadLibrary("wsock32.dll");
sendto_ws2 = (sendto_t)GetProcAddress(gSocket_ws2,"sendto");
sendto_wsock32 = (sendto_t)GetProcAddress(gSocket_wsock32, "sendto");
if (sendto_ws2)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach((void**)&sendto_ws2,newsendto_ws2);//attach make new jump data
DetourTransactionCommit();
}
if(sendto_wsock32)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach((void**)&sendto_wsock32,newsendto_wsock32); //attach make new jump data
DetourTransactionCommit();
}
gbHook = TRUE;
g_SMAPI->ConPrintf("\n\tServer using \"%s\"(v %s)\n\tCopyright 2012 by \"%s\".\n\tWeibo: \"%s\"\n\n", GetName(), GetVersion(), GetAuthor(), GetURL());
return true;
}
bool StubPlugin::Unload(char *error, size_t maxlen)
{
if(gbHook == TRUE) //check hook mark
{
if(sendto_ws2)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach((void**)&sendto_ws2,newsendto_ws2); //detach hook
DetourTransactionCommit(); //destory new jump data and restore
}
if(sendto_wsock32) //check hook mark
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach((void**)&sendto_wsock32,newsendto_wsock32); //detach hook
DetourTransactionCommit(); //destory new jump data and restore
}
}
return true;
}
void StubPlugin::AllPluginsLoaded()
{
}
bool StubPlugin::Pause(char *error, size_t maxlen)
{
return true;
}
bool StubPlugin::Unpause(char *error, size_t maxlen)
{
return true;
}
const char *StubPlugin::GetLicense()
{
return "Lv<->吕";
}
const char *StubPlugin::GetVersion()
{
return "1.0.0.3";
}
const char *StubPlugin::GetDate()
{
return __DATE__;
}
const char *StubPlugin::GetLogTag()
{
return "MNE";
}
const char *StubPlugin::GetAuthor()
{
return "L.K";
}
const char *StubPlugin::GetDescription()
{
return "Edit the map name at the sendto packet";
}
const char *StubPlugin::GetName()
{
return "Map Name Editor";
}
const char *StubPlugin::GetURL()
{
return "http://weibo.com/kklv";
}