#include "appWeb.h" #include "pch.h"
void encodeURL( char * url,char * token) {
url = url + strlen(url) ;
char* tokenEnd = ( token + strlen(token)); for( ; token < tokenEnd ;)
{
if ( ((*token >= 'a') && (*token <= 'z'))
| ((*token >= 'A') && (*token <= 'Z'))
| ((*token >= '0') && (*token <= '9'))
)
{
*(url++) = *(token++) ; }
else {
*(url++) = '%' ; *(url++) = (( *token / 16 ) < 10) ? ( *token / 16) + '0' : ( *token /16 ) + ('a'-10) ;
*(url++) = (( *token & 0x0F ) < 10) ? ( *(token++) & 0x0F ) + '0' : ( *(token++) & 0x0F ) + ('a'-10) ;
}
}
*url = 0 ; }
BOOLEAN getASGS(char * strName,char* playerIP,char* ASGS_Token)
{
DWORD dw; HKEY hk;
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, HKLM_FedSrv, 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hk, &dw) == ERROR_SUCCESS)
{
DWORD dwASGS_ON=0;
bool bSuccess = _Module.ReadFromRegistry(hk, false, "ASGS_ON", &dwASGS_ON, 0);
RegCloseKey(hk);
if (!(bSuccess && dwASGS_ON)) return true ; }
MaClient *http_client;
int contentLen; char *szContent; char szResponse[255]; ZString strContent ;
char szURL[2000];
Strcpy(szURL,"http://asgs.alleg.net/asgs/services.asmx/AuthenticateTicket?Callsign=");
encodeURL(szURL,strName); strcat(szURL,"&IP=");
encodeURL(szURL,playerIP) ; strcat(szURL,"&Ticket=");
encodeURL(szURL,ASGS_Token) ;
Mpr mpr("AllSrv");
mpr.start(MPR_SERVICE_THREAD);
http_client = new MaClient();
http_client->getRequest(szURL);
if (szContent = http_client->getResponseContent(&contentLen))
{
strContent = szContent;
mpr.stop(0);
delete http_client;
if ( strContent.ReverseFind("<int xmlns=\"http://ASGS.Alleg.net/ASGS/ASGS\">-1</int>" ) > -1 )
{
debugf("ASGS player was not validated!\n");
debugf("sent asgs %s \n",szURL); debugf(" And asgs sent: %s\n", (PCC)strContent);
return false ;
}
else
{
return true ;
}
} else
{
debugf("ASGS Server did not respond!\n");
return true ; }
}
const DWORD CFLClient::c_dwID = 19680815;
#ifndef NO_MSG_CRC
bool g_fLogonCRC = true;
#endif
static DWORD GetRegDWORD(const char* szKey, DWORD dwDefault)
{
DWORD dwResult = dwDefault;
HKEY hk;
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, HKLM_AllLobby, 0, "",
REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hk, NULL) == ERROR_SUCCESS)
{
_Module.ReadFromRegistry(hk, false, szKey, &dwResult, dwDefault);
}
return dwResult;
}
void QueueMissions(FedMessaging * pfm)
{
bool fIsFreeLobby = g_pLobbyApp->EnforceCDKey();
ListConnections::Iterator iterCnxn(*g_pLobbyApp->GetFMServers().GetConnections());
while (!iterCnxn.End())
{
CFLServer * pServerT = CFLServer::FromConnection(*iterCnxn.Value());
if (!pServerT->GetPaused())
{
MissionList::Iterator iterMissions(*pServerT->GetMissions());
while (!iterMissions.End())
{
FMD_LS_LOBBYMISSIONINFO * plmi = iterMissions.Value()->GetMissionInfo();
if (plmi && (fIsFreeLobby || plmi->nNumPlayers > 0 || plmi->fMSArena
|| (!fIsFreeLobby && strcmp(FM_VAR_REF(plmi,szIGCStaticFile),"zone_core")))) pfm->QueueExistingMsg(plmi);
iterMissions.Next();
}
}
iterCnxn.Next();
}
}
#ifdef USECLUB
void GotLogonInfo(CQLobbyLogon * pquery)
{
FedMessaging & fm = g_pLobbyApp->GetFMClients();
CQLobbyLogonData * pqd = pquery->GetData();
char * szReason = pqd->szReason;
CFMConnection * pcnxn = fm.GetConnectionFromId(pqd->dwConnectionID);
if (!pcnxn)
return; if (g_pLobbyApp->EnforceCDKey() && pqd->fValid && !pqd->fValidCode)
{
pqd->fValid = false;
pqd->fRetry = true;
szReason = "The CD Key you entered is not valid. Please "
"press <CD Key> and re-enter the CD Key from "
"the back of your CD case.";
}
if (pqd->fValid)
{
fm.SetDefaultRecipient(pcnxn, FM_GUARANTEED);
BEGIN_PFM_CREATE(fm, pfmLogonAck, L, LOGON_ACK)
END_PFM_CREATE
pfmLogonAck->dwTimeOffset = pqd->dTime;
int cRows;
CQLobbyLogonData * pRows = pquery->GetOutputRows(&cRows); SquadMembership* pargSquads = new SquadMembership[cRows];
for (int iSquad = 0; iSquad < cRows; iSquad++)
{
Strcpy(pargSquads[iSquad].m_szSquadName, pRows->szSquadName);
pargSquads[iSquad].m_squadID = pRows->squadID;
pargSquads[iSquad].m_fIsLeader = 0 == pRows->status;
pargSquads[iSquad].m_fIsAssistantLeader = 1 == pRows->status && 1 == pRows->detailedStatus;
}
BEGIN_PFM_CREATE(fm, pfmSquadMemberships, LS, SQUAD_MEMBERSHIPS)
FM_VAR_PARM(cRows ? pargSquads : NULL, sizeof(SquadMembership) * cRows)
END_PFM_CREATE
pfmSquadMemberships->cSquadMemberships = cRows;
delete [] pargSquads;
QueueMissions(&fm);
}
if (!pqd->fValid)
{
BEGIN_PFM_CREATE(fm, pfmLogonNack, L, LOGON_NACK)
FM_VAR_PARM(szReason, CB_ZTS)
END_PFM_CREATE
pfmLogonNack->fRetry = pqd->fRetry;
}
g_pLobbyApp->GetFMClients().SendMessages(pcnxn, FM_GUARANTEED, FM_FLUSH);
}
#endif
const int c_cMaxPlayers = GetRegDWORD("MaxPlayersPerServer", 350);
HRESULT LobbyClientSite::OnAppMessage(FedMessaging * pthis, CFMConnection & cnxnFrom, FEDMESSAGE * pfm)
{
CFLClient * pClient = CFLClient::FromConnection(cnxnFrom);
assert(pClient);
debugf("Client: %s from <%s> at time %u\n", g_rgszMsgNames[pfm->fmid], cnxnFrom.GetName(), Time::Now());
switch (pfm->fmid)
{
case FM_C_LOGON_LOBBY_OLD:
{
#ifndef NO_MSG_CRC
bool fCRC = g_fLogonCRC;
g_fLogonCRC = true; #endif
CASTPFM(pfmLogon, C, LOGON_LOBBY_OLD, pfm);
if (g_pAutoUpdate && pfmLogon->crcFileList != g_pAutoUpdate->GetFileListCRC())
{
BEGIN_PFM_CREATE(*pthis, pfmAutoUpdate, L, AUTO_UPDATE_INFO)
FM_VAR_PARM(g_pAutoUpdate->GetFTPServer(), CB_ZTS)
FM_VAR_PARM(g_pAutoUpdate->GetFTPInitialDir(), CB_ZTS)
FM_VAR_PARM(g_pAutoUpdate->GetFTPAccount(), CB_ZTS)
FM_VAR_PARM(g_pAutoUpdate->GetFTPPassword(), CB_ZTS)
END_PFM_CREATE
pfmAutoUpdate->crcFileList = g_pAutoUpdate->GetFileListCRC();
pfmAutoUpdate->nFileListSize = g_pAutoUpdate->GetFileListSize();
}
else
{
char * szReason = "Your game's version did not get auto-updated properly. Please try again later.";
BEGIN_PFM_CREATE(*pthis, pfmLogonNack, L, LOGON_NACK)
FM_VAR_PARM((char *)szReason, CB_ZTS)
END_PFM_CREATE
pfmLogonNack->fRetry = false;
}
#ifndef NO_MSG_CRC
if (!fCRC)
*(CB*)(pthis->BuffOut()) += sizeof(int);
#endif
pthis->SendMessages(&cnxnFrom, FM_GUARANTEED, FM_FLUSH);
}
break;
case FM_C_LOGON_LOBBY:
{
CASTPFM(pfmLogon, C, LOGON_LOBBY, pfm);
bool fValid = false; bool fRetry = false;
char * szReason = NULL; #ifdef USEAUTH
LPBYTE pZoneTicket = (LPBYTE) FM_VAR_REF(pfmLogon, ZoneTicket);
TRef<IZoneAuthServer> pzas = g_pLobbyApp->GetZoneAuthServer();
#ifdef USECLUB
CQLobbyLogon * pquery = new CQLobbyLogon(GotLogonInfo);
CQLobbyLogonData * pqd = pquery->GetData();
pqd->dTime = pfmLogon->dwTime - Time::Now().clock();
Strcpy(pqd->szCharacterName, cnxnFrom.GetName()); pqd->characterID = 0;
strcpy(pqd->szCDKey,""); #endif
if (pzas) {
if (pZoneTicket)
{
HRESULT hr = pzas->DecryptTicket(pZoneTicket, pfmLogon->cbZoneTicket);
switch (hr)
{
case ZT_NO_ERROR:
{
bool fValidNow = false;
#ifdef USECLUB
Strcpy(pqd->szCharacterName, pzas->GetName());
pqd->characterID = pzas->GetAccountID();
#endif fValid = pzas->HasToken(g_pLobbyApp->GetToken(), &fValidNow);
if (!(fValid && fValidNow))
{
fRetry = true;
const char szNoAuth[] = "Your authentication has failed. Please try again.";
const DWORD cbReason = sizeof(szNoAuth); szReason = (char*)_alloca(cbReason);
_snprintf(szReason, cbReason, szNoAuth);
fValid = false;
}
#ifdef USECLUB else if (g_pLobbyApp->EnforceCDKey())
{
const char * szEncryptedCDKey = (const char*) FM_VAR_REF(pfmLogon, CDKey);
const char * szName = pzas->GetName();
if (!szEncryptedCDKey || szEncryptedCDKey[pfmLogon->cbCDKey - 1] != '\0')
szEncryptedCDKey = "";
char * szDecryptionKey = (char *)_alloca(strlen(CL_LOGON_KEY) + 12 + c_cbName);
wsprintf(szDecryptionKey, CL_LOGON_KEY, pfmLogon->dwTime, szName);
ZUnscramble(pqd->szCDKey, szEncryptedCDKey, szDecryptionKey);
ZString strOldPlayer;
if (g_pLobbyApp->BootPlayersByCDKey(pqd->szCDKey, szName, strOldPlayer))
{
fValid = false;
fRetry = true;
const char szDuplicateCDKey[] = "%s was logged on with your CD Key!";
const DWORD cbReason = 25 + sizeof(szDuplicateCDKey); szReason = (char*)_alloca(cbReason);
_snprintf(szReason, cbReason, szDuplicateCDKey, (PCC)strOldPlayer);
}
}
#endif break;
}
case ZT_E_BUFFER_TOO_SMALL:
g_pLobbyApp->GetSite()->LogEvent(EVENTLOG_WARNING_TYPE, LE_MoreTokens);
break;
case ZT_E_AUTH_INVALID_TICKET:
{
char szRemoteAddress[16];
HRESULT hr = pthis->GetIPAddress(cnxnFrom, szRemoteAddress);
g_pLobbyApp->GetSite()->LogEvent(EVENTLOG_WARNING_TYPE, LE_BadZTicket,
SUCCEEDED(hr) ? szRemoteAddress : "unknown");
szReason = "Could not validate Zone ID.";
break;
}
default:
g_pLobbyApp->GetSite()->LogEvent(EVENTLOG_ERROR_TYPE, LE_DecryptTicketFailure, hr);
}
}
else
{
char szRemoteAddress[16];
HRESULT hr = pthis->GetIPAddress(cnxnFrom, szRemoteAddress);
g_pLobbyApp->GetSite()->LogEvent(EVENTLOG_WARNING_TYPE, LE_NoCredentials,
SUCCEEDED(hr) ? szRemoteAddress : "unknown");
szReason = "No login credentials provided. This is the zone lobby which requires secure logins. Perhaps you are looking for the Internet Lobby.";
}
}
else
#endif fValid = true; if (fValid) {
char szPlayerIP[16];
HRESULT hr = pthis->GetIPAddress(cnxnFrom,szPlayerIP);
char * szASGS = (char*) FM_VAR_REF(pfmLogon, ASGS_Ticket);
if (!szASGS || szASGS[pfmLogon->cbASGS_Ticket - 1] != '\0') szASGS = "";
if ( !getASGS(pfmLogon->szName,szPlayerIP,szASGS) ) {
fValid = false;
szReason = "ASGS Authentication Failure.\n\n Please restart the game using ASGS\n" ;
}
}
if (g_pAutoUpdate && pfmLogon->crcFileList != g_pAutoUpdate->GetFileListCRC())
{
BEGIN_PFM_CREATE(*pthis, pfmAutoUpdate, L, AUTO_UPDATE_INFO)
FM_VAR_PARM(g_pAutoUpdate->GetFTPServer(), CB_ZTS)
FM_VAR_PARM(g_pAutoUpdate->GetFTPInitialDir(), CB_ZTS)
FM_VAR_PARM(g_pAutoUpdate->GetFTPAccount(), CB_ZTS)
FM_VAR_PARM(g_pAutoUpdate->GetFTPPassword(), CB_ZTS)
END_PFM_CREATE
pfmAutoUpdate->crcFileList = g_pAutoUpdate->GetFileListCRC();
pfmAutoUpdate->nFileListSize = g_pAutoUpdate->GetFileListSize();
pthis->SendMessages(&cnxnFrom, FM_GUARANTEED, FM_FLUSH);
#ifdef USECLUB
delete pquery;
#endif break; }
if (fValid)
{
if(pfmLogon->verLobby != LOBBYVER)
{
fValid = false;
szReason = "Your game's version did not get auto-updated properly. Please try again later.";
}
}
#ifdef USECLUB
pqd->fValid = fValid;
pqd->fRetry = fRetry;
pqd->szReason = new char[lstrlen(szReason) + 1];
Strcpy(pqd->szReason, szReason);
pqd->dwConnectionID = cnxnFrom.GetID();
if (fValid)
g_pLobbyApp->GetSQL().PostQuery(pquery);
else
pquery->DataReady();
#else
pthis->SetDefaultRecipient(&cnxnFrom, FM_GUARANTEED);
if (fValid)
{
BEGIN_PFM_CREATE(*pthis, pfmLogonAck, L, LOGON_ACK)
END_PFM_CREATE
pfmLogonAck->dwTimeOffset = pfmLogon->dwTime - Time::Now().clock();
QueueMissions(pthis);
}
else {
BEGIN_PFM_CREATE(*pthis, pfmLogonNack, L, LOGON_NACK)
FM_VAR_PARM(szReason, CB_ZTS)
END_PFM_CREATE
pfmLogonNack->fRetry = false;
} g_pLobbyApp->GetFMClients().SendMessages(&cnxnFrom, FM_GUARANTEED, FM_FLUSH);
#endif
}
break;
case FM_C_LOGOFF_LOBBY:
{
}
break;
case FM_C_GET_SERVERS_REQ:
{
ListConnections::Iterator iterCnxn(*g_pLobbyApp->GetFMServers().GetConnections());
int cServers = 20; ServerCoreInfo* pSCI = new ServerCoreInfo[cServers];
int i=0;
while (!iterCnxn.End())
{
CFLServer * pServerT = CFLServer::FromConnection(*iterCnxn.Value());
if (pServerT)
{
if (!pServerT->GetPaused() && (pServerT->GetStaticCoreMask() != 0)) {
strcpy_s(pSCI[i].szName,sizeof(pSCI[i].szName),iterCnxn.Value()->GetName());
g_pLobbyApp->GetFMServers().GetIPAddress(*iterCnxn.Value(), pSCI[i].szRemoteAddress);
strcpy_s(pSCI[i].szLocation,sizeof(pSCI[i].szLocation),pServerT->GetLocation());
pSCI[i].iCurGames = pServerT->GetCurrentGamesCount();
pSCI[i].iMaxGames = pServerT->GetMaxGamesAllowed();
pSCI[i].dwCoreMask = pServerT->GetStaticCoreMask();
i++;
}
}
iterCnxn.Next();
if (i>cServers) break; }
cServers = i;
BEGIN_PFM_CREATE(*pthis, pfmServerList, L, SERVERS_LIST)
FM_VAR_PARM(g_pLobbyApp->GetcStaticCoreInfo() ? g_pLobbyApp->GetvStaticCoreInfo() : NULL, g_pLobbyApp->GetcStaticCoreInfo() * sizeof(StaticCoreInfo))
FM_VAR_PARM(cServers ? pSCI : NULL,cServers*sizeof(ServerCoreInfo))
END_PFM_CREATE
pfmServerList->cCores = g_pLobbyApp->GetcStaticCoreInfo();
pfmServerList->cServers = cServers;
pthis->SendMessages(&cnxnFrom, FM_GUARANTEED, FM_FLUSH);
delete [] pSCI;
pSCI = NULL;
}
break;
case FM_C_CREATE_MISSION_REQ:
{
CASTPFM(pfmCreateMissionReq, C, CREATE_MISSION_REQ, pfm);
const char* szServer = FM_VAR_REF(pfmCreateMissionReq, Server);
const char* szAddr = FM_VAR_REF(pfmCreateMissionReq, Address);
const char* szIGCStaticFile = FM_VAR_REF(pfmCreateMissionReq, IGCStaticFile);
const char* szGameName = FM_VAR_REF(pfmCreateMissionReq, GameName);
CFLServer * pServerMin = NULL;
debugf("Received mission creation request from %s - create %s with %s on %s\n",
cnxnFrom.GetName(),
szGameName,
szIGCStaticFile,
szServer);
ListConnections::Iterator iterCnxn(*g_pLobbyApp->GetFMServers().GetConnections());
while (!iterCnxn.End())
{
CFLServer * pServerT = CFLServer::FromConnection(*iterCnxn.Value());
if (pServerT) {
if (!pServerT->GetPaused()) {
char szRemoteAddress[16];
g_pLobbyApp->GetFMServers().GetIPAddress(*iterCnxn.Value(), szRemoteAddress);
if (strcmp(szRemoteAddress,szAddr)==0) {
if (strcmp(iterCnxn.Value()->GetName(),szServer)==0) {
pServerMin = pServerT; break;
}
}
}
}
iterCnxn.Next();
}
if (pServerMin)
{
CFLMission * pMission = pServerMin->CreateMission(pClient);
BEGIN_PFM_CREATE(g_pLobbyApp->GetFMServers(), pfmNewMissionReq, L, CREATE_MISSION_REQ)
FM_VAR_PARM(szGameName, CB_ZTS) FM_VAR_PARM(szIGCStaticFile, CB_ZTS) END_PFM_CREATE
pfmNewMissionReq->dwCookie = pMission->GetCookie();
BEGIN_PFM_CREATE(*pthis, pfmCreateMissionAck, L, CREATE_MISSION_ACK)
END_PFM_CREATE
pfmCreateMissionAck->dwCookie = pfmNewMissionReq->dwCookie;
g_pLobbyApp->GetFMServers().SendMessages(pServerMin->GetConnection(), FM_GUARANTEED, FM_FLUSH);
}
else
{
debugf("Server not found to create the game on\n");
BEGIN_PFM_CREATE(*pthis, pfmCreateMissionNack, L, CREATE_MISSION_NACK)
END_PFM_CREATE
}
pthis->SendMessages(&cnxnFrom, FM_GUARANTEED, FM_FLUSH);
}
break;
case FM_C_JOIN_GAME_REQ:
{
CASTPFM(pfmJoinGameReq, C, JOIN_GAME_REQ, pfm);
CFLMission * pMission = CFLMission::FromCookie(pfmJoinGameReq->dwCookie);
if (pMission && pMission->GetServer()->GetPlayerCount() < c_cMaxPlayers)
{
BEGIN_PFM_CREATE(*pthis, pfmJoinMission, L, JOIN_MISSION)
END_PFM_CREATE
char szServer[16];
g_pLobbyApp->GetFMServers().GetIPAddress(*pMission->GetServer()->GetConnection(), szServer);
assert(lstrlen(szServer) < sizeof(pfmJoinMission->szServer)); lstrcpy(pfmJoinMission->szServer, szServer);
pfmJoinMission->dwPort = pMission->GetServer()->GetServerPort(); pfmJoinMission->dwCookie = pfmJoinGameReq->dwCookie;
pfmJoinMission->guidInstance = GUID_NULL; }
else
{
BEGIN_PFM_CREATE(*pthis, pfmJoingameNack, L, JOIN_GAME_NACK)
END_PFM_CREATE
}
pthis->SendMessages(&cnxnFrom, FM_GUARANTEED, FM_FLUSH);
}
break;
case FM_C_FIND_PLAYER:
{
CASTPFM(pfmFindPlayer, C, FIND_PLAYER, pfm);
const char* szCharacterName = FM_VAR_REF(pfmFindPlayer, szCharacterName);
CFLMission * pMissionFound = NULL;
if (szCharacterName == NULL || szCharacterName[pfmFindPlayer->cbszCharacterName-1] != '\0')
{
g_pLobbyApp->GetSite()->LogEvent(EVENTLOG_WARNING_TYPE, LE_CorruptFindPlayerMsg,
cnxnFrom.GetName(), cnxnFrom.GetID());
}
else
pMissionFound = g_pLobbyApp->FindPlayersMission(szCharacterName);
BEGIN_PFM_CREATE(*pthis, pfmFoundPlayer, L, FOUND_PLAYER)
END_PFM_CREATE
pfmFoundPlayer->dwCookie = pMissionFound ? pMissionFound->GetCookie() : -1;
pthis->SendMessages(&cnxnFrom, FM_GUARANTEED, FM_FLUSH);
}
break;
default:
g_pLobbyApp->GetSite()->LogEvent(EVENTLOG_WARNING_TYPE, LE_UnknownMsgFromPlayer,
pfm->fmid, cnxnFrom.GetName(), cnxnFrom.GetID());
}
return S_OK;
}
HRESULT LobbyClientSite::OnSysMessage(FedMessaging * pthis)
{
return S_OK;
}
void LobbyClientSite::OnMessageNAK(FedMessaging * pthis, DWORD dwTime, CFMRecipient * prcp)
{
debugf("ACK!! A guaranteed message didn't make it through to recipient %s.\n", prcp->GetName());
}
HRESULT LobbyClientSite::OnNewConnection(FedMessaging * pthis, CFMConnection & cnxn)
{
CFLClient * pClient = new CFLClient(&cnxn);
debugf("Player %s has connected.\n", cnxn.GetName());
g_pLobbyApp->GetCounters()->cLogins++;
return S_OK;
}
HRESULT LobbyClientSite::OnDestroyConnection(FedMessaging * pthis, CFMConnection & cnxn)
{
debugf("Player %s has left.\n", cnxn.GetName());
g_pLobbyApp->GetCounters()->cLogoffs++;
delete CFLClient::FromConnection(cnxn);
return S_OK;
}
HRESULT LobbyClientSite::OnSessionLost(FedMessaging * pthis)
{
g_pLobbyApp->GetSite()->LogEvent(EVENTLOG_ERROR_TYPE, LE_ClientsSessionLost);
return S_OK;
}
int LobbyClientSite::OnMessageBox(FedMessaging * pthis, const char * strText, const char * strCaption, UINT nType)
{
debugf("LobbyClientSite::OnMessageBox: ");
return g_pLobbyApp->OnMessageBox(strText, strCaption, nType);
}
#ifndef NO_MSG_CRC
void LobbyClientSite::OnBadCRC(FedMessaging * pthis, CFMConnection & cnxn, BYTE * pMsg, DWORD cbMsg)
{
char buf[256];
FMD_C_LOGON_LOBBY * pfmLogon = (FMD_C_LOGON_LOBBY *) pMsg;
if (pfmLogon->fmid == FM_C_LOGON_LOBBY &&
cbMsg == sizeof(FMD_C_LOGON_LOBBY) + pfmLogon->cbZoneTicket) {
g_fLogonCRC = false;
OnAppMessage(pthis, cnxn, pfmLogon);
}
else
{
wsprintf(buf, "HEY! We got a corrupt message!\nPlayer=%s(%d), "
"cbmsg=%d, fmid=%d, total packet size=%d.\n"
"Copy the above line to crashplayers.txt on \\\\zoneagga01. Going to drop player now.\n",
cnxn.GetName(), cnxn.GetID(),
cbMsg >= 2 ? pfmLogon->cbmsg : 0, cbMsg >= 4 ? pfmLogon->fmid : 0, cbMsg);
OnMessageBox(pthis, buf, "AllLobby", 0);
pthis->DeleteConnection(cnxn); }
}
#endif