+/* Set default values which aren't zero. */\r
+void set_nssm_service_defaults(nssm_service_t *service) {\r
+ if (! service) return;\r
+\r
+ service->stdin_sharing = NSSM_STDIN_SHARING;\r
+ service->stdin_disposition = NSSM_STDIN_DISPOSITION;\r
+ service->stdin_flags = NSSM_STDIN_FLAGS;\r
+ service->stdout_sharing = NSSM_STDOUT_SHARING;\r
+ service->stdout_disposition = NSSM_STDOUT_DISPOSITION;\r
+ service->stdout_flags = NSSM_STDOUT_FLAGS;\r
+ service->stderr_sharing = NSSM_STDERR_SHARING;\r
+ service->stderr_disposition = NSSM_STDERR_DISPOSITION;\r
+ service->stderr_flags = NSSM_STDERR_FLAGS;\r
+ service->throttle_delay = NSSM_RESET_THROTTLE_RESTART;\r
+ service->stop_method = ~0;\r
+ service->kill_console_delay = NSSM_KILL_CONSOLE_GRACE_PERIOD;\r
+ service->kill_window_delay = NSSM_KILL_WINDOW_GRACE_PERIOD;\r
+ service->kill_threads_delay = NSSM_KILL_THREADS_GRACE_PERIOD;\r
+}\r
+\r
+/* Allocate and zero memory for a service. */\r
+nssm_service_t *alloc_nssm_service() {\r
+ nssm_service_t *service = (nssm_service_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(nssm_service_t));\r
+ if (! service) log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "service", "alloc_nssm_service()", 0);\r
+ return service;\r
+}\r
+\r
+/* Free memory for a service. */\r
+void cleanup_nssm_service(nssm_service_t *service) {\r
+ if (! service) return;\r
+ if (service->env) HeapFree(GetProcessHeap(), 0, service->env);\r
+ if (service->env_extra) HeapFree(GetProcessHeap(), 0, service->env_extra);\r
+ if (service->handle) CloseServiceHandle(service->handle);\r
+ if (service->process_handle) CloseHandle(service->process_handle);\r
+ if (service->wait_handle) UnregisterWait(service->process_handle);\r
+ if (service->throttle_section_initialised) DeleteCriticalSection(&service->throttle_section);\r
+ if (service->throttle_timer) CloseHandle(service->throttle_timer);\r
+ HeapFree(GetProcessHeap(), 0, service);\r
+}\r
+\r
+/* About to install the service */\r
+int pre_install_service(int argc, char **argv) {\r
+ /* Show the dialogue box if we didn't give the service name and path */\r
+ if (argc < 2) return nssm_gui(IDD_INSTALL, argv[0]);\r
+\r
+ nssm_service_t *service = alloc_nssm_service();\r
+ if (! service) {\r
+ print_message(stderr, NSSM_EVENT_OUT_OF_MEMORY, "service", "pre_install_service()");\r
+ return 1;\r
+ }\r
+\r
+ set_nssm_service_defaults(service);\r
+ memmove(service->name, argv[0], strlen(argv[0]));\r
+ memmove(service->exe, argv[1], strlen(argv[1]));\r
+\r
+ /* Arguments are optional */\r
+ size_t flagslen = 0;\r
+ size_t s = 0;\r
+ int i;\r
+ for (i = 2; i < argc; i++) flagslen += strlen(argv[i]) + 1;\r
+ if (! flagslen) flagslen = 1;\r
+\r
+ /*\r
+ This probably isn't UTF8-safe and should use std::string or something\r
+ but it's been broken for the best part of a decade and due for a rewrite\r
+ anyway so it'll do as a quick-'n'-dirty fix. Note that we don't free\r
+ the flags buffer but as the program exits that isn't a big problem.\r
+ */\r
+ for (i = 2; i < argc; i++) {\r
+ size_t len = strlen(argv[i]);\r
+ memmove(service->flags + s, argv[i], len);\r
+ s += len;\r
+ if (i < argc - 1) service->flags[s++] = ' ';\r
+ }\r
+\r
+ /* Work out directory name */\r
+ memmove(service->dir, service->exe, sizeof(service->dir));\r
+ strip_basename(service->dir);\r
+\r
+ int ret = install_service(service);\r
+ cleanup_nssm_service(service);\r
+ return ret;\r
+}\r
+\r
+/* About to remove the service */\r
+int pre_remove_service(int argc, char **argv) {\r
+ /* Show dialogue box if we didn't pass service name and "confirm" */\r
+ if (argc < 2) return nssm_gui(IDD_REMOVE, argv[0]);\r
+ if (str_equiv(argv[1], "confirm")) {\r
+ nssm_service_t *service = alloc_nssm_service();\r
+ memmove(service->name, argv[0], strlen(argv[0]));\r
+ int ret = remove_service(service);\r
+ cleanup_nssm_service(service);\r
+ return ret;\r
+ }\r
+ print_message(stderr, NSSM_MESSAGE_PRE_REMOVE_SERVICE);\r
+ return 100;\r
+}\r
+\r