Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
384 lines
8.4 KiB
C++
384 lines
8.4 KiB
C++
#include "comline.hpp"
|
|
//#include <exception>
|
|
#include <stdio.h>
|
|
#include "comline.h"
|
|
|
|
static void* __cdecl operator new (unsigned int size)
|
|
{
|
|
return malloc (size);
|
|
}
|
|
|
|
static void __cdecl operator delete (void *buffer)
|
|
{
|
|
free (buffer);
|
|
}
|
|
|
|
using namespace NCOMLINE;
|
|
|
|
CCommandLineServer *NCOMLINE::n_CurServer = NULL;
|
|
|
|
void ExecuteLine(const unsigned char * pszString)
|
|
{
|
|
if (n_CurServer)
|
|
n_CurServer->ExecuteLine ((const char *) pszString);
|
|
}
|
|
int NumOutputLines(void)
|
|
{
|
|
if (n_CurServer)
|
|
return n_CurServer->NumOutputLines ();
|
|
return 0;
|
|
}
|
|
void GetOutputLine(int size,unsigned char * pszString)
|
|
{
|
|
if (n_CurServer)
|
|
n_CurServer->GetOutputLine (size,pszString);
|
|
}
|
|
void Shutdown(void)
|
|
{
|
|
#ifdef LAB_ONLY
|
|
RPC_STATUS status;
|
|
|
|
status = RpcMgmtStopServerListening(NULL);
|
|
if (!status)
|
|
{
|
|
status = RpcServerUnregisterIf(NULL, NULL, FALSE);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
DWORD WINAPI NCOMLINE::ServerThreadProc (void *p1)
|
|
{
|
|
#if LAB_ONLY
|
|
CCommandLineServer *data;
|
|
|
|
data = static_cast<CCommandLineServer *> (p1);
|
|
|
|
WaitForSingleObject (data->m_Semaphore,INFINITE);
|
|
ReleaseSemaphore (data->m_ExitSemaphore,1,NULL);
|
|
|
|
ReleaseSemaphore (data->m_Semaphore,1,NULL);
|
|
RPC_STATUS status;
|
|
unsigned char * pszProtocolSequence1 = (unsigned char *) "ncacn_ip_tcp";
|
|
unsigned char * pszEndpoint1 = (unsigned char *) "1404";
|
|
|
|
unsigned char * pszProtocolSequence2 = (unsigned char *) "ncalrpc";
|
|
unsigned char * pszEndpoint2 = (unsigned char *) "ComLine";
|
|
unsigned char * pszSecurity = (unsigned char *) NULL;
|
|
unsigned int cMinCalls = 1;
|
|
unsigned int cMaxCalls = 20;
|
|
unsigned int fDontWait = FALSE;
|
|
|
|
|
|
// status = RpcServerUseAllProtseqs (cMaxCalls,pszSecurity);
|
|
status = RpcServerUseProtseqEp(pszProtocolSequence1,cMaxCalls,pszEndpoint1,pszSecurity); // Security descriptor
|
|
if (status)
|
|
return (status);
|
|
|
|
status = RpcServerUseProtseqEp(pszProtocolSequence2,cMaxCalls,pszEndpoint2,pszSecurity); // Security descriptor
|
|
if (status)
|
|
return (status);
|
|
|
|
RPC_BINDING_VECTOR *inq;
|
|
status = RpcServerInqBindings (&inq);
|
|
|
|
status = RpcServerRegisterIf(ComLine_ServerIfHandle, // interface to register
|
|
NULL, // MgrTypeUuid
|
|
NULL); // MgrEpv; null means use default
|
|
if (status)
|
|
return (status);
|
|
|
|
status = RpcServerListen(cMinCalls,cMaxCalls,fDontWait);
|
|
if (status)
|
|
return status;
|
|
|
|
WaitForSingleObject (data->m_ExitSemaphore,INFINITE);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
void CCommandLineServer::PushLine (const LineData& data)
|
|
{
|
|
CRITICAL_CONTROL (m_Critical);
|
|
if (!m_Inited)
|
|
return;
|
|
if (m_NumLines == m_SizeLines)
|
|
{
|
|
int i;
|
|
LineData *temp;
|
|
|
|
temp = new LineData[m_SizeLines+50];
|
|
for (i=0;i<m_NumLines;i++)
|
|
{
|
|
temp[i] = m_Lines[i];
|
|
}
|
|
delete[] m_Lines;
|
|
m_Lines = temp;
|
|
m_SizeLines+=50;
|
|
}
|
|
m_Lines[m_NumLines] = data;
|
|
m_NumLines++;
|
|
}
|
|
|
|
void CCommandLineServer::RemoveLine (void)
|
|
{
|
|
int i;
|
|
|
|
CRITICAL_CONTROL (m_Critical);
|
|
if (!m_Inited)
|
|
return;
|
|
assert (m_NumLines);
|
|
m_NumLines--;
|
|
for (i=0;i<m_NumLines;i++)
|
|
{
|
|
m_Lines[i] = m_Lines[i+1];
|
|
}
|
|
}
|
|
|
|
void CCommandLineServer::PushCommand (const CommandMap& data)
|
|
{
|
|
CRITICAL_CONTROL (m_Critical);
|
|
if (!m_Inited)
|
|
return;
|
|
if (m_NumLines == m_SizeLines)
|
|
{
|
|
int i;
|
|
CommandMap *temp;
|
|
|
|
temp = new CommandMap[m_SizeCommands+50];
|
|
for (i=0;i<m_NumCommands;i++)
|
|
{
|
|
temp[i] = m_Commands[i];
|
|
}
|
|
delete[] m_Commands;
|
|
m_Commands = temp;
|
|
m_SizeCommands+=50;
|
|
}
|
|
m_Commands[m_NumCommands] = data;
|
|
m_NumCommands++;
|
|
}
|
|
|
|
CCommandLineServer::CCommandLineServer (void)
|
|
{
|
|
m_Inited = false;
|
|
m_Lines = NULL;
|
|
m_NumLines = 0;
|
|
m_SizeLines = 0;
|
|
m_Commands = NULL;
|
|
m_NumCommands = 0;
|
|
m_SizeCommands = 0;
|
|
m_Semaphore = NULL;
|
|
m_ExitSemaphore = NULL;
|
|
m_Thread = NULL;
|
|
|
|
hMappedFile=NULL;
|
|
#if LAB_ONLY
|
|
hMappedFile=CreateFileMapping( (HANDLE)0xffffffff, //-1 hFile flag
|
|
NULL, // no sharing allowed
|
|
PAGE_READONLY|SEC_RESERVE, // no writing or physical space allocated
|
|
0, // high-byte size
|
|
4, // low byte size
|
|
"AHF_COMLINE_FILE"); // use class string as file name
|
|
if (hMappedFile!=NULL && GetLastError() == ERROR_ALREADY_EXISTS)
|
|
{
|
|
//another T2 is running, it just hasn't created it's window yet
|
|
CloseHandle(hMappedFile);
|
|
hMappedFile=NULL;
|
|
return;
|
|
}
|
|
|
|
m_Lines = new LineData[50];
|
|
m_NumLines = 0;
|
|
m_SizeLines = 50;
|
|
PushLine (LineData ("Command Line server started",LINE_OUTPUT));
|
|
m_Commands = new CommandMap[50];
|
|
m_NumCommands = 0;
|
|
m_SizeCommands = 50;
|
|
|
|
m_Semaphore = CreateSemaphore (NULL,0,1,NULL);
|
|
if (!m_Semaphore)
|
|
assert (false);
|
|
m_ExitSemaphore = CreateSemaphore (NULL,0,1,NULL);
|
|
if (!m_ExitSemaphore)
|
|
assert (false);
|
|
m_Thread = CreateThread (NULL,0,NCOMLINE::ServerThreadProc,(void *) this,0,&m_ThreadID);
|
|
if (!m_Thread)
|
|
assert (false);
|
|
|
|
ReleaseSemaphore (m_Semaphore,1,NULL);
|
|
WaitForSingleObject (m_ExitSemaphore,INFINITE);
|
|
WaitForSingleObject (m_Semaphore,INFINITE);
|
|
|
|
n_CurServer = this;
|
|
m_Inited = true;
|
|
#endif
|
|
}
|
|
|
|
CCommandLineServer::~CCommandLineServer (void)
|
|
{
|
|
|
|
if (!m_Inited)
|
|
return;
|
|
#ifdef LAB_ONLY
|
|
RPC_STATUS status;
|
|
status = RpcMgmtStopServerListening(NULL);
|
|
if (!status)
|
|
{
|
|
status = RpcServerUnregisterIf(NULL, NULL, FALSE);
|
|
}
|
|
#endif
|
|
n_CurServer = NULL;
|
|
|
|
ReleaseSemaphore (m_ExitSemaphore,1,NULL);
|
|
|
|
WaitForSingleObject (m_Thread,INFINITE);
|
|
|
|
CloseHandle (m_ExitSemaphore);
|
|
CloseHandle (m_Semaphore);
|
|
CloseHandle (m_Thread);
|
|
|
|
if (hMappedFile)
|
|
CloseHandle (hMappedFile);
|
|
hMappedFile = NULL;
|
|
|
|
delete[] m_Lines;
|
|
delete[] m_Commands;
|
|
m_Inited = false;
|
|
|
|
}
|
|
|
|
void CCommandLineServer::PushLine (const char *line)
|
|
{
|
|
CRITICAL_CONTROL (m_Critical);
|
|
if (!m_Inited)
|
|
return;
|
|
LineData data (line,LINE_OUTPUT);
|
|
|
|
PushLine (data);
|
|
}
|
|
|
|
void CCommandLineServer::ExecuteLine (const char *line)
|
|
{
|
|
CRITICAL_CONTROL (m_Critical);
|
|
int iter;
|
|
LineData data (line,LINE_COMMAND);
|
|
CCom_String name (line);
|
|
|
|
if (!m_Inited)
|
|
return;
|
|
ParseLine (data);
|
|
if (data.m_ComBreak != name.GetLength ())
|
|
{
|
|
name.SetAt (data.m_ComBreak,0);
|
|
}
|
|
for (iter = 0;iter<m_NumCommands;iter++)
|
|
{
|
|
if (m_Commands[iter].m_Command == name)
|
|
break;
|
|
}
|
|
if (iter != m_NumCommands)
|
|
{
|
|
if (!m_Commands[iter].m_Function (this,data))
|
|
PushLine (LineData ("Function failed",LINE_OUTPUT));
|
|
}
|
|
else
|
|
{
|
|
PushLine (LineData ("Function not found",LINE_OUTPUT));
|
|
}
|
|
}
|
|
|
|
void CCommandLineServer::ParseLine (LineData& data)
|
|
{
|
|
char *buf;
|
|
int i,size;
|
|
bool ignore;
|
|
|
|
CRITICAL_CONTROL (m_Critical);
|
|
ignore = false;
|
|
data.m_Data.TrimLeft ();
|
|
data.m_ComBreak = -1;
|
|
size = data.m_Data.GetLength ();
|
|
buf = data.m_Data.GetBuffer (0);
|
|
for (i=0;i<size;i++,buf++)
|
|
{
|
|
if ((*buf == ' ') && !ignore)
|
|
{
|
|
data.m_ArgBreak[data.m_NumArgs] = i;
|
|
data.m_NumArgs++;
|
|
}
|
|
else if (*buf == '\"')
|
|
{
|
|
ignore = !ignore;
|
|
}
|
|
}
|
|
data.m_Data.ReleaseBuffer ();
|
|
data.m_ArgBreak[data.m_NumArgs] = data.m_Data.GetLength ();
|
|
data.m_NumArgs++;
|
|
data.m_ComBreak = data.m_ArgBreak[0];
|
|
}
|
|
|
|
int CCommandLineServer::NumOutputLines(void)
|
|
{
|
|
return m_NumLines;
|
|
}
|
|
|
|
void CCommandLineServer::GetOutputLine(int size,unsigned char * pszString)
|
|
{
|
|
CRITICAL_CONTROL (m_Critical);
|
|
LineData *iter;
|
|
|
|
iter = m_Lines;
|
|
|
|
if (m_NumLines)
|
|
{
|
|
const char *buffer = (LPCTSTR) iter->m_Data;
|
|
strncpy ((char *) pszString,buffer,size-1);
|
|
pszString[size-1] = 0;
|
|
RemoveLine ();
|
|
}
|
|
else
|
|
pszString[0] = 0;
|
|
}
|
|
|
|
bool CCommandLineServer::AddCommand (NCOMLINE::ComFunc func,const CCom_String& name)
|
|
{
|
|
CRITICAL_CONTROL (m_Critical);
|
|
int iter;
|
|
|
|
if (!m_Inited)
|
|
return false;
|
|
for (iter = 0;iter<m_NumCommands;iter++)
|
|
{
|
|
if (m_Commands[iter].m_Command == name)
|
|
break;
|
|
}
|
|
if (iter != m_NumCommands)
|
|
m_Commands[iter].m_Function = func;
|
|
else
|
|
PushCommand (CommandMap (name,func));
|
|
return true;
|
|
}
|
|
|
|
bool CCommandLineServer::RemoveCommand (const CCom_String& name)
|
|
{
|
|
CRITICAL_CONTROL (m_Critical);
|
|
int iter;
|
|
int i;
|
|
if (!m_Inited)
|
|
return false;
|
|
for (iter = 0;iter<m_NumCommands;iter++)
|
|
{
|
|
if (m_Commands[iter].m_Command == name)
|
|
break;
|
|
}
|
|
if (iter == m_NumCommands)
|
|
return false;
|
|
m_NumCommands--;
|
|
for (i=iter;i<m_NumCommands;i++)
|
|
{
|
|
m_Commands[i] = m_Commands[i+1];
|
|
}
|
|
return true;
|
|
|
|
}
|
|
|