[2/8] programs/services: Support setting and changing service dependencies.
Hans Leidekker
hans at codeweavers.com
Fri Oct 22 03:35:49 CDT 2010
---
programs/services/rpc.c | 104 +++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 96 insertions(+), 8 deletions(-)
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index c647cc8..41630be 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -84,8 +84,11 @@ struct sc_lock
struct scmdatabase *db;
};
-static void free_config_strings(QUERY_SERVICE_CONFIGW *old_cfg, QUERY_SERVICE_CONFIGW *new_cfg)
+static void free_service_strings(struct service_entry *old, struct service_entry *new)
{
+ QUERY_SERVICE_CONFIGW *old_cfg = &old->config;
+ QUERY_SERVICE_CONFIGW *new_cfg = &new->config;
+
if (old_cfg->lpBinaryPathName != new_cfg->lpBinaryPathName)
HeapFree(GetProcessHeap(), 0, old_cfg->lpBinaryPathName);
@@ -97,6 +100,12 @@ static void free_config_strings(QUERY_SERVICE_CONFIGW *old_cfg, QUERY_SERVICE_CO
if (old_cfg->lpDisplayName != new_cfg->lpDisplayName)
HeapFree(GetProcessHeap(), 0, old_cfg->lpDisplayName);
+
+ if (old->dependOnServices != new->dependOnServices)
+ HeapFree(GetProcessHeap(), 0, old->dependOnServices);
+
+ if (old->dependOnGroups != new->dependOnGroups)
+ HeapFree(GetProcessHeap(), 0, old->dependOnGroups);
}
/* Check if the given handle is of the required type and allows the requested access. */
@@ -335,6 +344,78 @@ DWORD svcctl_OpenServiceW(
return create_handle_for_service(entry, dwDesiredAccess, phService);
}
+static DWORD parse_dependencies(const WCHAR *dependencies, struct service_entry *entry)
+{
+ WCHAR *services = NULL, *groups, *s;
+ DWORD len, len_services = 0, len_groups = 0;
+ const WCHAR *ptr = dependencies;
+
+ if (!dependencies || !dependencies[0])
+ {
+ entry->dependOnServices = NULL;
+ entry->dependOnGroups = NULL;
+ return ERROR_SUCCESS;
+ }
+
+ while (*ptr)
+ {
+ len = strlenW(ptr) + 1;
+ if (ptr[0] == '+' && ptr[1])
+ len_groups += len - 1;
+ else
+ len_services += len;
+ ptr += len;
+ }
+ if (!len_services) entry->dependOnServices = NULL;
+ else
+ {
+ services = HeapAlloc(GetProcessHeap(), 0, (len_services + 1) * sizeof(WCHAR));
+ if (!services)
+ return ERROR_OUTOFMEMORY;
+
+ s = services;
+ ptr = dependencies;
+ while (*ptr)
+ {
+ len = strlenW(ptr) + 1;
+ if (*ptr != '+')
+ {
+ strcpyW(s, ptr);
+ s += len;
+ }
+ ptr += len;
+ }
+ *s = 0;
+ entry->dependOnServices = services;
+ }
+ if (!len_groups) entry->dependOnGroups = NULL;
+ else
+ {
+ groups = HeapAlloc(GetProcessHeap(), 0, (len_groups + 1) * sizeof(WCHAR));
+ if (!groups)
+ {
+ HeapFree(GetProcessHeap(), 0, services);
+ return ERROR_OUTOFMEMORY;
+ }
+ s = groups;
+ ptr = dependencies;
+ while (*ptr)
+ {
+ len = strlenW(ptr) + 1;
+ if (ptr[0] == '+' && ptr[1])
+ {
+ strcpyW(s, ptr + 1);
+ s += len - 1;
+ }
+ ptr += len;
+ }
+ *s = 0;
+ entry->dependOnGroups = groups;
+ }
+
+ return ERROR_SUCCESS;
+}
+
DWORD svcctl_CreateServiceW(
SC_RPC_HANDLE hSCManager,
LPCWSTR lpServiceName,
@@ -369,12 +450,15 @@ DWORD svcctl_CreateServiceW(
if (lpPassword)
WINE_FIXME("Don't know how to add a password\n"); /* I always get ERROR_GEN_FAILURE */
- if (lpDependencies)
- WINE_FIXME("Dependencies not supported yet\n");
err = service_create(lpServiceName, &entry);
if (err != ERROR_SUCCESS)
return err;
+
+ err = parse_dependencies((LPCWSTR)lpDependencies, entry);
+ if (err != ERROR_SUCCESS)
+ return err;
+
entry->ref_count = 1;
entry->config.dwServiceType = entry->status.dwServiceType = dwServiceType;
entry->config.dwStartType = dwStartType;
@@ -540,9 +624,6 @@ DWORD svcctl_ChangeServiceConfigW(
if (lpdwTagId != NULL)
WINE_FIXME("Changing tag id not supported\n");
- if (lpDependencies != NULL)
- WINE_FIXME("Changing dependencies not supported\n");
-
if (lpServiceStartName != NULL)
new_entry.config.lpServiceStartName = (LPWSTR)lpServiceStartName;
@@ -552,6 +633,13 @@ DWORD svcctl_ChangeServiceConfigW(
if (lpDisplayName != NULL)
new_entry.config.lpDisplayName = (LPWSTR)lpDisplayName;
+ err = parse_dependencies((LPCWSTR)lpDependencies, &new_entry);
+ if (err != ERROR_SUCCESS)
+ {
+ service_unlock(service->service_entry);
+ return err;
+ }
+
if (!validate_service_config(&new_entry))
{
WINE_ERR("The configuration after the change wouldn't be valid\n");
@@ -576,10 +664,10 @@ DWORD svcctl_ChangeServiceConfigW(
err = save_service_config(&new_entry);
if (ERROR_SUCCESS == err)
{
- free_config_strings(&service->service_entry->config,&new_entry.config);
+ free_service_strings(service->service_entry, &new_entry);
*service->service_entry = new_entry;
}
- else free_config_strings(&new_entry.config,&service->service_entry->config);
+ else free_service_strings(&new_entry, service->service_entry);
service_unlock(service->service_entry);
return err;
--
1.7.1
More information about the wine-patches
mailing list