version 0.2.14
[fms.git] / src / fmsservice.cpp
1 #include "../include/fmsservice.h"\r
2 #include "../include/global.h"\r
3 #include "../include/logfile.h"\r
4 \r
5 #include <string>\r
6 \r
7 #ifdef _WIN32\r
8 \r
9 #include <direct.h>\r
10 \r
11 #ifdef XMEM\r
12         #include <xmem.h>\r
13 #endif\r
14 \r
15 SERVICE_STATUS ServiceStatus; \r
16 SERVICE_STATUS_HANDLE hStatus; \r
17 \r
18 void ControlHandler(DWORD request) \r
19\r
20     switch(request) \r
21     { \r
22         case SERVICE_CONTROL_STOP: \r
23         case SERVICE_CONTROL_SHUTDOWN: \r
24             ServiceStatus.dwWin32ExitCode = 0; \r
25             ServiceStatus.dwCurrentState  = SERVICE_STOP_PENDING; \r
26                         LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ControlHandler service got shutdown request");\r
27                         wantshutdown=true;\r
28             break; \r
29         \r
30         default:\r
31             break;\r
32     } \r
33  \r
34     /* Report current status */\r
35     SetServiceStatus (hStatus, &ServiceStatus);\r
36  \r
37     return; \r
38 }\r
39 \r
40 BOOL ServiceInstall()\r
41 {\r
42     SC_HANDLE hSCM, hService;\r
43     char szFilePath[FILENAME_MAX], szKey[256];\r
44     HKEY hKey;\r
45     DWORD dwData;\r
46     \r
47     hSCM = OpenSCManager(NULL, /* local machine */\r
48                          NULL, /* ServicesActive database */\r
49                          SC_MANAGER_ALL_ACCESS); /* full access */\r
50 \r
51     if (!hSCM) return FALSE;\r
52 \r
53     GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));\r
54         std::string commandline(szFilePath);\r
55         commandline+=" -s";\r
56 \r
57     hService = CreateService(hSCM,\r
58                              FMS_SERVICE_NAME,\r
59                              FMS_SERVICE_NAME,\r
60                              SERVICE_ALL_ACCESS,\r
61                              SERVICE_WIN32_OWN_PROCESS,\r
62                              SERVICE_AUTO_START, /* start condition */\r
63                              SERVICE_ERROR_NORMAL,\r
64                              commandline.c_str(),\r
65                              NULL,\r
66                              NULL,\r
67                              NULL,\r
68                              NULL,\r
69                              NULL);\r
70 \r
71     if (!hService) {\r
72         CloseServiceHandle(hSCM);\r
73         return FALSE;\r
74     }\r
75 \r
76     hKey = NULL;\r
77     strcpy(szKey, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\");\r
78     strcat(szKey, FMS_SERVICE_NAME);\r
79     if (RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey) != ERROR_SUCCESS) {\r
80         CloseServiceHandle(hService);\r
81         CloseServiceHandle(hSCM);\r
82         return FALSE;\r
83     }\r
84 \r
85     RegSetValueEx(hKey,\r
86                   "EventMessageFile",\r
87                   0,\r
88                   REG_EXPAND_SZ, \r
89                   (CONST BYTE*)szFilePath,\r
90                   (int) strlen(szFilePath) + 1);     \r
91 \r
92     dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;\r
93     RegSetValueEx(hKey,\r
94                   "TypesSupported",\r
95                   0,\r
96                   REG_DWORD,\r
97                   (CONST BYTE*)&dwData,\r
98                   sizeof(DWORD));\r
99     RegCloseKey(hKey);\r
100 \r
101     CloseServiceHandle(hService);\r
102     CloseServiceHandle(hSCM);\r
103 \r
104     return TRUE;\r
105 }\r
106 \r
107 BOOL ServiceIsInstalled()\r
108 {\r
109     BOOL bResult;\r
110     SC_HANDLE hSCM, hService;\r
111     \r
112     hSCM = OpenSCManager(NULL, /* local machine */\r
113                          NULL, /* ServicesActive database */\r
114                          SC_MANAGER_ALL_ACCESS); /* full access */\r
115 \r
116     bResult = FALSE;\r
117 \r
118     if (hSCM) {\r
119         hService = OpenService(hSCM,\r
120                                FMS_SERVICE_NAME,\r
121                                SERVICE_QUERY_CONFIG);\r
122 \r
123         if (hService) {\r
124             bResult = TRUE;\r
125             CloseServiceHandle(hService);\r
126         }\r
127         CloseServiceHandle(hSCM);\r
128     }\r
129 \r
130     return bResult;\r
131 }\r
132 \r
133 void ServiceMain(int argc, char** argv) \r
134\r
135     char szDocumentRoot[MAX_PATH];\r
136 \r
137     ServiceStatus.dwServiceType        = SERVICE_WIN32; \r
138     ServiceStatus.dwCurrentState       = SERVICE_START_PENDING; \r
139     ServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;\r
140     ServiceStatus.dwWin32ExitCode      = 0; \r
141     ServiceStatus.dwServiceSpecificExitCode = 0; \r
142     ServiceStatus.dwCheckPoint         = 0; \r
143     ServiceStatus.dwWaitHint           = 0; \r
144 \r
145     hStatus = RegisterServiceCtrlHandler(FMS_SERVICE_NAME, (LPHANDLER_FUNCTION)ControlHandler);\r
146 \r
147     if (hStatus == (SERVICE_STATUS_HANDLE)0) { \r
148         /* Registering Control Handler failed */\r
149         return; \r
150     }\r
151 \r
152     /* Initialize Service */\r
153 \r
154     /*\r
155      Construct default paths & filenames and make sure we serve documents from the folder containing the executable.\r
156      If left without a default value, we will be serving from C:\WINDOWS\SYSTEM32 (we start there as a service)!\r
157     */\r
158     GetModuleFileName(NULL, szDocumentRoot, MAX_PATH);\r
159         std::string path(szDocumentRoot);\r
160         std::string::size_type slashpos=path.rfind("\\");\r
161         if(slashpos==std::string::npos)\r
162         {\r
163                 slashpos=path.rfind("/");\r
164         }\r
165         if(slashpos!=std::string::npos)\r
166         {\r
167                 path.erase(slashpos);\r
168         }\r
169         chdir(path.c_str());\r
170 \r
171     /* We report the running status to SCM. */\r
172     ServiceStatus.dwCurrentState = SERVICE_RUNNING;\r
173     SetServiceStatus (hStatus, &ServiceStatus);\r
174 \r
175         LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ServiceMain starting service");\r
176 \r
177         MainFunction();\r
178 \r
179         LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ServiceMain stopping service");\r
180 \r
181         ServiceStatus.dwCurrentState=SERVICE_STOPPED;\r
182         SetServiceStatus(hStatus,&ServiceStatus);\r
183 \r
184         LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ServiceMain returning");\r
185 \r
186     return; \r
187 }\r
188 \r
189 BOOL ServiceStart()\r
190 {\r
191     SERVICE_TABLE_ENTRY ServiceTable[2];\r
192 \r
193     ServiceTable[0].lpServiceName = FMS_SERVICE_NAME;\r
194     ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;\r
195 \r
196     ServiceTable[1].lpServiceName = NULL;\r
197     ServiceTable[1].lpServiceProc = NULL;\r
198 \r
199     /* Start the control dispatcher thread for our service */\r
200     return StartServiceCtrlDispatcher(ServiceTable);\r
201 }\r
202 \r
203 BOOL ServiceUninstall()\r
204 {\r
205     SC_HANDLE hSCM, hService;\r
206     BOOL bResult;\r
207     \r
208     hSCM = OpenSCManager(NULL, /* local machine */\r
209                          NULL, /* ServicesActive database */\r
210                          SC_MANAGER_ALL_ACCESS); /* full access */\r
211 \r
212     if (!hSCM) return 0;\r
213 \r
214     bResult = FALSE;\r
215 \r
216     hService = OpenService(hSCM,\r
217                            FMS_SERVICE_NAME,\r
218                            DELETE);\r
219 \r
220     if (hService) {\r
221         if (DeleteService(hService)) bResult = TRUE;\r
222         CloseServiceHandle(hService);\r
223     }\r
224 \r
225     CloseServiceHandle(hSCM);\r
226 \r
227     return bResult;\r
228 }\r
229 \r
230 #endif  // _WIN32\r