}\r
\r
/* Functions to manage native service settings. */\r
+static int native_set_dependon(const TCHAR *service_name, SC_HANDLE service_handle, TCHAR **dependencies, unsigned long *dependencieslen, value_t *value, int type) {\r
+ *dependencieslen = 0;\r
+ if (! value || ! value->string || ! value->string[0]) return 0;\r
+\r
+ TCHAR *string = value->string;\r
+ unsigned long buflen;\r
+ int op = 0;\r
+ switch (string[0]) {\r
+ case _T('+'): op = 1; break;\r
+ case _T('-'): op = -1; break;\r
+ case _T(':'): string++; break;\r
+ }\r
+\r
+ if (op) {\r
+ string++;\r
+ TCHAR *buffer = 0;\r
+ if (get_service_dependencies(service_name, service_handle, &buffer, &buflen, type)) return -1;\r
+ if (buffer) {\r
+ int ret;\r
+ if (op > 0) ret = append_to_dependencies(buffer, buflen, string, dependencies, dependencieslen, type);\r
+ else ret = remove_from_dependencies(buffer, buflen, string, dependencies, dependencieslen, type);\r
+ if (buflen) HeapFree(GetProcessHeap(), 0, buffer);\r
+ return ret;\r
+ }\r
+ else {\r
+ /*\r
+ No existing list.\r
+ We can't remove from an empty list so just treat an add\r
+ operation as setting a new string.\r
+ */\r
+ if (op < 0) return 0;\r
+ op = 0;\r
+ }\r
+ }\r
+\r
+ if (! op) {\r
+ TCHAR *unformatted = 0;\r
+ unsigned long newlen;\r
+ if (unformat_double_null(string, (unsigned long) _tcslen(string), &unformatted, &newlen)) return -1;\r
+\r
+ if (type == DEPENDENCY_GROUPS) {\r
+ /* Prepend group identifier. */\r
+ unsigned long missing = 0;\r
+ TCHAR *canon = unformatted;\r
+ size_t canonlen = 0;\r
+ TCHAR *s;\r
+ for (s = unformatted; *s; s++) {\r
+ if (*s != SC_GROUP_IDENTIFIER) missing++;\r
+ size_t len = _tcslen(s);\r
+ canonlen += len + 1;\r
+ s += len;\r
+ }\r
+\r
+ if (missing) {\r
+ /* Missing identifiers plus double NULL terminator. */\r
+ canonlen += missing + 1;\r
+\r
+ canon = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, canonlen * sizeof(TCHAR));\r
+ if (! canon) {\r
+ print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("native_set_dependon"));\r
+ if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted);\r
+ return -1;\r
+ }\r
+\r
+ size_t i = 0;\r
+ for (s = unformatted; *s; s++) {\r
+ if (*s != SC_GROUP_IDENTIFIER) canon[i++] = SC_GROUP_IDENTIFIER;\r
+ size_t len = _tcslen(s);\r
+ memmove(canon + i, s, (len + 1) * sizeof(TCHAR));\r
+ i += len + 1;\r
+ s += len;\r
+ }\r
+\r
+ HeapFree(GetProcessHeap(), 0, unformatted);\r
+ unformatted = canon;\r
+ newlen = (unsigned long) canonlen;\r
+ }\r
+ }\r
+\r
+ *dependencies = unformatted;\r
+ *dependencieslen = newlen;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
static int native_set_dependongroup(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) {\r
SC_HANDLE service_handle = (SC_HANDLE) param;\r
if (! service_handle) return -1;\r
/*\r
Get existing service dependencies because we must set both types together.\r
*/\r
- TCHAR *buffer;\r
- unsigned long buflen;\r
- if (get_service_dependencies(service_name, service_handle, &buffer, &buflen, DEPENDENCY_SERVICES)) return -1;\r
+ TCHAR *services_buffer;\r
+ unsigned long services_buflen;\r
+ if (get_service_dependencies(service_name, service_handle, &services_buffer, &services_buflen, DEPENDENCY_SERVICES)) return -1;\r
\r
if (! value || ! value->string || ! value->string[0]) {\r
- if (! ChangeServiceConfig(service_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, buffer, 0, 0, 0)) {\r
+ if (! ChangeServiceConfig(service_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, services_buffer, 0, 0, 0)) {\r
print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError()));\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
+ if (services_buffer) HeapFree(GetProcessHeap(), 0, services_buffer);\r
return -1;\r
}\r
\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
+ if (services_buffer) HeapFree(GetProcessHeap(), 0, services_buffer);\r
return 0;\r
}\r
\r
- unsigned long len = (unsigned long) _tcslen(value->string) + 1;\r
- TCHAR *unformatted = 0;\r
- unsigned long newlen;\r
- if (unformat_double_null(value->string, len, &unformatted, &newlen)) {\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
- return -1;\r
- }\r
-\r
- /* Prepend group identifier. */\r
- unsigned long missing = 0;\r
- TCHAR *canon = unformatted;\r
- size_t canonlen = 0;\r
- TCHAR *s;\r
- for (s = unformatted; *s; s++) {\r
- if (*s != SC_GROUP_IDENTIFIER) missing++;\r
- size_t len = _tcslen(s);\r
- canonlen += len + 1;\r
- s += len;\r
- }\r
-\r
- if (missing) {\r
- /* Missing identifiers plus double NULL terminator. */\r
- canonlen += missing + 1;\r
- newlen = (unsigned long) canonlen;\r
-\r
- canon = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, canonlen * sizeof(TCHAR));\r
- if (! canon) {\r
- print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("native_set_dependongroup"));\r
- if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted);\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
- return -1;\r
- }\r
-\r
- size_t i = 0;\r
- for (s = unformatted; *s; s++) {\r
- if (*s != SC_GROUP_IDENTIFIER) canon[i++] = SC_GROUP_IDENTIFIER;\r
- size_t len = _tcslen(s);\r
- memmove(canon + i, s, (len + 1) * sizeof(TCHAR));\r
- i += len + 1;\r
- s += len;\r
- }\r
- }\r
+ /* Update the group list. */\r
+ TCHAR *groups_buffer;\r
+ unsigned long groups_buflen;\r
+ if (native_set_dependon(service_name, service_handle, &groups_buffer, &groups_buflen, value, DEPENDENCY_GROUPS)) return -1;\r
\r
TCHAR *dependencies;\r
- if (buflen > 2) {\r
- dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, (newlen + buflen) * sizeof(TCHAR));\r
+ if (services_buflen > 2) {\r
+ dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, (groups_buflen + services_buflen) * sizeof(TCHAR));\r
if (! dependencies) {\r
print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("dependencies"), _T("native_set_dependongroup"));\r
- if (canon != unformatted) HeapFree(GetProcessHeap(), 0, canon);\r
- if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted);\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
+ if (groups_buffer) HeapFree(GetProcessHeap(), 0, groups_buffer);\r
+ if (services_buffer) HeapFree(GetProcessHeap(), 0, services_buffer);\r
return -1;\r
}\r
\r
- memmove(dependencies, buffer, buflen * sizeof(TCHAR));\r
- memmove(dependencies + buflen - 1, canon, newlen * sizeof(TCHAR));\r
+ memmove(dependencies, services_buffer, services_buflen * sizeof(TCHAR));\r
+ memmove(dependencies + services_buflen - 1, groups_buffer, groups_buflen * sizeof(TCHAR));\r
}\r
- else dependencies = canon;\r
+ else dependencies = groups_buffer;\r
\r
int ret = 1;\r
if (set_service_dependencies(service_name, service_handle, dependencies)) ret = -1;\r
- if (dependencies != unformatted) HeapFree(GetProcessHeap(), 0, dependencies);\r
- if (canon != unformatted) HeapFree(GetProcessHeap(), 0, canon);\r
- if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted);\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
+ if (dependencies != groups_buffer) HeapFree(GetProcessHeap(), 0, dependencies);\r
+ if (groups_buffer) HeapFree(GetProcessHeap(), 0, groups_buffer);\r
+ if (services_buffer) HeapFree(GetProcessHeap(), 0, services_buffer);\r
\r
return ret;\r
}\r
/*\r
Get existing group dependencies because we must set both types together.\r
*/\r
- TCHAR *buffer;\r
- unsigned long buflen;\r
- if (get_service_dependencies(service_name, service_handle, &buffer, &buflen, DEPENDENCY_GROUPS)) return -1;\r
+ TCHAR *groups_buffer;\r
+ unsigned long groups_buflen;\r
+ if (get_service_dependencies(service_name, service_handle, &groups_buffer, &groups_buflen, DEPENDENCY_GROUPS)) return -1;\r
\r
if (! value || ! value->string || ! value->string[0]) {\r
- if (! ChangeServiceConfig(service_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, buffer, 0, 0, 0)) {\r
+ if (! ChangeServiceConfig(service_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, groups_buffer, 0, 0, 0)) {\r
print_message(stderr, NSSM_MESSAGE_CHANGESERVICECONFIG_FAILED, error_string(GetLastError()));\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
+ if (groups_buffer) HeapFree(GetProcessHeap(), 0, groups_buffer);\r
return -1;\r
}\r
\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
+ if (groups_buffer) HeapFree(GetProcessHeap(), 0, groups_buffer);\r
return 0;\r
}\r
\r
- unsigned long len = (unsigned long) _tcslen(value->string) + 1;\r
- TCHAR *unformatted = 0;\r
- unsigned long newlen;\r
- if (unformat_double_null(value->string, len, &unformatted, &newlen)) {\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
- return -1;\r
- }\r
+ /* Update the service list. */\r
+ TCHAR *services_buffer;\r
+ unsigned long services_buflen;\r
+ if (native_set_dependon(service_name, service_handle, &services_buffer, &services_buflen, value, DEPENDENCY_SERVICES)) return -1;\r
\r
TCHAR *dependencies;\r
- if (buflen > 2) {\r
- dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, (newlen + buflen) * sizeof(TCHAR));\r
+ if (groups_buflen > 2) {\r
+ dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, (services_buflen + groups_buflen) * sizeof(TCHAR));\r
if (! dependencies) {\r
print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("dependencies"), _T("native_set_dependonservice"));\r
- if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted);\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
+ if (groups_buffer) HeapFree(GetProcessHeap(), 0, groups_buffer);\r
+ if (services_buffer) HeapFree(GetProcessHeap(), 0, services_buffer);\r
return -1;\r
}\r
\r
- memmove(dependencies, buffer, buflen * sizeof(TCHAR));\r
- memmove(dependencies + buflen - 1, unformatted, newlen * sizeof(TCHAR));\r
+ memmove(dependencies, services_buffer, services_buflen * sizeof(TCHAR));\r
+ memmove(dependencies + services_buflen - 1, groups_buffer, groups_buflen * sizeof(TCHAR));\r
}\r
- else dependencies = unformatted;\r
+ else dependencies = services_buffer;\r
\r
int ret = 1;\r
if (set_service_dependencies(service_name, service_handle, dependencies)) ret = -1;\r
- if (dependencies != unformatted) HeapFree(GetProcessHeap(), 0, dependencies);\r
- if (unformatted) HeapFree(GetProcessHeap(), 0, unformatted);\r
- if (buffer) HeapFree(GetProcessHeap(), 0, buffer);\r
+ if (dependencies != services_buffer) HeapFree(GetProcessHeap(), 0, dependencies);\r
+ if (groups_buffer) HeapFree(GetProcessHeap(), 0, groups_buffer);\r
+ if (services_buffer) HeapFree(GetProcessHeap(), 0, services_buffer);\r
\r
return ret;\r
}\r