[PATCH] services.exe/advapi32: move ChangeServiceConfigW to services.exe
Mikołaj Zalewski
mikolaj at zalewski.pl
Sat Mar 15 13:11:12 CDT 2008
---
dlls/advapi32/service.c | 74 ++++++++++-----------------
dlls/advapi32/tests/service.c | 21 ++++++++
include/wine/svcctl.idl | 18 +++++++
programs/services/rpc.c | 113 +++++++++++++++++++++++++++++++++++++++++
programs/services/services.c | 2 +-
programs/services/services.h | 1 +
6 files changed, 182 insertions(+), 47 deletions(-)
diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index b9892c1..5fc73c9 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -246,6 +246,18 @@ static inline LPWSTR SERV_dupmulti(LPCSTR str)
return wstr;
}
+static inline DWORD multisz_cb(LPCWSTR wmultisz)
+{
+ const WCHAR *wptr = wmultisz;
+
+ if (wmultisz == NULL)
+ return 0;
+
+ while (*wptr)
+ wptr += lstrlenW(wptr)+1;
+ return (wptr - wmultisz + 1)*sizeof(WCHAR);
+}
+
/******************************************************************************
* RPC connection with servies.exe
*/
@@ -1333,7 +1345,7 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
struct sc_service *hsvc = NULL;
DWORD new_mask = dwDesiredAccess;
DWORD len, err;
- SIZE_T depslen = 0, passwdlen;
+ SIZE_T passwdlen;
TRACE("%p %s %s\n", hSCManager,
debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
@@ -1351,16 +1363,6 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
return NULL;
}
- if (lpDependencies)
- {
- const WCHAR *wptr = lpDependencies;
- while (*wptr)
- wptr += strlenW(wptr)+1;
- depslen = (wptr - lpDependencies + 1)*sizeof(WCHAR);
- }
- else
- depslen = 0;
-
if (lpPassword)
passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
else
@@ -1382,8 +1384,9 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
err = svcctl_CreateServiceW(hscm->hdr.rpc_handle, &hscm->hdr.server_handle, lpServiceName,
lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
- lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (LPBYTE)lpDependencies, depslen,
- lpServiceStartName, (LPBYTE)lpPassword, passwdlen, &hsvc->hdr.server_handle);
+ lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (LPBYTE)lpDependencies,
+ multisz_cb(lpDependencies), lpServiceStartName, (LPBYTE)lpPassword, passwdlen,
+ &hsvc->hdr.server_handle);
if (err != ERROR_SUCCESS)
{
@@ -2194,55 +2197,34 @@ BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
{
- struct reg_value val[10];
struct sc_service *hsvc;
- DWORD r = ERROR_SUCCESS;
- HKEY hKey;
- int n = 0;
+ DWORD cb_pwd;
+ DWORD err;
TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
hService, dwServiceType, dwStartType, dwErrorControl,
debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
-
+
hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
if (!hsvc)
{
SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
- hKey = hsvc->hkey;
-
- if( dwServiceType != SERVICE_NO_CHANGE )
- service_set_dword( &val[n++], szType, &dwServiceType );
-
- if( dwStartType != SERVICE_NO_CHANGE )
- service_set_dword( &val[n++], szStart, &dwStartType );
-
- if( dwErrorControl != SERVICE_NO_CHANGE )
- service_set_dword( &val[n++], szError, &dwErrorControl );
-
- if( lpBinaryPathName )
- service_set_string( &val[n++], szImagePath, lpBinaryPathName );
- if( lpLoadOrderGroup )
- service_set_string( &val[n++], szGroup, lpLoadOrderGroup );
+ cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
- /* FIXME: lpDependencies is used to create/change both DependOnService and DependOnGroup
- * There is no such key as what szDependencies refers to */
- if( lpDependencies )
- service_set_multi_string( &val[n++], szDependencies, lpDependencies );
+ err = svcctl_ChangeServiceConfigW(hsvc->hdr.rpc_handle, &hsvc->hdr.server_handle, dwServiceType,
+ dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
+ (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
+ (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
- if( lpPassword )
- FIXME("ignoring password\n");
-
- if( lpServiceStartName )
- service_set_string( &val[n++], szObjectName, lpServiceStartName );
-
- r = service_write_values( hsvc->hkey, val, n );
-
- return (r == ERROR_SUCCESS) ? TRUE : FALSE ;
+ if (err != ERROR_SUCCESS)
+ SetLastError(err);
+
+ return err == ERROR_SUCCESS;
}
/******************************************************************************
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c
index 27bad34..be6bd79 100644
--- a/dlls/advapi32/tests/service.c
+++ b/dlls/advapi32/tests/service.c
@@ -730,6 +730,7 @@ static void test_sequence(void)
DWORD given, needed;
static const CHAR servicename [] = "Winetest";
static const CHAR displayname [] = "Winetest dummy service";
+ static const CHAR displayname2[] = "Winetest dummy service (2)";
static const CHAR pathname [] = "we_dont_care.exe";
static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
static const CHAR password [] = "";
@@ -823,6 +824,26 @@ static void test_sequence(void)
ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName);
+ ok(ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_ERROR_NORMAL, NULL, "TestGroup2", NULL, NULL, NULL, NULL, displayname2),
+ "ChangeServiceConfig failed (err=%d)\n", GetLastError());
+
+#if 0 /* for some reason (rpcrt4 bug?) QueryServiceConfig for a non-NULL lpLoadOrder crashes Wine */
+ QueryServiceConfigA(svc_handle, NULL, 0, &needed);
+ config = HeapReAlloc(GetProcessHeap(), 0, config, needed);
+ ok(QueryServiceConfigA(svc_handle, config, needed, &needed), "QueryServiceConfig failed\n");
+ ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
+ config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
+ ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
+ "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
+ ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
+ ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "Expected SERVICE_ERROR_NORMAL, got %d\n", config->dwErrorControl);
+ ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
+ ok(!strcmp(config->lpLoadOrderGroup, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config->lpLoadOrderGroup);
+ ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
+ ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
+ ok(!strcmp(config->lpDisplayName, displayname2), "Expected '%s', got '%s'\n", displayname2, config->lpDisplayName);
+#endif
+
SetLastError(0xdeadbeef);
ret = DeleteService(svc_handle);
ok(ret, "Expected success\n");
diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl
index f7ce1d9..fa94315 100644
--- a/include/wine/svcctl.idl
+++ b/include/wine/svcctl.idl
@@ -79,6 +79,24 @@ cpp_quote("#endif")
[in,ref] POLICY_HANDLE *hService
);
+ /* Compatible with Windows function 0x0b */
+ DWORD svcctl_ChangeServiceConfigW(
+ SvcCtlRpcHandle rpc_handle,
+ [in,ref] POLICY_HANDLE *hService,
+ [in] DWORD dwServiceType,
+ [in] DWORD dwStartType,
+ [in] DWORD dwErrorControl,
+ [in,unique,string] LPCWSTR lpBinaryPathName,
+ [in,unique,string] LPCWSTR lpLoadOrderGroupKey,
+ [in,out,unique] DWORD *lpdwTagId,
+ [in,unique,size_is(dwDependenciesSize)] const BYTE *lpDependencies,
+ [in] DWORD dwDependenciesSize,
+ [in,unique,string] LPCWSTR lpServiceStartName,
+ [in,unique,size_is(dwPasswordSize)] const BYTE *lpPassword,
+ [in] DWORD dwPasswordSize,
+ [in,unique,string] LPCWSTR lpDisplayName
+ );
+
/* Compatible with Windows function 0x0c */
DWORD svcctl_CreateServiceW(
SvcCtlRpcHandle rpc_handle,
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 1fe474f..b2bb1f9 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -388,6 +388,119 @@ DWORD svcctl_QueryServiceConfigW(
return ERROR_SUCCESS;
}
+DWORD svcctl_ChangeServiceConfigW(
+ SvcCtlRpcHandle rpc_handle,
+ POLICY_HANDLE *hService,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPCWSTR lpBinaryPathName,
+ LPCWSTR lpLoadOrderGroup,
+ DWORD *lpdwTagId,
+ const BYTE *lpDependencies,
+ DWORD dwDependenciesSize,
+ LPCWSTR lpServiceStartName,
+ const BYTE *lpPassword,
+ DWORD dwPasswordSize,
+ LPCWSTR lpDisplayName)
+{
+ service_entry new_entry;
+ service_entry *service;
+ DWORD err;
+
+ WINE_TRACE("conn=%p (%s)\n", rpc_handle, wine_dbgstr_guid(&hService->uuid));
+ if ((err = validate_service_handle(hService, SERVICE_CHANGE_CONFIG, &service)) != 0)
+ return err;
+
+ if (!check_multisz((LPCWSTR)lpDependencies, dwDependenciesSize))
+ return ERROR_INVALID_PARAMETER;
+
+ /* first check if the new configuration is correct */
+ lock_services();
+
+ if (is_marked_for_delete(service))
+ {
+ unlock_services();
+ return ERROR_SERVICE_MARKED_FOR_DELETE;
+ }
+
+ if (lpDisplayName != NULL && find_service_by_displayname(lpDisplayName))
+ {
+ unlock_services();
+ return ERROR_DUPLICATE_SERVICE_NAME;
+ }
+
+ new_entry = *service;
+
+ if (dwServiceType != SERVICE_NO_CHANGE)
+ new_entry.config.dwServiceType = dwServiceType;
+
+ if (dwStartType != SERVICE_NO_CHANGE)
+ new_entry.config.dwStartType = dwStartType;
+
+ if (dwErrorControl != SERVICE_NO_CHANGE)
+ new_entry.config.dwErrorControl = dwErrorControl;
+
+ if (lpBinaryPathName != NULL)
+ new_entry.config.lpBinaryPathName = (LPWSTR)lpBinaryPathName;
+
+ if (lpLoadOrderGroup != NULL)
+ new_entry.config.lpLoadOrderGroup = (LPWSTR)lpLoadOrderGroup;
+
+ if (lpdwTagId != NULL)
+ WINE_FIXME("Changing tag id not supported\n");
+
+ if (lpDependencies != NULL)
+ WINE_FIXME("Chainging dependencies not supported\n");
+
+ if (lpServiceStartName != NULL)
+ new_entry.config.lpServiceStartName = (LPWSTR)lpServiceStartName;
+
+ if (lpPassword != NULL)
+ WINE_FIXME("Setting password not supported\n");
+
+ if (lpDisplayName != NULL)
+ new_entry.config.lpDisplayName = (LPWSTR)lpDisplayName;
+
+ if (!validate_service_config(&new_entry))
+ {
+ WINE_ERR("The configuration after the change wouldn't be valid");
+ unlock_services();
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* configuration OK. The strings needs to be duplicated */
+ if (lpBinaryPathName != NULL)
+ {
+ HeapFree(GetProcessHeap(), 0, service->config.lpBinaryPathName);
+ new_entry.config.lpBinaryPathName = strdupW(lpBinaryPathName);
+ }
+
+ if (lpLoadOrderGroup != NULL)
+ {
+ HeapFree(GetProcessHeap(), 0, service->config.lpLoadOrderGroup);
+ new_entry.config.lpLoadOrderGroup = strdupW(lpLoadOrderGroup);
+ }
+
+ if (lpServiceStartName != NULL)
+ {
+ HeapFree(GetProcessHeap(), 0, service->config.lpServiceStartName);
+ new_entry.config.lpServiceStartName = strdupW(lpServiceStartName);
+ }
+
+ if (lpDisplayName != NULL)
+ {
+ HeapFree(GetProcessHeap(), 0, service->config.lpDisplayName);
+ new_entry.config.lpDisplayName = strdupW(lpDisplayName);
+ }
+
+ *service = new_entry;
+ save_service_config(service);
+ unlock_services();
+
+ return ERROR_SUCCESS;
+}
+
DWORD svcctl_CloseServiceHandle(
SvcCtlRpcHandle rpc_handle,
POLICY_HANDLE *handle)
diff --git a/programs/services/services.c b/programs/services/services.c
index b78fc5f..3ab8690 100644
--- a/programs/services/services.c
+++ b/programs/services/services.c
@@ -141,7 +141,7 @@ static DWORD reg_set_string_value(HKEY hKey, LPCWSTR value_name, LPCWSTR string)
return RegSetValueExW(hKey, value_name, 0, REG_SZ, (LPBYTE)string, sizeof(WCHAR)*(strlenW(string) + 1));
}
-static DWORD save_service_config(service_entry *entry)
+DWORD save_service_config(service_entry *entry)
{
HKEY hServicesRootKey;
DWORD err;
diff --git a/programs/services/services.h b/programs/services/services.h
index 5dfca89..b8cf458 100644
--- a/programs/services/services.h
+++ b/programs/services/services.h
@@ -41,6 +41,7 @@ service_entry *find_service(LPCWSTR name);
service_entry *find_service_by_displayname(LPCWSTR name);
DWORD add_service(service_entry *entry);
DWORD remove_service(service_entry *entry);
+DWORD save_service_config(service_entry *entry);
void free_service_entry(service_entry *entry);
void release_service(service_entry *service);
--
1.5.4
--------------000309080705090404040605--
More information about the wine-patches
mailing list