549 lines
16 KiB
C++
549 lines
16 KiB
C++
// GearRemoteFileSystem.cpp : Defines the entry point for the console application.
|
|
//
|
|
// PORT 8088
|
|
|
|
#include "stdafx.h"
|
|
#include "logfile.h"
|
|
#include "Windows.h"
|
|
#include "Winsvc.h"
|
|
#include <conio.h>
|
|
#include "time.h"
|
|
#include "../Utils/cpp/singleinstancechecker.h"
|
|
|
|
#define CONFIG_FILENAME "config.xml"
|
|
|
|
#define SERVER_LOG_LEVEL GEAR_LOG_USER_DEFINED
|
|
#define SYSTEM_LOG_LEVEL (GEAR_LOG_INFO | GEAR_LOG_ERROR | GEAR_LOG_CRITICAL | SERVER_LOG_LEVEL)
|
|
|
|
#define CMD_LINE_MSG "\nGearRemoteFileSystem -i -d -start -stop -n\n" \
|
|
"-i To install service\n" \
|
|
"-d To UnInstall service\n" \
|
|
"-start To start the service\n" \
|
|
"-stop To stop the service\n" \
|
|
"-n To run GearRemoteFileSystem as a normal command line application\n"\
|
|
"-v Verbose Mode (will display full debug info)\n"
|
|
|
|
LogFile* errorLogfile=0;
|
|
|
|
Gear::RFSServer* gRFSServer = 0;
|
|
|
|
SERVICE_STATUS m_ServiceStatus;
|
|
SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
|
|
BOOL bRunning = true;
|
|
Gear::U32 ServerLogLevel = SYSTEM_LOG_LEVEL;
|
|
|
|
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
|
|
void WINAPI ServiceCtrlHandler(DWORD Opcode);
|
|
BOOL InstallService();
|
|
BOOL DeleteService();
|
|
BOOL StartService();
|
|
BOOL StopService();
|
|
int RealMain(BOOL bStartFromService);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void MyConsoleOut(Gear::U32 iLogLevel,const char* msg)
|
|
{
|
|
GEAR_UNUSED(iLogLevel);
|
|
if (strstr(msg, "Debug :") == 0)
|
|
{
|
|
printf("%s", msg);
|
|
if (errorLogfile)
|
|
errorLogfile->Write(msg);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static int AssertFunct(const char *condition, const char *msg, const char *file, int line, int extra)
|
|
{
|
|
GEAR_UNUSED(extra);
|
|
char tmp[256];
|
|
Gear::StrFormat::snprintf(tmp, 256, "ASSERT: %s %s at %s(%d)\n", condition, msg, file, line);
|
|
Gear::NativeDebugOutput(tmp);
|
|
printf("%s", tmp);
|
|
|
|
if (errorLogfile)
|
|
errorLogfile->Write(tmp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// -i install the service
|
|
// -d delete the service
|
|
// -start start the service
|
|
// -stop stop the srevice
|
|
// -n start the server as a command line application and not a service
|
|
// -v Verbose
|
|
//
|
|
int main(int argc, char* argv[])
|
|
{
|
|
bool RunMain = false;
|
|
|
|
if(argc > 1)
|
|
{
|
|
for(int i = 1; i < argc; i++)
|
|
{
|
|
if(strcmp(argv[i],"-i")==0)
|
|
{
|
|
if(InstallService())
|
|
printf("\n\nService Installed Sucessfully\n");
|
|
else
|
|
printf("\n\nError Installing Service\n");
|
|
}
|
|
else if(strcmp(argv[i],"-d")==0)
|
|
{
|
|
if(DeleteService())
|
|
printf("\n\nService UnInstalled Sucessfully\n");
|
|
else
|
|
printf("\n\nError UnInstalling Service\n");
|
|
}
|
|
else if(strcmp(argv[i],"-start")==0)
|
|
{
|
|
StartService();
|
|
}
|
|
else if(strcmp(argv[i],"-stop")==0)
|
|
{
|
|
StopService();
|
|
}
|
|
else if(strcmp(argv[i],"-n")==0)
|
|
{
|
|
//NOTE: if you're debugging the server, use -n to run it as a normal command line application
|
|
RunMain = true;
|
|
}
|
|
else if(strcmp(argv[i],"-v")==0)
|
|
{
|
|
ServerLogLevel = 0xFFFFFFFF;
|
|
}
|
|
else
|
|
{
|
|
printf("\n\nUnknown Switch"CMD_LINE_MSG);
|
|
}
|
|
} // end for
|
|
|
|
if(RunMain)
|
|
{
|
|
RealMain(false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SERVICE_TABLE_ENTRY DispatchTable[]= {{"GearRemoteFileSystem",ServiceMain},{NULL,NULL}};
|
|
if (StartServiceCtrlDispatcher(DispatchTable) == 0)
|
|
{
|
|
//NOTE: if you're debugging the server, use -n to run it as a normal command line application
|
|
MyConsoleOut(GEAR_LOG_INFO,"\n\nYou cannot start the service from the command line.\n"
|
|
"Please use the -start command line option if it is not allready started\n"
|
|
"If you dont want to run this server as a service, use the -n option\n"
|
|
"Here are the command line options : "CMD_LINE_MSG);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void WINAPI ServiceMain(DWORD , LPTSTR *)
|
|
{
|
|
m_ServiceStatus.dwServiceType = SERVICE_WIN32;
|
|
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
|
m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
|
m_ServiceStatus.dwWin32ExitCode = 0;
|
|
m_ServiceStatus.dwServiceSpecificExitCode = 0;
|
|
m_ServiceStatus.dwCheckPoint = 0;
|
|
m_ServiceStatus.dwWaitHint = 0;
|
|
|
|
m_ServiceStatusHandle = RegisterServiceCtrlHandler("GearRemoteFileSystem", ServiceCtrlHandler);
|
|
|
|
if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error registering the service\n");
|
|
return;
|
|
}
|
|
|
|
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
|
m_ServiceStatus.dwCheckPoint = 0;
|
|
m_ServiceStatus.dwWaitHint = 0;
|
|
if (!SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus))
|
|
{
|
|
}
|
|
|
|
Sleep(3000);
|
|
GEAR_LOG(GEAR_LOG_MSG, "Service is running...\n");
|
|
RealMain(true);
|
|
|
|
return;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void WINAPI ServiceCtrlHandler(DWORD Opcode)
|
|
{
|
|
switch(Opcode)
|
|
{
|
|
case SERVICE_CONTROL_PAUSE:
|
|
m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
|
|
break;
|
|
case SERVICE_CONTROL_CONTINUE:
|
|
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
|
break;
|
|
case SERVICE_CONTROL_STOP:
|
|
m_ServiceStatus.dwWin32ExitCode = 0;
|
|
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
|
m_ServiceStatus.dwCheckPoint = 0;
|
|
m_ServiceStatus.dwWaitHint = 0;
|
|
|
|
SetServiceStatus(m_ServiceStatusHandle,&m_ServiceStatus);
|
|
bRunning=false;
|
|
GEAR_LOG(GEAR_LOG_MSG, "Stopping service\n");
|
|
|
|
if( gRFSServer )
|
|
gRFSServer->Shutdown();
|
|
|
|
break;
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL GetServiceBinaryPath(Gear::GearString & directoryPath)
|
|
{
|
|
SC_HANDLE schService, schSCManager;
|
|
LPQUERY_SERVICE_CONFIG lpqscBuf;
|
|
DWORD dwBytesNeeded;
|
|
BOOL bSuccess = false;
|
|
|
|
// Open a handle to the SC Manager database...
|
|
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
|
|
if (schSCManager == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error Opening Service Manager\n");
|
|
}
|
|
else
|
|
{
|
|
schService=OpenService(schSCManager,"GearRemoteFileSystem",SERVICE_ALL_ACCESS);
|
|
if (schService == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error Opening Service GearRemoteFileSystem\n");
|
|
}
|
|
else
|
|
{
|
|
// Allocate a buffer for the configuration information.
|
|
lpqscBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096);
|
|
if (lpqscBuf == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error , Could not allocate memory to retrieve service config.\n");
|
|
|
|
}
|
|
else
|
|
{
|
|
// Get the configuration information.
|
|
if (! QueryServiceConfig(schService, lpqscBuf,4096, &dwBytesNeeded))
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error , Could not retrieve service configuration\n");
|
|
|
|
}
|
|
else
|
|
{
|
|
directoryPath = lpqscBuf->lpBinaryPathName;
|
|
Gear::S32 iIndex = directoryPath.FindReverse('\\');
|
|
|
|
if (iIndex != -1)
|
|
{
|
|
directoryPath.Resize(iIndex);
|
|
bSuccess = true;
|
|
}
|
|
}
|
|
|
|
LocalFree(lpqscBuf);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL InstallService()
|
|
{
|
|
char strDir[1024];
|
|
SC_HANDLE schSCManager,schService;
|
|
GetCurrentDirectory(1024,strDir);
|
|
strcat(strDir,"\\GearRemoteFileSystem.exe");
|
|
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
|
|
|
|
if (schSCManager == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error openning SCManager\n");
|
|
return false;
|
|
}
|
|
LPCTSTR lpszBinaryPathName=strDir;
|
|
|
|
schService = CreateService(schSCManager,"GearRemoteFileSystem", "Gear Remote file system server", // service name to display
|
|
SERVICE_ALL_ACCESS, // desired access
|
|
SERVICE_WIN32_OWN_PROCESS, // service type
|
|
SERVICE_AUTO_START, // start type
|
|
SERVICE_ERROR_NORMAL, // error control type
|
|
lpszBinaryPathName, // service's binary
|
|
NULL, // no load ordering group
|
|
NULL, // no tag identifier
|
|
NULL, // no dependencies
|
|
NULL, // LocalSystem account
|
|
NULL); // no password
|
|
|
|
if (schService == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error creating service \n");
|
|
return false;
|
|
}
|
|
|
|
CloseServiceHandle(schService);
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL DeleteService()
|
|
{
|
|
SC_HANDLE schSCManager;
|
|
SC_HANDLE hService;
|
|
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
|
|
|
|
if (schSCManager == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error deleting service \n");
|
|
return false;
|
|
}
|
|
hService=OpenService(schSCManager,"GearRemoteFileSystem",SERVICE_ALL_ACCESS);
|
|
if (hService == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error deleting service \n");
|
|
return false;
|
|
}
|
|
if(DeleteService(hService)==0)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error deleting service \n");
|
|
return false;
|
|
}
|
|
if(CloseServiceHandle(hService)==0)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error deleting service \n");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL StartService()
|
|
{
|
|
SC_HANDLE schSCManager;
|
|
SC_HANDLE hService;
|
|
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
|
|
|
|
if (schSCManager == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error Starting service\n");
|
|
return false;
|
|
}
|
|
hService=OpenService(schSCManager,"GearRemoteFileSystem",SERVICE_ALL_ACCESS);
|
|
if (hService == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error Starting service \n");
|
|
return false;
|
|
}
|
|
if(StartService(hService, 0, 0)==0)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error Starting service \n");
|
|
return false;
|
|
}
|
|
if(CloseServiceHandle(hService)==0)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error Starting service \n");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL StopService()
|
|
{
|
|
SC_HANDLE schSCManager;
|
|
SC_HANDLE hService;
|
|
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
|
|
|
|
if (schSCManager == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error Stoping service \n");
|
|
return false;
|
|
}
|
|
hService=OpenService(schSCManager,"GearRemoteFileSystem",SERVICE_ALL_ACCESS);
|
|
if (hService == NULL)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error Stoping service \n");
|
|
return false;
|
|
}
|
|
|
|
SERVICE_STATUS status;
|
|
if(ControlService(hService, SERVICE_CONTROL_STOP, &status)==0)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error Stoping service \n");
|
|
return false;
|
|
}
|
|
if(CloseServiceHandle(hService)==0)
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Error Stoping service \n");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Be sure to have Locked the server config before calling SaveServerConfig()
|
|
|
|
Gear::Bool SaveServerConfig(Gear::RFS::Config& Config, Gear::Char* pFilename)
|
|
{
|
|
Gear::GearString filename = Config.GetApplicationPath();
|
|
filename += pFilename;
|
|
|
|
Gear::XMLWriterSerializer SerializerObj;
|
|
Gear::Bool result = SerializerObj.SetDevice(filename.CStr());
|
|
|
|
if( result )
|
|
{
|
|
SerializerObj << Config;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void LoadServerConfig(Gear::RFSServer& server, Gear::Char* pFilename)
|
|
{
|
|
// Take atomic access to the Server config
|
|
Gear::RFS::Config& Config = server.GetConfig();
|
|
|
|
Gear::GearString filename = Config.GetApplicationPath();
|
|
filename += pFilename;
|
|
|
|
Gear::XMLReaderSerializer SerializerObj;
|
|
Gear::Bool result = SerializerObj.SetDevice(filename.CStr());
|
|
|
|
if( result )
|
|
{
|
|
SerializerObj << Config;
|
|
GEAR_LOG1(SERVER_LOG_LEVEL, "> Configuration loaded successfully from '%s'\n", pFilename);
|
|
}
|
|
else
|
|
{
|
|
GEAR_LOG1(SERVER_LOG_LEVEL, "> Configuration file not found, creating new one '%s'\n", pFilename);
|
|
|
|
// Set Default configuration since we cannot find the configuration file
|
|
Config.ResetDefaultConfig();
|
|
|
|
// For the server application, let's assume we are at Ubisoft & Add the Ubisoft domain
|
|
Config.AddAuthorizedIP("10.*.*.*");
|
|
|
|
SaveServerConfig(Config, pFilename);
|
|
}
|
|
|
|
// Release atomic access to the Server config
|
|
server.ReleaseConfig();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ConfigModificationCallback(Gear::RFS::Config& Config)
|
|
{
|
|
SaveServerConfig(Config, CONFIG_FILENAME);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int RealMain(BOOL bStartFromService)
|
|
{
|
|
SingleInstanceChecker singleInstanceChecker("GearRemoteFileSystem");
|
|
if(singleInstanceChecker.IsAlreadyStarted())
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Gear Remote File System Server is already running, exising...");
|
|
return FALSE;
|
|
}
|
|
|
|
errorLogfile = new LogFile("error.log");
|
|
|
|
//if we start from a service we need to change directory path
|
|
if (bStartFromService)
|
|
{
|
|
//get the path
|
|
Gear::GearString strServiceBinaryPath;
|
|
if (GetServiceBinaryPath(strServiceBinaryPath))
|
|
{
|
|
if (!SetCurrentDirectory(strServiceBinaryPath.CStr()))
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Could not change current directory to service application root : ");
|
|
GEAR_LOG(GEAR_LOG_ERROR, strServiceBinaryPath.CStr());
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GEAR_LOG(GEAR_LOG_ERROR, "Could not retrieve service information, make sure the service is registered.");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Start Gear
|
|
Gear::StartEngine();
|
|
|
|
// Set Logging Level
|
|
Gear::GearLogManager::SetLoggingFilter(ServerLogLevel);
|
|
|
|
// Connect our Assert Function
|
|
Gear::Assert::ReplaceAssertFunction(AssertFunct);
|
|
|
|
// Create Console functor
|
|
Gear::ConsoleOut::ConsoleHook functor = Gear::MakeFunctor(&functor, MyConsoleOut);
|
|
Gear::ConsoleOut::AddHook(functor);
|
|
|
|
{
|
|
Gear::RFSServer rfsServer(SERVER_LOG_LEVEL, 0, Gear::True);
|
|
gRFSServer = &rfsServer;
|
|
|
|
// Load server config...
|
|
LoadServerConfig(rfsServer, CONFIG_FILENAME);
|
|
|
|
Gear::RFSServer::ConfigFunctor ConfigModifFunctor;
|
|
ConfigModifFunctor = MakeFunctor(&ConfigModifFunctor, &ConfigModificationCallback);
|
|
|
|
// Register config change notifier, to save on changes
|
|
rfsServer.SetConfigFunctor(ConfigModifFunctor);
|
|
|
|
// Start server...
|
|
rfsServer.Start();
|
|
|
|
// If a key is pressed we quit
|
|
Gear::ConsoleOut::Print("Press any key to exit...\n" );
|
|
while (!_kbhit())
|
|
Gear::System::Sleep(100);
|
|
|
|
rfsServer.Shutdown();
|
|
|
|
// Reset global server pointer
|
|
gRFSServer = 0;
|
|
}
|
|
|
|
Gear::ShutDownEngine();
|
|
|
|
delete errorLogfile;
|
|
return 0;
|
|
}
|
|
|