\r
unsigned long bufsize, required, count, i;\r
unsigned long resume = 0;\r
- EnumServicesStatus(services, SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, 0, 0, &required, &count, &resume);\r
+ EnumServicesStatusEx(services, SC_ENUM_PROCESS_INFO, SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, 0, 0, &required, &count, &resume, 0);\r
error = GetLastError();\r
if (error != ERROR_MORE_DATA) {\r
print_message(stderr, NSSM_MESSAGE_ENUMSERVICESSTATUS_FAILED, error_string(GetLastError()));\r
return 0;\r
}\r
\r
- ENUM_SERVICE_STATUS *status = (ENUM_SERVICE_STATUS *) HeapAlloc(GetProcessHeap(), 0, required);\r
+ ENUM_SERVICE_STATUS_PROCESS *status = (ENUM_SERVICE_STATUS_PROCESS *) HeapAlloc(GetProcessHeap(), 0, required);\r
if (! status) {\r
- print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("ENUM_SERVICE_STATUS"), _T("open_service()"));\r
+ print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("ENUM_SERVICE_STATUS_PROCESS"), _T("open_service()"));\r
return 0;\r
}\r
\r
bufsize = required;\r
while (true) {\r
/*\r
- EnumServicesStatus() returns:\r
+ EnumServicesStatusEx() returns:\r
1 when it retrieved data and there's no more data to come.\r
0 and sets last error to ERROR_MORE_DATA when it retrieved data and\r
there's more data to come.\r
0 and sets last error to something else on error.\r
*/\r
- int ret = EnumServicesStatus(services, SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, status, bufsize, &required, &count, &resume);\r
+ int ret = EnumServicesStatusEx(services, SC_ENUM_PROCESS_INFO, SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE) status, bufsize, &required, &count, &resume, 0);\r
if (! ret) {\r
error = GetLastError();\r
if (error != ERROR_MORE_DATA) {\r
}\r
\r
/* Control a service. */\r
-int control_service(unsigned long control, int argc, TCHAR **argv) {\r
+int control_service(unsigned long control, int argc, TCHAR **argv, bool return_status) {\r
if (argc < 1) return usage(1);\r
TCHAR *service_name = argv[0];\r
TCHAR canonical_name[SERVICE_NAME_LENGTH];\r
SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);\r
if (! services) {\r
print_message(stderr, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);\r
+ if (return_status) return 0;\r
return 2;\r
}\r
\r
SC_HANDLE service_handle = open_service(services, service_name, access, canonical_name, _countof(canonical_name));\r
if (! service_handle) {\r
CloseServiceHandle(services);\r
+ if (return_status) return 0;\r
return 3;\r
}\r
\r
\r
if (response) {\r
print_message(stderr, NSSM_MESSAGE_BAD_CONTROL_RESPONSE, canonical_name, service_status_text(service_status.dwCurrentState), service_control_text(control));\r
+ if (return_status) return 0;\r
return 1;\r
}\r
else _tprintf(_T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error));\r
else {\r
CloseServiceHandle(service_handle);\r
_ftprintf(stderr, _T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error));\r
+ if (return_status) return 0;\r
return 1;\r
}\r
}\r
\r
if (ret) {\r
_tprintf(_T("%s\n"), service_status_text(service_status.dwCurrentState));\r
+ if (return_status) return service_status.dwCurrentState;\r
return 0;\r
}\r
else {\r
_ftprintf(stderr, _T("%s: %s\n"), canonical_name, error_string(error));\r
+ if (return_status) return 0;\r
return 1;\r
}\r
}\r
\r
if (response) {\r
print_message(stderr, NSSM_MESSAGE_BAD_CONTROL_RESPONSE, canonical_name, service_status_text(service_status.dwCurrentState), service_control_text(control));\r
+ if (return_status) return 0;\r
return 1;\r
}\r
else _tprintf(_T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error));\r
+ if (return_status) return service_status.dwCurrentState;\r
return 0;\r
}\r
else {\r
CloseServiceHandle(service_handle);\r
_ftprintf(stderr, _T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error));\r
if (error == ERROR_SERVICE_NOT_ACTIVE) {\r
- if (control == SERVICE_CONTROL_SHUTDOWN || control == SERVICE_CONTROL_STOP) return 0;\r
+ if (control == SERVICE_CONTROL_SHUTDOWN || control == SERVICE_CONTROL_STOP) {\r
+ if (return_status) return SERVICE_STOPPED;\r
+ return 0;\r
+ }\r
}\r
+ if (return_status) return 0;\r
return 1;\r
}\r
}\r
}\r
\r
+int control_service(unsigned long control, int argc, TCHAR **argv) {\r
+ return control_service(control, argc, argv, false);\r
+}\r
+\r
/* Remove the service */\r
int remove_service(nssm_service_t *service) {\r
if (! service) return 1;\r
/* Set up I/O redirection. */\r
if (get_output_handles(service, &si)) {\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_OUTPUT_HANDLES_FAILED, service->name, 0);\r
- if (! service->no_console) FreeConsole();\r
+ FreeConsole();\r
close_output_handles(&si);\r
unset_service_environment(service);\r
return stop_service(service, 4, true, true);\r
}\r
+ FreeConsole();\r
\r
/* Pre-start hook. May need I/O to have been redirected already. */\r
if (nssm_hook(&hook_threads, service, NSSM_HOOK_EVENT_START, NSSM_HOOK_ACTION_PRE, &control, NSSM_SERVICE_STATUS_DEADLINE, false) == NSSM_HOOK_STATUS_ABORT) {\r
if (si.dwFlags & STARTF_USESTDHANDLES) inherit_handles = true;\r
unsigned long flags = service->priority & priority_mask();\r
if (service->affinity) flags |= CREATE_SUSPENDED;\r
+ if (! service->no_console) flags |= CREATE_NEW_CONSOLE;\r\r
if (! CreateProcess(0, cmd, 0, 0, inherit_handles, flags, 0, service->dir, &si, &pi)) {\r
unsigned long exitcode = 3;\r
unsigned long error = GetLastError();\r
\r
close_output_handles(&si);\r
\r
- if (! service->no_console) FreeConsole();\r
-\r
if (service->affinity) {\r
/*\r
We are explicitly storing service->affinity as a 64-bit unsigned integer\r
service->exit_count++;\r
(void) nssm_hook(&hook_threads, service, NSSM_HOOK_EVENT_EXIT, NSSM_HOOK_ACTION_POST, NULL, NSSM_HOOK_DEADLINE, true);\r
\r
+ /* Exit logging threads. */\r
+ cleanup_loggers(service);\r
+\r
/*\r
The why argument is true if our wait timed out or false otherwise.\r
Our wait is infinite so why will never be true when called by the system.\r
\r
unsigned long bufsize, required, count, i;\r
unsigned long resume = 0;\r
- EnumServicesStatus(services, SERVICE_WIN32, SERVICE_STATE_ALL, 0, 0, &required, &count, &resume);\r
+ EnumServicesStatusEx(services, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, 0, 0, &required, &count, &resume, 0);\r
unsigned long error = GetLastError();\r
if (error != ERROR_MORE_DATA) {\r
print_message(stderr, NSSM_MESSAGE_ENUMSERVICESSTATUS_FAILED, error_string(GetLastError()));\r
return 2;\r
}\r
\r
- ENUM_SERVICE_STATUS *status = (ENUM_SERVICE_STATUS *) HeapAlloc(GetProcessHeap(), 0, required);\r
+ ENUM_SERVICE_STATUS_PROCESS *status = (ENUM_SERVICE_STATUS_PROCESS *) HeapAlloc(GetProcessHeap(), 0, required);\r
if (! status) {\r
- print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("ENUM_SERVICE_STATUS"), _T("list_nssm_services()"));\r
+ print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("ENUM_SERVICE_STATUS_PROCESS"), _T("list_nssm_services()"));\r
return 3;\r
}\r
\r
bufsize = required;\r
while (true) {\r
- int ret = EnumServicesStatus(services, SERVICE_WIN32, SERVICE_STATE_ALL, status, bufsize, &required, &count, &resume);\r
+ int ret = EnumServicesStatusEx(services, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE) status, bufsize, &required, &count, &resume, 0);\r
if (! ret) {\r
error = GetLastError();\r
if (error != ERROR_MORE_DATA) {\r