Viewing file: Service.cpp (15.23 KB) -rw-rw-rw- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
// FileZilla Server - a Windows ftp server
// Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// Based upon example code from Nishant S
// Original code is available under http://www.codeproject.com/system/serviceskeleton.asp
#include "stdafx.h"
#include "server.h"
#include "Options.h"
void ServiceMain(DWORD argc, LPTSTR *argv);
void ServiceCtrlHandler(DWORD nControlCode);
BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
DWORD dwWaitHint);
BOOL StartServiceThread();
DWORD ServiceExecutionThread(LPDWORD param);
HANDLE hServiceThread=0;
void KillService();
SERVICE_STATUS_HANDLE nServiceStatusHandle = 0;
HANDLE killServiceEvent = 0;
BOOL nServiceRunning = 0;
DWORD nServiceCurrentStatus = 0;
static TCHAR ServiceDisplayName[257] = _T("FileZilla Server FTP server");
static TCHAR ServiceName[257] = _T("FileZilla Server");
int SetAdminPort(int port);
int ReloadConfig();
int CompatMain(LPCSTR lpCmdLine);
void LoadServiceName()
{
COptions *pOptions = new COptions();
CStdString name = pOptions->GetOption(OPTION_SERVICE_NAME);
if (name.size() > 0 && name.size() < 256)
_tcscpy(ServiceName, name);
CStdString display_name = pOptions->GetOption(OPTION_SERVICE_DISPLAY_NAME);
if (display_name.size() > 0 && display_name.size() < 256)
_tcscpy(ServiceDisplayName, display_name);
delete pOptions;
}
int SetServiceName(LPCTSTR serviceName)
{
size_t len = _tcslen(serviceName);
if (!len || len > 256)
return 1;
COptions *pOptions = new COptions();
pOptions->SetOption(OPTION_SERVICE_NAME, serviceName);
delete pOptions;
pOptions = new COptions();
if (pOptions->GetOption(OPTION_SERVICE_NAME) != serviceName)
{
delete pOptions;
return 1;
}
delete pOptions;
return 0;
}
int SetServiceDisplayName(LPCTSTR serviceDisplayName)
{
size_t len = _tcslen(serviceDisplayName);
if (!len || len > 256)
return 1;
COptions *pOptions = new COptions();
pOptions->SetOption(OPTION_SERVICE_DISPLAY_NAME, serviceDisplayName);
delete pOptions;
pOptions = new COptions();
if (pOptions->GetOption(OPTION_SERVICE_DISPLAY_NAME) != serviceDisplayName)
{
delete pOptions;
return 1;
}
delete pOptions;
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
BOOL bNT = FALSE;
BOOL bInstalled = FALSE;
BOOL dwCurrentState = 0;
int nAction = 0;
if (lpCmdLine[0] == '/' || lpCmdLine[0] == '-')
{
lpCmdLine++;
if (strlen(lpCmdLine) >= 6 && !strncmp(lpCmdLine, "compat", 6))
{
lpCmdLine += 6;
while (lpCmdLine[0] == ' ')
lpCmdLine++;
return CompatMain(lpCmdLine);
}
else if (!strcmp(lpCmdLine, "install"))
nAction = 1;
else if (!strcmp(lpCmdLine, "uninstall"))
nAction = 2;
else if (!strcmp(lpCmdLine, "start"))
nAction = 3;
else if (!strcmp(lpCmdLine, "stop"))
nAction = 4;
else if (!strcmp(lpCmdLine, "install auto"))
nAction = 5;
else if (strlen(lpCmdLine) >= 10 && !strncmp(lpCmdLine, "adminport ", 10))
nAction = 6;
else if (!strcmp(lpCmdLine, "reload-config"))
nAction = 7;
else if (!strncmp(lpCmdLine, "servicename ", 12))
return SetServiceName(CStdString(lpCmdLine + 12));
else if (!strncmp(lpCmdLine, "servicedisplayname ", 19))
return SetServiceDisplayName(CStdString(lpCmdLine + 19));
}
LoadServiceName();
if (nAction == 6)
return SetAdminPort(atoi(lpCmdLine + 10));
else if (nAction == 7)
return ReloadConfig();
SC_HANDLE hService, hScm;
hScm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
if (hScm)
{
bNT = TRUE;
hService = OpenService(hScm, ServiceName, GENERIC_READ);
if (hService)
{
bInstalled = TRUE;
SERVICE_STATUS ServiceStatus;
if (QueryServiceStatus(hService, &ServiceStatus))
{
dwCurrentState = ServiceStatus.dwCurrentState;
if (dwCurrentState == SERVICE_START_PENDING)
{
CloseServiceHandle(hService);
CloseServiceHandle(hScm);
const SERVICE_TABLE_ENTRY servicetable[]=
{
{ServiceName,(LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL,NULL}
};
BOOL success;
success=StartServiceCtrlDispatcher(servicetable);
if (!success)
{
int nError=GetLastError();
TCHAR buffer[1000];
_stprintf(buffer, _T("StartServiceCtrlDispatcher failed with error %d"), nError);
MessageBox(0, buffer, _T("Error while starting service"), MB_OK);
//error occured
}
return 0;
}
}
CloseServiceHandle(hService);
}
CloseServiceHandle(hScm);
}
else
{
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
lpCmdLine--;
return CompatMain(lpCmdLine);
}
}
if (!bInstalled)
{
if (nAction==1 || nAction==5 || (nAction == 0 && MessageBox(0, _T("Install Service?"), _T("Question"), MB_YESNO|MB_ICONQUESTION)==IDYES))
{
hScm=OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
if(!hScm)
{
return 1;
}
int nStartMode = (nAction==5)?SERVICE_AUTO_START:SERVICE_DEMAND_START;
if (!nAction)
if (MessageBox(0, _T("Autostart service?"), _T("Question"), MB_YESNO|MB_ICONQUESTION)==IDYES)
nStartMode = SERVICE_AUTO_START;
TCHAR buffer[MAX_PATH + 3];
buffer[0] = '"';
DWORD written = GetModuleFileName(0, buffer + 1, MAX_PATH);
if (!written)
{
CloseServiceHandle(hScm);
MessageBox(0, _T("Failed to get own executable path"), _T("Could not install server"), MB_ICONSTOP);
return 1;
}
buffer[written + 1] = '"';
buffer[written + 2] = 0;
hService=CreateService(hScm, ServiceName,
ServiceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS, nStartMode,
SERVICE_ERROR_NORMAL,
buffer,
0, 0, 0, 0, 0);
if(!hService)
{
CloseServiceHandle(hScm);
return 1;
}
CloseServiceHandle(hService);
CloseServiceHandle(hScm);
dwCurrentState = SERVICE_STOPPED;
}
else
return 0;
}
if (dwCurrentState == SERVICE_STOPPED && (nAction==3 || (nAction == 0 && MessageBox(0, _T("Start server?"), _T("Question"), MB_YESNO|MB_ICONQUESTION)==IDYES)))
{
SC_HANDLE hService,hScm;
hScm=OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
if(!hScm)
{
return 1;
}
hService=OpenService(hScm, ServiceName, SERVICE_ALL_ACCESS);
if(!hService)
{
CloseServiceHandle(hScm);
return 1;
}
StartService(hService, 0, NULL);
CloseServiceHandle(hService);
CloseServiceHandle(hScm);
return 0;
}
if (dwCurrentState == SERVICE_STOPPED && (nAction==2 || (nAction == 0 && MessageBox(0, _T("Uninstall Service?"), _T("Question"), MB_YESNO|MB_ICONQUESTION)==IDYES)))
{
SC_HANDLE hService,hScm;
hScm=OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
if(!hScm)
{
return 1;
}
hService=OpenService(hScm, ServiceName, SERVICE_ALL_ACCESS);
if(!hService)
{
CloseServiceHandle(hScm);
return 1;
}
DeleteService(hService);
CloseServiceHandle(hService);
CloseServiceHandle(hScm);
return 0;
}
if (dwCurrentState != SERVICE_STOPPED && (nAction==4 || (nAction == 0 && MessageBox(0, _T("Stop Server?"), _T("Question"), MB_YESNO|MB_ICONQUESTION)==IDYES)))
{
SC_HANDLE hService,hScm;
hScm=OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
if(!hScm)
{
return 1;
}
hService=OpenService(hScm, ServiceName, SERVICE_ALL_ACCESS);
if(!hService)
{
CloseServiceHandle(hScm);
return 1;
}
SERVICE_STATUS status;
ControlService(hService, SERVICE_CONTROL_STOP, &status);
CloseServiceHandle(hService);
CloseServiceHandle(hScm);
return 0;
}
if (dwCurrentState == SERVICE_STOPPED)
return 0;
return 0;
}
void ServiceMain(DWORD argc, LPTSTR *argv)
{
LoadServiceName();
BOOL success;
nServiceStatusHandle = RegisterServiceCtrlHandler(ServiceName,
(LPHANDLER_FUNCTION)ServiceCtrlHandler);
if (!nServiceStatusHandle)
return;
success = UpdateServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 3000);
if (!success)
return;
killServiceEvent = CreateEvent(0, TRUE, FALSE, 0);
if (killServiceEvent == NULL)
return;
success = UpdateServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, 2, 1000);
if (!success)
return;
success = StartServiceThread();
if (!success)
return;
nServiceCurrentStatus = SERVICE_RUNNING;
success = UpdateServiceStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
if (!success)
return;
WaitForSingleObject(killServiceEvent, INFINITE);
CloseHandle(killServiceEvent);
WaitForSingleObject(hServiceThread, INFINITE);
CloseHandle(hServiceThread);
UpdateServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);
}
BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
DWORD dwWaitHint)
{
BOOL success;
SERVICE_STATUS nServiceStatus;
nServiceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
nServiceStatus.dwCurrentState=dwCurrentState;
if(dwCurrentState==SERVICE_START_PENDING)
{
nServiceStatus.dwControlsAccepted=0;
}
else
{
nServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP
|SERVICE_ACCEPT_SHUTDOWN;
}
if(dwServiceSpecificExitCode==0)
{
nServiceStatus.dwWin32ExitCode=dwWin32ExitCode;
}
else
{
nServiceStatus.dwWin32ExitCode=ERROR_SERVICE_SPECIFIC_ERROR;
}
nServiceStatus.dwServiceSpecificExitCode=dwServiceSpecificExitCode;
nServiceStatus.dwCheckPoint=dwCheckPoint;
nServiceStatus.dwWaitHint=dwWaitHint;
success=SetServiceStatus(nServiceStatusHandle,&nServiceStatus);
if(!success)
{
KillService();
return success;
}
else
return success;
}
BOOL StartServiceThread()
{
DWORD id;
hServiceThread=CreateThread(0,0,
(LPTHREAD_START_ROUTINE)ServiceExecutionThread,
0,0,&id);
if(hServiceThread==0)
{
return false;
}
else
{
nServiceRunning=true;
return true;
}
}
void KillService()
{
if (hMainWnd)
PostMessage(hMainWnd, WM_CLOSE, 0, 0);
nServiceRunning = false;
}
static BOOL CALLBACK SendReloadConfigProc(HWND hwnd, LPARAM lParam)
{
int* res = (int*)lParam;
TCHAR buffer[100];
if (!GetClassName(hwnd, buffer, 100))
return TRUE;
if (_tcscmp(buffer, _T("FileZilla Server Helper Window")))
return TRUE;
if (!GetWindowText(hwnd, buffer, 100))
return TRUE;
if (_tcscmp(buffer, _T("FileZilla Server Helper Window")))
return TRUE;
PostMessage(hwnd, WM_FILEZILLA_RELOADCONFIG, 0, 0);
*res = 0;
return TRUE;
}
int SendReloadConfig()
{
int res = 1;
EnumWindows(SendReloadConfigProc, (LPARAM)&res);
return res;
}
void ServiceCtrlHandler(DWORD nControlCode)
{
BOOL success;
switch(nControlCode)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
nServiceCurrentStatus=SERVICE_STOP_PENDING;
success=UpdateServiceStatus(SERVICE_STOP_PENDING,NO_ERROR,0,1,3000);
KillService();
return;
case 128:
SendReloadConfig();
break;
default:
break;
}
UpdateServiceStatus(nServiceCurrentStatus,NO_ERROR,0,0,0);
}
DWORD ServiceExecutionThread(LPDWORD param)
{
// initialize Winsock library
BOOL res=TRUE;
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1, 1);
int nResult = WSAStartup(wVersionRequested, &wsaData);
if (nResult != 0)
res=FALSE;
else if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup();
res=FALSE;
}
if(!res)
{
SetEvent(killServiceEvent);
UpdateServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);
return 0;
}
CServer *pServer = new CServer;
VERIFY(pServer->Create());
if (!nServiceRunning)
PostQuitMessage(0);
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
delete pServer;
WSACleanup();
SetEvent(killServiceEvent);
return 0;
}
int SetAdminPort(int nAdminPort)
{
if (nAdminPort < 1 || nAdminPort > 65535)
return 1;
COptions *pOptions = new COptions();
pOptions->SetOption(OPTION_ADMINPORT, nAdminPort);
delete pOptions;
pOptions = new COptions();
if (pOptions->GetOptionVal(OPTION_ADMINPORT) != nAdminPort)
{
delete pOptions;
return 1;
}
delete pOptions;
return 0;
}
int ReloadConfig()
{
int res = SendReloadConfig();
SC_HANDLE hService, hScm;
hScm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
if (hScm)
{
hService = OpenService(hScm, ServiceName, SERVICE_USER_DEFINED_CONTROL);
if (hService)
{
SERVICE_STATUS status;
res |= ControlService(hService, 128, &status) == 0;
CloseServiceHandle(hService);
}
CloseServiceHandle(hScm);
}
return !res;
}
int CompatMain(LPCSTR lpCmdLine)
{
int nAction = 0;
if (lpCmdLine[0] == '/' || lpCmdLine[0] == '-')
{
lpCmdLine++;
if (!strcmp(lpCmdLine, "start"))
nAction = 1;
else if (!strcmp(lpCmdLine, "stop"))
nAction = 2;
else if (strlen(lpCmdLine) >= 10 && !strncmp(lpCmdLine, "adminport ", 10))
nAction = 3;
else if (!strcmp(lpCmdLine, "install"))
return 0;
else if (!strcmp(lpCmdLine, "uninstall"))
return 0;
else if (!strcmp(lpCmdLine, "install auto"))
return 0;
else if (!strcmp(lpCmdLine, "reload-config"))
nAction = 4;
}
if (nAction == 3)
return SetAdminPort(atoi(lpCmdLine + 10));
else if (nAction == 4)
return ReloadConfig();
HWND hWnd = FindWindow(_T("FileZilla Server Helper Window"), _T("FileZilla Server Helper Window"));
if (nAction == 1 && hWnd)
return 0;
else if (nAction==2 && !hWnd)
return 0;
if (!hWnd && (nAction == 1 || (nAction == 0 && MessageBox(0, _T("Start Server?"), _T("Question"), MB_YESNO|MB_ICONQUESTION)==IDYES)))
{
// initialize Winsock library
BOOL res=TRUE;
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1, 1);
int nResult = WSAStartup(wVersionRequested, &wsaData);
if (nResult != 0)
res=FALSE;
else if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup();
res=FALSE;
}
if(!res)
{
return 1;
}
CServer *pServer = new CServer;
VERIFY(pServer->Create());
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
delete pServer;
WSACleanup();
return 0;
}
else if (hWnd && (nAction == 2 || (nAction == 0 && MessageBox(0, _T("Stop Server?"), _T("Question"), MB_YESNO|MB_ICONQUESTION)==IDYES)))
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
if (GetLastError())
return 1;
else
return 0;
}
return 1;
}
|