X-Git-Url: http://git.iain.cx/?a=blobdiff_plain;f=registry.cpp;h=48783f136b47c4cf22ea8716d9d321fc84c6e7b5;hb=70c205435a839d0378035071777e8c8384008337;hp=c0ba8f1568b8ad5d0d67a928db0d4355a472ce35;hpb=1ca188026d2d0b9a379cc1588eee314ca96528ab;p=nssm.git diff --git a/registry.cpp b/registry.cpp index c0ba8f1..48783f1 100644 --- a/registry.cpp +++ b/registry.cpp @@ -14,24 +14,31 @@ static int service_registry_path(const TCHAR *service_name, bool parameters, con return ret; } -static HKEY open_registry_key(const TCHAR *registry, REGSAM sam, bool must_exist) { - HKEY key; +static long open_registry_key(const TCHAR *registry, REGSAM sam, HKEY *key, bool must_exist) { + long error; if (sam & KEY_SET_VALUE) { - if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, sam, 0, &key, 0) != ERROR_SUCCESS) { + error = RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, sam, 0, key, 0); + if (error != ERROR_SUCCESS) { + *key = 0; log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0); - return 0; + return error; } } else { - long error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, registry, 0, sam, &key); + error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, registry, 0, sam, key); if (error != ERROR_SUCCESS) { - if (error == ERROR_FILE_NOT_FOUND && ! must_exist) return 0; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0); - return 0; + *key = 0; + if (error != ERROR_FILE_NOT_FOUND || must_exist) log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0); } } + return error; +} + +static HKEY open_registry_key(const TCHAR *registry, REGSAM sam, bool must_exist) { + HKEY key; + long error = open_registry_key(registry, sam, &key, must_exist); return key; } @@ -50,7 +57,7 @@ int create_messages() { } /* Get path of this program */ - const TCHAR *path = nssm_imagepath(); + const TCHAR *path = nssm_unquoted_imagepath(); /* Try to register the module but don't worry so much on failure */ RegSetValueEx(key, _T("EventMessageFile"), 0, REG_SZ, (const unsigned char *) path, (unsigned long) (_tcslen(path) + 1) * sizeof(TCHAR)); @@ -60,6 +67,14 @@ int create_messages() { return 0; } +long enumerate_registry_values(HKEY key, unsigned long *index, TCHAR *name, unsigned long namelen) { + unsigned long type; + unsigned long datalen = namelen; + long error = RegEnumValue(key, *index, name, &datalen, 0, &type, 0, 0); + if (error == ERROR_SUCCESS) ++*index; + return error; +} + int create_parameters(nssm_service_t *service, bool editing) { /* Try to open the registry */ HKEY key = open_registry(service->name, KEY_WRITE); @@ -151,6 +166,8 @@ int create_parameters(nssm_service_t *service, bool editing) { if (service->stderr_copy_and_truncate) set_createfile_parameter(key, NSSM_REG_STDERR, NSSM_REG_STDIO_COPY_AND_TRUNCATE, 1); else if (editing) delete_createfile_parameter(key, NSSM_REG_STDERR, NSSM_REG_STDIO_COPY_AND_TRUNCATE); } + if (service->hook_share_output_handles) set_number(key, NSSM_REG_HOOK_SHARE_OUTPUT_HANDLES, 1); + else if (editing) RegDeleteValue(key, NSSM_REG_HOOK_SHARE_OUTPUT_HANDLES); if (service->rotate_files) set_number(key, NSSM_REG_ROTATE, 1); else if (editing) RegDeleteValue(key, NSSM_REG_ROTATE); if (service->rotate_stdout_online) set_number(key, NSSM_REG_ROTATE_ONLINE, 1); @@ -189,7 +206,7 @@ int create_parameters(nssm_service_t *service, bool editing) { int create_exit_action(TCHAR *service_name, const TCHAR *action_string, bool editing) { /* Get registry */ TCHAR registry[KEY_LENGTH]; - if (_sntprintf_s(registry, _countof(registry), _TRUNCATE, NSSM_REGISTRY _T("\\%s"), service_name, NSSM_REG_EXIT) < 0) { + if (service_registry_path(service_name, true, NSSM_REG_EXIT, registry, _countof(registry)) < 0) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("NSSM_REG_EXIT"), _T("create_exit_action()"), 0); return 1; } @@ -223,48 +240,50 @@ int create_exit_action(TCHAR *service_name, const TCHAR *action_string, bool edi int get_environment(TCHAR *service_name, HKEY key, TCHAR *value, TCHAR **env, unsigned long *envlen) { unsigned long type = REG_MULTI_SZ; + unsigned long envsize; + + *envlen = 0; /* Dummy test to find buffer size */ - unsigned long ret = RegQueryValueEx(key, value, 0, &type, NULL, envlen); + unsigned long ret = RegQueryValueEx(key, value, 0, &type, NULL, &envsize); if (ret != ERROR_SUCCESS) { *env = 0; - *envlen = 0; /* The service probably doesn't have any environment configured */ if (ret == ERROR_FILE_NOT_FOUND) return 0; - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(GetLastError()), 0); + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(ret), 0); return 1; } if (type != REG_MULTI_SZ) { - *env = 0; - *envlen = 0; log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_INVALID_ENVIRONMENT_STRING_TYPE, value, service_name, 0); + *env = 0; return 2; } /* Probably not possible */ - if (! *envlen) return 0; + if (! envsize) return 0; /* Previously initialised? */ if (*env) HeapFree(GetProcessHeap(), 0, *env); - *env = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, *envlen); + *env = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, envsize); if (! *env) { - *envlen = 0; log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, value, _T("get_environment()"), 0); return 3; } - /* Actually get the strings */ - ret = RegQueryValueEx(key, value, 0, &type, (unsigned char *) *env, envlen); + /* Actually get the strings. */ + ret = RegQueryValueEx(key, value, 0, &type, (unsigned char *) *env, &envsize); if (ret != ERROR_SUCCESS) { - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(GetLastError()), 0); + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(ret), 0); HeapFree(GetProcessHeap(), 0, *env); *env = 0; - *envlen = 0; return 4; } + /* Value retrieved by RegQueryValueEx() is SIZE not COUNT. */ + *envlen = (unsigned long) environment_length(env); + return 0; } @@ -283,14 +302,13 @@ int get_string(HKEY key, TCHAR *value, TCHAR *data, unsigned long datalen, bool unsigned long ret = RegQueryValueEx(key, value, 0, &type, (unsigned char *) buffer, &buflen); if (ret != ERROR_SUCCESS) { - unsigned long error = GetLastError(); HeapFree(GetProcessHeap(), 0, buffer); if (ret == ERROR_FILE_NOT_FOUND) { if (! must_exist) return 0; } - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(error), 0); + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(ret), 0); return 2; } @@ -346,12 +364,10 @@ int set_string(HKEY key, TCHAR *value, TCHAR *string, bool expand) { int set_string(HKEY key, TCHAR *value, TCHAR *string) { return set_string(key, value, string, false); - return 1; } int set_expand_string(HKEY key, TCHAR *value, TCHAR *string) { return set_string(key, value, string, true); - return 1; } /* @@ -383,7 +399,7 @@ int get_number(HKEY key, TCHAR *value, unsigned long *number, bool must_exist) { if (! must_exist) return 0; } - log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(GetLastError()), 0); + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(ret), 0); if (ret == ERROR_FILE_NOT_FOUND) return -1; return -2; @@ -485,7 +501,7 @@ void override_milliseconds(TCHAR *service_name, HKEY key, TCHAR *value, unsigned _sntprintf_s(milliseconds, _countof(milliseconds), _TRUNCATE, _T("%lu"), default_value); log_event(EVENTLOG_WARNING_TYPE, event, service_name, value, milliseconds, 0); } - else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(GetLastError()), 0); + else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(ret), 0); } } else ok = true; @@ -504,7 +520,7 @@ HKEY open_service_registry(const TCHAR *service_name, REGSAM sam, bool must_exis return open_registry_key(registry, sam, must_exist); } -HKEY open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam, bool must_exist) { +long open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam, HKEY *key, bool must_exist) { /* Get registry */ TCHAR registry[KEY_LENGTH]; if (service_registry_path(service_name, true, sub, registry, _countof(registry)) < 0) { @@ -512,7 +528,13 @@ HKEY open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam, bool return 0; } - return open_registry_key(registry, sam, must_exist); + return open_registry_key(registry, sam, key, must_exist); +} + +HKEY open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam, bool must_exist) { + HKEY key; + long error = open_registry(service_name, sub, sam, &key, must_exist); + return key; } HKEY open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam) { @@ -627,6 +649,13 @@ int get_parameters(nssm_service_t *service, STARTUPINFO *si) { else log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_BOGUS_PRIORITY, service->name, NSSM_REG_PRIORITY, 0); } + /* Try to get hook I/O sharing - may fail. */ + unsigned long hook_share_output_handles; + if (get_number(key, NSSM_REG_HOOK_SHARE_OUTPUT_HANDLES, &hook_share_output_handles, false) == 1) { + if (hook_share_output_handles) service->hook_share_output_handles = true; + else service->hook_share_output_handles = false; + } + else hook_share_output_handles = false; /* Try to get file rotation settings - may fail. */ unsigned long rotate_files; if (get_number(key, NSSM_REG_ROTATE, &rotate_files, false) == 1) { @@ -639,6 +668,9 @@ int get_parameters(nssm_service_t *service, STARTUPINFO *si) { else service->rotate_stdout_online = service->rotate_stderr_online = false; } else service->rotate_stdout_online = service->rotate_stderr_online = false; + /* Hook I/O sharing and online rotation need a pipe. */ + service->use_stdout_pipe = service->rotate_stdout_online || hook_share_output_handles; + service->use_stderr_pipe = service->rotate_stderr_online || hook_share_output_handles; if (get_number(key, NSSM_REG_ROTATE_SECONDS, &service->rotate_seconds, false) != 1) service->rotate_seconds = 0; if (get_number(key, NSSM_REG_ROTATE_BYTES_LOW, &service->rotate_bytes_low, false) != 1) service->rotate_bytes_low = 0; if (get_number(key, NSSM_REG_ROTATE_BYTES_HIGH, &service->rotate_bytes_high, false) != 1) service->rotate_bytes_high = 0; @@ -680,7 +712,7 @@ int get_parameters(nssm_service_t *service, STARTUPINFO *si) { if (type != REG_DWORD) { log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_BOGUS_STOP_METHOD_SKIP, service->name, NSSM_REG_STOP_METHOD_SKIP, NSSM, 0); } - else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_STOP_METHOD_SKIP, error_string(GetLastError()), 0); + else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_STOP_METHOD_SKIP, error_string(ret), 0); } } else stop_ok = true; @@ -809,8 +841,15 @@ int get_hook(const TCHAR *service_name, const TCHAR *hook_event, const TCHAR *ho log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("hook registry"), _T("get_hook()"), 0); return 1; } - HKEY key = open_registry(service_name, registry, KEY_READ, false); - if (! key) return 1; + HKEY key; + long error = open_registry(service_name, registry, KEY_READ, &key, false); + if (! key) { + if (error == ERROR_FILE_NOT_FOUND) { + ZeroMemory(buffer, buflen); + return 0; + } + return 1; + } int ret = expand_parameter(key, (TCHAR *) hook_action, buffer, buflen, true, false);