Files
ls-2019-source/extra/LS_Service/LS_controller/GameCommand.cpp
T
2026-11-07 13:30:45 +07:00

710 lines
15 KiB
C++

#include "StdAfx.h"
#include "cFile.h"
#include "MD5.h"
#include "cDemonLauncher.h"
#include "SessionProc.h"
#include "GameCommand.h"
#include "Utility.h"
#include "../include/IIocpContext.h"
#include <io.h>
#include <shlwapi.h>
extern void Tokenize(const std::tstring& str, TOKENS& tokens, const std::tstring& delimiters);
extern BOOL GetServices(STRINGS& services, STRINGS& files, STRINGS& scripts);
extern BOOL IsService(const TCHAR* serviceName);
extern BOOL CreateFolder(const TCHAR* path);
extern BOOL CreateConsole(const TCHAR* title, TCHAR* command, TCHAR* arguments);
void CPing::Run(IIocpContext* context)
{
scPing packet;
packet.code = rand();
SessionProc::SendPacket(
context,
S_PING,
reinterpret_cast<uint8*>(&packet),
sizeof(packet));
}
void CServices::Run(IIocpContext* context)
{
if(!Ready(context))
return;
Begin(context);
}
BOOL CServices::Ready(IIocpContext* context)
{
m_session = SessionProc::GetSession(context->GetEntity());
if(!m_session) return FALSE;
return TRUE;
}
void CServices::Begin(IIocpContext* context)
{
if(GetServices(m_services, m_files, m_scripts))
{
Debug(_T("Service count :: %lu\n"), m_services.size());
scServices packet;
packet.count = m_services.size();
cSerialize::Reset();
cSerialize::Write(reinterpret_cast<uint8*>(&packet), sizeof(packet));
Service temp;
std::tstring service, file, script;
for(uint32 n = 0 ; n < packet.count ; n++)
{
service = m_services[n];
file = m_files[n];
script = m_scripts[n];
ZeroMemory(&temp, sizeof(temp));
BOOL result = GetRunning(service.c_str(), temp.running, temp.console);
if(result)
{
Debug(_T("Running :: %s\n"), service.c_str());
}
else
{
Debug(_T("Not Running :: %s\n"), service.c_str());
}
CopyMemory(temp.service, service.c_str(), sizeof(temp.service));
cSerialize::Write(reinterpret_cast<uint8*>(&temp), sizeof(temp));
}
SessionProc::SendPacket(
context,
S_SERVICES,
cSerialize::GetBuffer(),
cSerialize::GetLength());
}
else
{
Debug(_T("Service count :: 0\n"));
scServices packet;
packet.count = 0;
SessionProc::SendPacket(
context,
S_SERVICES,
reinterpret_cast<uint8*>(&packet),
sizeof(packet));
}
}
BOOL CServices::GetRunning(const TCHAR* service, BOOL& running, BOOL& console)
{
running = g_demonLauncher.IsRunningService(service);
if(running)
{
console = FALSE;
return TRUE;
}
running = g_demonLauncher.IsRunningConsole(service);
if(running)
{
//PID = g_demonLauncher.GetPID(service);
console = TRUE;
return TRUE;
}
return FALSE;
}
void CTransfer::Run(IIocpContext* context)
{
if(!Ready(context))
return;
Begin(context);
}
BOOL CTransfer::Ready(IIocpContext* context)
{
m_session = SessionProc::GetSession(context->GetEntity());
if(!m_session) return FALSE;
return TRUE;
}
void CTransfer::Begin(IIocpContext* context)
{
BOOL result = FALSE;
switch(m_packet->type)
{
case TRANSFER_BEGIN :
result = TransferBegin();
break;
case TRANSFER_DO :
result = TransferDo();
break;
case TRANSFER_END :
result = TransferEnd();
break;
}
if(result)
{
scTransfer packet;
packet.result = result;
packet.type = m_packet->type;
packet.index = m_packet->index;
SessionProc::SendPacket(
context,
S_TRANSFER,
reinterpret_cast<uint8*>(&packet),
sizeof(packet));
}
else
{
scTransferFail packet;
packet.result = result;
packet.type = m_packet->type;
packet.index = m_packet->index;
CopyMemory(packet.file, m_session->GetFile(), sizeof(packet.file));
SessionProc::SendPacket(
context,
S_TRANSFER,
reinterpret_cast<uint8*>(&packet),
sizeof(packet));
m_session->TransferEnd();
}
}
BOOL CTransfer::TransferBegin()
{
if(m_session->DoingTransfer())
return FALSE;
TCHAR path[512];
_stprintf_s(path, _countof(path), _T("%s\\%s"), m_begin->folder, m_begin->file);
if(UpdateFile(path, m_begin->length, m_begin->digest))
{
// 파일이 존재하지 않거나 다른 버젼이므로 복사한다
CreateFolder(m_begin->folder);
CreateBuffer(path, m_begin->length);
return TRUE;
}
// 파일이 존재하고 같은 버젼의 파일이다
return FALSE;
}
BOOL CTransfer::TransferDo()
{
if(m_session->TransferDo(m_buffer, m_length))
{
// 추가 성공
if(m_session->GetLength() >= G_MAXFILESIZE)
{
cFileWriter file;
if(!file.Open(m_session->GetFile(), OPEN_ALWAYS))
{
// 파일생성 실패
Debug(_T("CTransfer - 파일생성 실패\n"));
return FALSE;
}
file.Move(FILE_END, 0);
if(!file.Write(m_session->GetBuffer(), m_session->GetLength()))
{
// 파일 쓰기 실패
file.Close();
Debug(_T("CTransfer - 파일쓰기 실패(%lu Bytes)\n"), m_session->GetLength());
return FALSE;
}
// 종료
file.Close();
// 버퍼정리
m_session->TransferWrite();
}
return TRUE;
}
// 실패
Debug(_T("CTransfer - 데이타 전송실패\n"));
return FALSE;
}
BOOL CTransfer::TransferEnd()
{
if(!m_session->DoingTransfer())
return FALSE;
if(m_end->length == m_session->GetTransferLength())
{
// 미리 저장된 파일인지 확인
if(m_session->GetTransferLength() == m_session->GetLength())
{
// 저장된 적이 없으면 기존 파일을 지운다
DeleteFile(m_session->GetFile());
}
BOOL result = TRUE;
cFileWriter file;
if(!file.Open(m_session->GetFile(), OPEN_ALWAYS))
{
// 파일생성 실패
result = FALSE;
DWORD error = GetLastError();
m_session->TransferEnd();
Debug(_T("CTransfer - 파일생성 실패\n"));
return FALSE;
}
file.Move(FILE_END, 0);
if(!file.Write(m_session->GetBuffer(), m_session->GetLength()))
{
// 파일 쓰기 실패
file.Close();
result = FALSE;
m_session->TransferEnd();
Debug(_T("CTransfer - 파일쓰기 실패(%lu Bytes)\n"), m_session->GetLength());
return FALSE;
}
// 종료
file.Close();
m_session->TransferEnd();
Debug(_T("CTransfer - 파일 전송완료 (%0.1lfKB)\n"), m_end->length / 1024.0);
return result;
}
// 실패
m_session->TransferEnd();
Debug(_T("CTransfer - 파일 전송실패\n"));
return FALSE;
}
BOOL CTransfer::UpdateFile(const TCHAR* fileName, const uint32 fileLength, const BYTE* source)
{
cFileReader file;
BOOL result = file.Open(fileName);
if(result)
{
if(file.GetFileSize() == fileLength)
{
m_temp.Erase();
m_temp.Resize(fileLength);
if(!file.Read(m_temp.GetBuffer(), fileLength))
{
file.Close();
return TRUE;
}
m_temp.SetLength(fileLength);
CMD5 MD5;
MD5.Generate(m_temp.GetBuffer(), fileLength);
BYTE digest[16];
CopyMemory(digest, MD5.GetDigest(), sizeof(digest));
for(uint32 n = 0 ; n < 16 ; n++)
{
if(digest[n] != source[n])
{
file.Close();
return TRUE;
}
}
file.Close();
return FALSE;
}
else
{
file.Close();
return TRUE;
}
}
return TRUE;
}
BOOL CTransfer::CreateBuffer(const TCHAR* fileName, const uint32 length)
{
m_session->TransferBegin(fileName, length);
DeleteFile(m_session->GetFile());
return TRUE;
}
void CRemove::Run(IIocpContext* context)
{
if(!Ready(context))
return;
Begin(context);
}
BOOL CRemove::Ready(IIocpContext* context)
{
m_session = SessionProc::GetSession(context->GetEntity());
if(!m_session) return FALSE;
return TRUE;
}
void CRemove::Begin(IIocpContext* context)
{
BOOL result = RemoveFolder();
scRemove packet;
packet.result = result;
SessionProc::SendPacket(
context,
S_REMOVE,
reinterpret_cast<uint8*>(&packet),
sizeof(packet));
}
BOOL CRemove::RemoveFolder()
{
SHFILEOPSTRUCT fileop = {0};
fileop.hwnd = NULL;
fileop.wFunc = FO_DELETE; // 삭제 속성 설정
fileop.pFrom = m_packet->folder;
fileop.pTo = NULL;
fileop.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI;
fileop.fAnyOperationsAborted = FALSE;
fileop.hNameMappings = NULL;
fileop.lpszProgressTitle = NULL;
int result = SHFileOperation(&fileop);
return (0 == result) ? TRUE : FALSE;
}
void CInstall::Run(IIocpContext* context)
{
if(!Ready(context))
return;
Begin(context);
}
BOOL CInstall::Ready(IIocpContext* context)
{
m_session = SessionProc::GetSession(context->GetEntity());
if(!m_session) return FALSE;
return TRUE;
}
void CInstall::Begin(IIocpContext* context)
{
BOOL result = FALSE;
if(m_packet->install)
{
result = DoInstall(m_install->service, m_install->file, m_install->script);
}
else
{
result = DoUninstall(m_uninstall->service);
if(result)
{
Remove(m_uninstall->clear);
}
}
scInstall packet;
packet.result = result;
SessionProc::SendPacket(
context,
S_INSTALL,
reinterpret_cast<uint8*>(&packet),
sizeof(packet));
}
BOOL CInstall::DoInstall(const TCHAR* service, const TCHAR* file, const TCHAR* script)
{
if(CreateRegistry(service, file, script))
{
TCHAR command[512];
_stprintf_s(command, _countof(command), _T("/c \"%s -i %s %s\""), file, service, service);
ShellExecute(NULL , NULL, _T("cmd.exe") , command, NULL, SW_HIDE);
return IsService(service);
}
return FALSE;
}
BOOL CInstall::DoUninstall(const TCHAR* service)
{
if(DeleteRegistry(service))
{
TCHAR command[512];
_stprintf_s(command, _countof(command), _T("/c \"sc delete %s\""), service);
ShellExecute(NULL , NULL, _T("cmd.exe") , command, NULL, SW_HIDE);
return !IsService(service);
}
return FALSE;
}
void CInstall::Remove(const BOOL b)
{
if(b)
{
// 파일을 모두 지운다
}
}
BOOL CInstall::CreateRegistry(const TCHAR* service, const TCHAR* file, const TCHAR* script)
{
TCHAR regKey[512];
_stprintf_s(regKey, _countof(regKey), _T("software\\LostSaga\\%s"), service);
HKEY key;
DWORD disp = 0;
LONG ret = RegCreateKeyEx(HKEY_CURRENT_USER, regKey,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &disp);
if(ret != ERROR_SUCCESS) return FALSE;
uint32 length = _tcsclen(service);
length = length*sizeof(TCHAR);
RegSetValueEx(key, _T("service"), 0, REG_SZ, (LPBYTE)service, length);
length = _tcsclen(file);
length = length*sizeof(TCHAR);
RegSetValueEx(key, _T("file"), 0, REG_SZ, (LPBYTE)file, length);
length = _tcsclen(script);
length = length*sizeof(TCHAR);
RegSetValueEx(key, _T("script"), 0, REG_SZ, (LPBYTE)script, length);
RegCloseKey(key);
return TRUE;
}
BOOL CInstall::DeleteRegistry(const TCHAR* service)
{
TCHAR regKey[512];
_stprintf_s(regKey, _countof(regKey), _T("software\\LostSaga\\%s"), service);
DWORD disp = 0;
LONG ret = SHDeleteKey(HKEY_CURRENT_USER, regKey);
if(ret != ERROR_SUCCESS) return FALSE;
return TRUE;
}
void CPlay::Run(IIocpContext* context)
{
if(!Ready(context))
return;
Begin(context);
}
BOOL CPlay::Ready(IIocpContext* context)
{
m_session = SessionProc::GetSession(context->GetEntity());
if(!m_session) return FALSE;
return TRUE;
}
void CPlay::Begin(IIocpContext* context)
{
BOOL result = FALSE;
if(m_packet->play)
{
result = g_demonLauncher.Play(m_packet->service, m_packet->isDemon);
}
else
{
result = g_demonLauncher.Stop(m_packet->service, m_packet->isDemon);
}
scPlay packet;
packet.result = result;
SessionProc::SendPacket(
context,
S_PLAY,
reinterpret_cast<uint8*>(&packet),
sizeof(packet));
}
void CBackup::Run(IIocpContext* context)
{
if(!Ready(context))
return;
Begin(context);
}
BOOL CBackup::Ready(IIocpContext* context)
{
m_session = SessionProc::GetSession(context->GetEntity());
if(!m_session) return FALSE;
return TRUE;
}
void CBackup::Begin(IIocpContext* context)
{
BOOL result = DoBackup(m_packet->source, m_packet->target);
scBackup packet;
packet.result = result;
SessionProc::SendPacket(
context,
S_BACKUP,
reinterpret_cast<uint8*>(&packet),
sizeof(packet));
}
BOOL CBackup::DoBackup(const TCHAR* source, const TCHAR* target)
{
SYSTEMTIME systemTime;
GetLocalTime(&systemTime);
TCHAR backup[512];
ZeroMemory(backup, _countof(backup));
_stprintf_s(backup, _countof(backup),
_T("%s\\%04d%02d%02d-%02d%02d"),
target,
systemTime.wYear,
systemTime.wMonth,
systemTime.wDay,
systemTime.wHour,
systemTime.wMinute);
if(!CreateFolder(backup))
return FALSE;
SHFILEOPSTRUCT fileop = {0};
fileop.hwnd = NULL;
fileop.wFunc = FO_COPY; // 삭제 속성 설정
fileop.pFrom = source;
fileop.pTo = backup;
fileop.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI;
fileop.fAnyOperationsAborted = FALSE;
fileop.hNameMappings = NULL;
fileop.lpszProgressTitle = NULL;
int result = SHFileOperation(&fileop);
return (0 == result) ? TRUE : FALSE;
}
void CReboot::Run(IIocpContext* context)
{
if(!Ready(context))
return;
Begin(context);
}
BOOL CReboot::Ready(IIocpContext* context)
{
m_session = SessionProc::GetSession(context->GetEntity());
if(!m_session) return FALSE;
return TRUE;
}
void CReboot::Begin(IIocpContext* context)
{
BOOL result = DoReboot(m_packet->option);
scReboot packet;
packet.result = result;
SessionProc::SendPacket(
context,
S_REBOOT,
reinterpret_cast<uint8*>(&packet),
sizeof(packet));
}
BOOL CReboot::DoReboot(const uint32 option)
{
TCHAR command[512];
_stprintf_s(command, _countof(command), _T("/c \"shutdown.exe /f /r /t %lu\""), option);
ShellExecute(NULL , NULL, _T("cmd.exe") , command, NULL, SW_HIDE);
return TRUE;
}
void CResource::Run(IIocpContext* context)
{
if(!Ready(context))
return;
Begin(context);
}
BOOL CResource::Ready(IIocpContext* context)
{
m_session = SessionProc::GetSession(context->GetEntity());
if(!m_session) return FALSE;
return TRUE;
}
void CResource::Begin(IIocpContext* context)
{
UNITS cpus, mems, diskC, diskD, networks;
DWORD error;
m_perfomance.GetCPU(cpus, error);
m_perfomance.GetMemory(mems, error);
m_perfomance.GetDisk(_T("c:"), diskC, error);
m_perfomance.GetDisk(_T("d:"), diskD, error);
m_perfomance.GetNetwork(networks, error);
scResource packet;
packet.result = TRUE;
packet.cpu = cpus.size();
packet.memory = mems.size();
packet.disk = diskC.size() + diskD.size();
packet.network = networks.size();
cSerialize::Reset();
cSerialize::Write(reinterpret_cast<uint8*>(&packet), sizeof(packet));
for(unsigned int i = 0 ; i < cpus.size() ; i++)
{
cSerialize::Write(static_cast<uint32>(cpus[i]));
}
for(unsigned int i = 0 ; i < mems.size() ; i++)
{
cSerialize::Write(static_cast<uint32>(mems[i]));
}
for(unsigned int i = 0 ; i < diskC.size() ; i++)
{
cSerialize::Write(static_cast<uint32>(diskC[i]));
}
for(unsigned int i = 0 ; i < diskD.size() ; i++)
{
cSerialize::Write(static_cast<uint32>(diskD[i]));
}
for(unsigned int i = 0 ; i < networks.size() ; i++)
{
cSerialize::Write(static_cast<uint32>(networks[i]));
}
SessionProc::SendPacket(
context,
S_RESOURCE,
cSerialize::GetBuffer(),
cSerialize::GetLength());
}