38 #define SERVICE_SDDL \
39 "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)" \
40 "(A;;CCLCSWLORC;;;IU)(A;;CCLCSWLORC;;;SU)"
43 static bool SCServiceAppendChar(
char *path,
size_t size,
size_t *
len,
char c)
45 if (size == 0 || *
len >= size - 1) {
58 static bool SCServiceAppendArgument(
char *path,
size_t size,
size_t *
len,
const char *arg)
60 if (!SCServiceAppendChar(path, size,
len,
'"')) {
63 while (*arg !=
'\0') {
64 size_t backslashes = 0;
65 while (*arg ==
'\\') {
69 for (
size_t i = 0; i < backslashes; i++) {
70 if (!SCServiceAppendChar(path, size,
len,
'\\')) {
73 if ((*arg ==
'"' || *arg ==
'\0') && !SCServiceAppendChar(path, size,
len,
'\\')) {
80 if (*arg ==
'"' && !SCServiceAppendChar(path, size,
len,
'\\')) {
83 if (!SCServiceAppendChar(path, size,
len, *arg++)) {
87 return SCServiceAppendChar(path, size,
len,
'"');
91 static bool SCServiceBuildCommandLine(
char *path,
size_t size,
const char *module,
int argc,
92 const char *
const *argv,
const char *service_option)
99 if (!SCServiceAppendArgument(path, size, &
len, module)) {
102 for (
int i = 1; i < argc; i++) {
104 if (strlen(argv[i]) <= strlen(service_option) &&
105 strncmp(service_option, argv[i], strlen(argv[i])) == 0) {
108 if (!SCServiceAppendChar(path, size, &
len,
' ') ||
109 !SCServiceAppendArgument(path, size, &
len, argv[i])) {
117 static bool SCServiceGetCommandLine(
118 char *path,
size_t size,
int argc,
char **argv,
const char *service_option)
121 DWORD
len = GetModuleFileName(NULL, module,
sizeof(module));
123 SCLogError(
"Can't get path to service binary: %d", (
int)GetLastError());
126 if (
len >=
sizeof(module)) {
127 SCLogError(
"failed to construct service path string: binary path truncated");
130 if (!SCServiceBuildCommandLine(
131 path, size, module, argc, (
const char *
const *)argv, service_option)) {
132 SCLogError(
"failed to construct service path string: invalid or truncated command line");
138 static SERVICE_STATUS_HANDLE service_status_handle = 0;
143 static int service_argc = 0;
145 static char **service_argv = NULL;
147 static int service_initialized = 0;
149 int main(
int argc,
char **argv);
154 int SCRunningAsService(
void)
156 HANDLE h = INVALID_HANDLE_VALUE;
157 if ((h = CreateFile(
"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
169 static void SCAtExitHandler(
void)
171 SERVICE_STATUS status = {
174 SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN,
184 if (!SetServiceStatus(service_status_handle, &status)) {
185 SCLogWarning(
"Can't set service status: %d", (
int)GetLastError());
187 SCLogInfo(
"Service status set to: SERVICE_STOPPED");
196 uint32_t SCServiceTakeRequests(
void)
204 static DWORD WINAPI SCServiceCtrlHandlerEx(DWORD code, DWORD etype, LPVOID edata, LPVOID context)
206 if (code == SC_SERVICE_CONTROL_RELOAD_RULES) {
208 SC_ATOMIC_OR(service_requests, SC_SERVICE_REQUEST_RELOAD_RULES);
212 if (code == SC_SERVICE_CONTROL_REOPEN_LOG_FILES) {
214 SC_ATOMIC_OR(service_requests, SC_SERVICE_REQUEST_REOPEN_LOG_FILES);
218 if (code == SERVICE_CONTROL_SHUTDOWN || code == SERVICE_CONTROL_STOP) {
219 SERVICE_STATUS status = {
221 SERVICE_STOP_PENDING,
222 SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN,
229 SCLogInfo(
"Service control handler called with %s control code.",
230 ((code == SERVICE_CONTROL_SHUTDOWN) ? (
"SERVICE_CONTROL_SHUTDOWN") : (
"SERVICE_CONTROL_STOP")));
233 if (!SetServiceStatus(service_status_handle, &status)) {
234 SCLogWarning(
"Can't set service status: %d", (
int)GetLastError());
236 SCLogInfo(
"Service status set to: SERVICE_STOP_PENDING");
245 return ERROR_CALL_NOT_IMPLEMENTED;
251 static void WINAPI SCServiceMain(uint32_t argc,
char** argv)
253 SERVICE_STATUS status = {
256 SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN,
263 if ((service_status_handle = RegisterServiceCtrlHandlerEx((
char *)
PROG_NAME, SCServiceCtrlHandlerEx, NULL)) == (SERVICE_STATUS_HANDLE)0) {
264 SCLogError(
"Can't register service control handler: %d", (
int)GetLastError());
269 if (atexit(SCAtExitHandler)) {
270 SCLogWarning(
"Can't register exit handler: %d", (
int)GetLastError());
274 if (!SetServiceStatus(service_status_handle, &status)) {
275 SCLogWarning(
"Can't set service status: %d", (
int)GetLastError());
277 SCLogInfo(
"Service status set to: SERVICE_RUNNING");
283 main(service_argc, service_argv);
288 status.dwCurrentState = SERVICE_STOPPED;
290 if (!SetServiceStatus(service_status_handle, &status)) {
291 SCLogWarning(
"Can't set service status: %d", (
int)GetLastError());
293 SCLogInfo(
"Service status set to: SERVICE_STOPPED");
303 int SCServiceInit(
int argc,
char **argv)
305 SERVICE_TABLE_ENTRY DispatchTable[] = {
306 {(
char *)
PROG_NAME, (LPSERVICE_MAIN_FUNCTION) SCServiceMain},
311 if (service_initialized) {
320 service_initialized = 1;
322 SCLogInfo(
"Entering service control dispatcher...");
324 if (!StartServiceCtrlDispatcher(DispatchTable)) {
329 SCLogInfo(
"Leaving service control dispatcher.");
342 static int SCServiceSetSecurity(SC_HANDLE service)
344 PSECURITY_DESCRIPTOR sd = NULL;
347 if (!ConvertStringSecurityDescriptorToSecurityDescriptorA(
348 SERVICE_SDDL, SDDL_REVISION_1, &sd, NULL)) {
349 SCLogError(
"Can't create service security descriptor: %d", (
int)GetLastError());
353 if (!SetServiceObjectSecurity(service, DACL_SECURITY_INFORMATION, sd)) {
354 SCLogError(
"Can't set service security descriptor: %d", (
int)GetLastError());
368 int SCServiceInstall(
int argc,
char **argv)
371 SC_HANDLE service = NULL;
372 SC_HANDLE scm = NULL;
376 if (!SCServiceGetCommandLine(path,
sizeof(path), argc, argv,
"--service-install")) {
380 if ((scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL) {
381 SCLogError(
"Can't open SCM: %d", (
int)GetLastError());
385 service = CreateService(
390 SERVICE_WIN32_OWN_PROCESS,
391 SERVICE_DEMAND_START,
392 SERVICE_ERROR_NORMAL,
400 if (service == NULL) {
401 SCLogError(
"Can't create service: %d", (
int)GetLastError());
405 if (SCServiceSetSecurity(service) != 0) {
406 DeleteService(service);
415 CloseServiceHandle(service);
419 CloseServiceHandle(scm);
431 int SCServiceRemove(
void)
433 SERVICE_STATUS status;
434 SC_HANDLE service = NULL;
435 SC_HANDLE scm = NULL;
439 if ((scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL) {
440 SCLogError(
"Can't open SCM: %d", (
int)GetLastError());
444 if ((service = OpenService(scm,
PROG_NAME, SERVICE_ALL_ACCESS)) == NULL) {
445 SCLogError(
"Can't open service: %d", (
int)GetLastError());
449 if (!QueryServiceStatus(service, &status)) {
450 SCLogError(
"Can't query service status: %d", (
int)GetLastError());
454 if (status.dwCurrentState != SERVICE_STOPPED) {
455 SCLogError(
"Service isn't in stopped state: %d", (
int)GetLastError());
459 if (!DeleteService(service)) {
460 SCLogError(
"Can't delete service: %d", (
int)GetLastError());
469 CloseServiceHandle(service);
473 CloseServiceHandle(scm);
485 int SCServiceChangeParams(
int argc,
char **argv)
488 SC_HANDLE service = NULL;
489 SC_HANDLE scm = NULL;
493 if (!SCServiceGetCommandLine(path,
sizeof(path), argc, argv,
"--service-change-params")) {
497 if ((scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL) {
498 SCLogError(
"Can't open SCM: %d", (
int)GetLastError());
502 if ((service = OpenService(scm,
PROG_NAME, SERVICE_ALL_ACCESS)) == NULL) {
503 SCLogError(
"Can't open service: %d", (
int)GetLastError());
507 if (!ChangeServiceConfig(
509 SERVICE_WIN32_OWN_PROCESS,
510 SERVICE_DEMAND_START,
511 SERVICE_ERROR_NORMAL,
520 SCLogError(
"Can't change service configuration: %d", (
int)GetLastError());