aboutsummaryrefslogtreecommitdiff
path: root/src/shared/ServiceWin32.cpp
diff options
context:
space:
mode:
authorNeo2003 <none@none>2008-10-02 16:23:55 -0500
committerNeo2003 <none@none>2008-10-02 16:23:55 -0500
commit9b1c0e006f20091f28f3f468cfcab1feb51286bd (patch)
treeb5d1ba94a656e6679f8737f9ea6bed1239b73b14 /src/shared/ServiceWin32.cpp
[svn] * Proper SVN structureinit
--HG-- branch : trunk
Diffstat (limited to 'src/shared/ServiceWin32.cpp')
-rw-r--r--src/shared/ServiceWin32.cpp260
1 files changed, 260 insertions, 0 deletions
diff --git a/src/shared/ServiceWin32.cpp b/src/shared/ServiceWin32.cpp
new file mode 100644
index 00000000000..d95cfe90291
--- /dev/null
+++ b/src/shared/ServiceWin32.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ *
+ * 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.
+ */
+
+#ifdef WIN32
+
+#include "Common.h"
+#include "Log.h"
+#include <cstring>
+#include <windows.h>
+#include <winsvc.h>
+
+#if !defined(WINADVAPI)
+#if !defined(_ADVAPI32_)
+#define WINADVAPI DECLSPEC_IMPORT
+#else
+#define WINADVAPI
+#endif
+#endif
+
+extern int main(int argc, char ** argv);
+extern char serviceLongName[];
+extern char serviceName[];
+extern char serviceDescription[];
+
+extern int m_ServiceStatus;
+
+SERVICE_STATUS serviceStatus;
+
+SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
+
+typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID);
+
+bool WinServiceInstall()
+{
+ CSD_T ChangeService_Config2;
+ HMODULE advapi32;
+ SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
+
+ if (serviceControlManager)
+ {
+ char path[_MAX_PATH + 10];
+ if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0)
+ {
+ SC_HANDLE service;
+ std::strcat(path, " --service");
+ service = CreateService(serviceControlManager,
+ serviceName, // name of service
+ serviceLongName, // service name to display
+ SERVICE_ALL_ACCESS, // desired access
+ // service type
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_AUTO_START, // start type
+ SERVICE_ERROR_IGNORE, // error control type
+ path, // service's binary
+ 0, // no load ordering group
+ 0, // no tag identifier
+ 0, // no dependencies
+ 0, // LocalSystem account
+ 0); // no password
+ if (service)
+ {
+ advapi32 = GetModuleHandle("ADVAPI32.DLL");
+ if(!advapi32)
+ {
+ CloseServiceHandle(service);
+ CloseServiceHandle(serviceControlManager);
+ return false;
+ }
+
+ ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A");
+ if (!ChangeService_Config2)
+ {
+ CloseServiceHandle(service);
+ CloseServiceHandle(serviceControlManager);
+ return false;
+ }
+
+ SERVICE_DESCRIPTION sdBuf;
+ sdBuf.lpDescription = serviceDescription;
+ ChangeService_Config2(
+ service, // handle to service
+ SERVICE_CONFIG_DESCRIPTION, // change: description
+ &sdBuf); // new data
+
+ SC_ACTION _action[1];
+ _action[0].Type = SC_ACTION_RESTART;
+ _action[0].Delay = 10000;
+ SERVICE_FAILURE_ACTIONS sfa;
+ ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS));
+ sfa.lpsaActions = _action;
+ sfa.cActions = 1;
+ sfa.dwResetPeriod =INFINITE;
+ ChangeService_Config2(
+ service, // handle to service
+ SERVICE_CONFIG_FAILURE_ACTIONS, // information level
+ &sfa); // new data
+
+ CloseServiceHandle(service);
+
+ }
+ }
+ CloseServiceHandle(serviceControlManager);
+ }
+ return true;
+}
+
+bool WinServiceUninstall()
+{
+ SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
+
+ if (serviceControlManager)
+ {
+ SC_HANDLE service = OpenService(serviceControlManager,
+ serviceName, SERVICE_QUERY_STATUS | DELETE);
+ if (service)
+ {
+ SERVICE_STATUS serviceStatus;
+ if (QueryServiceStatus(service, &serviceStatus))
+ {
+ if (serviceStatus.dwCurrentState == SERVICE_STOPPED)
+ DeleteService(service);
+ }
+ CloseServiceHandle(service);
+ }
+
+ CloseServiceHandle(serviceControlManager);
+ }
+ return true;
+}
+
+void WINAPI ServiceControlHandler(DWORD controlCode)
+{
+ switch (controlCode)
+ {
+ case SERVICE_CONTROL_INTERROGATE:
+ break;
+
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+
+ m_ServiceStatus = 0;
+ return;
+
+ case SERVICE_CONTROL_PAUSE:
+ m_ServiceStatus = 2;
+ serviceStatus.dwCurrentState = SERVICE_PAUSED;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+ break;
+
+ case SERVICE_CONTROL_CONTINUE:
+ serviceStatus.dwCurrentState = SERVICE_RUNNING;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+ m_ServiceStatus = 1;
+ break;
+
+ default:
+ if ( controlCode >= 128 && controlCode <= 255 )
+ // user defined control code
+ break;
+ else
+ // unrecognized control code
+ break;
+ }
+
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+}
+
+void WINAPI ServiceMain(DWORD argc, char *argv[])
+{
+ // initialise service status
+ serviceStatus.dwServiceType = SERVICE_WIN32;
+ serviceStatus.dwCurrentState = SERVICE_START_PENDING;
+ serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
+ serviceStatus.dwWin32ExitCode = NO_ERROR;
+ serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
+ serviceStatus.dwCheckPoint = 0;
+ serviceStatus.dwWaitHint = 0;
+
+ serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler);
+
+ if ( serviceStatusHandle )
+ {
+ char path[_MAX_PATH + 1];
+ unsigned int i, last_slash = 0;
+
+ GetModuleFileName(0, path, sizeof(path)/sizeof(path[0]));
+
+ for (i = 0; i < std::strlen(path); i++)
+ {
+ if (path[i] == '\\') last_slash = i;
+ }
+
+ path[last_slash] = 0;
+
+ // service is starting
+ serviceStatus.dwCurrentState = SERVICE_START_PENDING;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+
+ // do initialisation here
+ SetCurrentDirectory(path);
+
+ // running
+ serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
+ serviceStatus.dwCurrentState = SERVICE_RUNNING;
+ SetServiceStatus( serviceStatusHandle, &serviceStatus );
+
+ ////////////////////////
+ // service main cycle //
+ ////////////////////////
+
+ m_ServiceStatus = 1;
+ argc = 1;
+ main(argc , argv);
+
+ // service was stopped
+ serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+
+ // do cleanup here
+
+ // service is now stopped
+ serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
+ serviceStatus.dwCurrentState = SERVICE_STOPPED;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+ }
+}
+
+bool WinServiceRun()
+{
+ SERVICE_TABLE_ENTRY serviceTable[] =
+ {
+ { serviceName, ServiceMain },
+ { 0, 0 }
+ };
+
+ if (!StartServiceCtrlDispatcher(serviceTable))
+ {
+ sLog.outError("StartService Failed. Error [%u]", ::GetLastError());
+ return false;
+ }
+ return true;
+}
+#endif