[PATCH] services.exe/advapi32: Move QueryServiceConfig to services.exe
Mikołaj Zalewski
mikolaj at zalewski.pl
Sat Mar 15 10:42:40 CDT 2008
---
dlls/advapi32/service.c | 209 ++++++++++++-----------------------------------
include/wine/svcctl.idl | 26 ++++++
programs/services/rpc.c | 26 ++++++
3 files changed, 105 insertions(+), 156 deletions(-)
diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index 52a3f1c..b9892c1 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -1862,6 +1862,29 @@ done:
return ret;
}
+static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
+{
+ DWORD cb;
+ WCHAR empty_str[] = {0};
+
+ if (!*string_ptr)
+ *string_ptr = empty_str;
+
+ cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
+
+ memcpy(*buf, *string_ptr, cb);
+ MIDL_user_free(*string_ptr);
+ *string_ptr = (LPWSTR)*buf;
+ *buf += cb;
+
+ return cb;
+}
+
+static DWORD size_string(LPWSTR string)
+{
+ return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
+}
+
/******************************************************************************
* QueryServiceConfigW [ADVAPI32.@]
*/
@@ -1870,12 +1893,11 @@ QueryServiceConfigW( SC_HANDLE hService,
LPQUERY_SERVICE_CONFIGW lpServiceConfig,
DWORD cbBufSize, LPDWORD pcbBytesNeeded)
{
- WCHAR str_buffer[ MAX_PATH ];
- LONG r;
- DWORD type, val, sz, total, n;
- LPBYTE p;
- HKEY hKey;
+ QUERY_SERVICE_CONFIGW config;
struct sc_service *hsvc;
+ DWORD total;
+ DWORD err;
+ BYTE *bufpos;
TRACE("%p %p %d %p\n", hService, lpServiceConfig,
cbBufSize, pcbBytesNeeded);
@@ -1886,58 +1908,21 @@ QueryServiceConfigW( SC_HANDLE hService,
SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
- hKey = hsvc->hkey;
-
- /* TODO: Check which members are mandatory and what the registry types
- * should be. This should of course also be tested when a service is
- * created.
- */
-
- /* calculate the size required first */
- total = sizeof (QUERY_SERVICE_CONFIGW);
- sz = sizeof(str_buffer);
- r = RegQueryValueExW( hKey, szImagePath, 0, &type, (LPBYTE) str_buffer, &sz );
- if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ || type == REG_EXPAND_SZ ) )
+ if ((err = svcctl_QueryServiceConfigW(hsvc->hdr.rpc_handle, &hsvc->hdr.server_handle, &config)) != 0)
{
- sz = ExpandEnvironmentStringsW(str_buffer,NULL,0);
- if( 0 == sz ) return FALSE;
-
- total += sizeof(WCHAR) * sz;
- }
- else
- {
- /* FIXME: set last error */
- return FALSE;
+ TRACE("services.exe: error %u\n", err);
+ SetLastError(err);
+ return FALSE;
}
- sz = 0;
- r = RegQueryValueExW( hKey, szGroup, 0, &type, NULL, &sz );
- if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
- total += sz;
- else
- total += sizeof(WCHAR);
-
- sz = 0;
- r = RegQueryValueExW( hKey, szDependencies, 0, &type, NULL, &sz );
- if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
- total += sz;
- else
- total += sizeof(WCHAR);
-
- sz = 0;
- r = RegQueryValueExW( hKey, szObjectName, 0, &type, NULL, &sz );
- if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
- total += sz;
- else
- total += sizeof(WCHAR);
-
- sz = 0;
- r = RegQueryValueExW( hKey, szDisplayName, 0, &type, NULL, &sz );
- if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
- total += sz;
- else
- total += sizeof(WCHAR);
+ /* calculate the size required first */
+ total = sizeof (QUERY_SERVICE_CONFIGW);
+ total += size_string(config.lpBinaryPathName);
+ total += size_string(config.lpLoadOrderGroup);
+ total += size_string(config.lpDependencies);
+ total += size_string(config.lpServiceStartName);
+ total += size_string(config.lpDisplayName);
*pcbBytesNeeded = total;
@@ -1945,112 +1930,24 @@ QueryServiceConfigW( SC_HANDLE hService,
if( total > cbBufSize )
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
+ MIDL_user_free(config.lpBinaryPathName);
+ MIDL_user_free(config.lpLoadOrderGroup);
+ MIDL_user_free(config.lpDependencies);
+ MIDL_user_free(config.lpServiceStartName);
+ MIDL_user_free(config.lpDisplayName);
return FALSE;
}
- ZeroMemory( lpServiceConfig, total );
-
- sz = sizeof val;
- r = RegQueryValueExW( hKey, szType, 0, &type, (LPBYTE)&val, &sz );
- if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) )
- lpServiceConfig->dwServiceType = val;
-
- sz = sizeof val;
- r = RegQueryValueExW( hKey, szStart, 0, &type, (LPBYTE)&val, &sz );
- if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) )
- lpServiceConfig->dwStartType = val;
-
- sz = sizeof val;
- r = RegQueryValueExW( hKey, szError, 0, &type, (LPBYTE)&val, &sz );
- if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) )
- lpServiceConfig->dwErrorControl = val;
-
- sz = sizeof val;
- r = RegQueryValueExW( hKey, szTag, 0, &type, (LPBYTE)&val, &sz );
- if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) )
- lpServiceConfig->dwTagId = val;
-
- /* now do the strings */
- p = (LPBYTE) &lpServiceConfig[1];
- n = total - sizeof (QUERY_SERVICE_CONFIGW);
-
- sz = sizeof(str_buffer);
- r = RegQueryValueExW( hKey, szImagePath, 0, &type, (LPBYTE) str_buffer, &sz );
- if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ || type == REG_EXPAND_SZ ) )
- {
- sz = ExpandEnvironmentStringsW(str_buffer, (LPWSTR) p, n);
- sz *= sizeof(WCHAR);
- if( 0 == sz || sz > n ) return FALSE;
-
- lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
- p += sz;
- n -= sz;
- }
- else
- {
- /* FIXME: set last error */
- return FALSE;
- }
-
- sz = n;
- r = RegQueryValueExW( hKey, szGroup, 0, &type, p, &sz );
- lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
- if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
- {
- p += sz;
- n -= sz;
- }
- else
- {
- *(WCHAR *) p = 0;
- p += sizeof(WCHAR);
- n -= sizeof(WCHAR);
- }
-
- sz = n;
- r = RegQueryValueExW( hKey, szDependencies, 0, &type, p, &sz );
- lpServiceConfig->lpDependencies = (LPWSTR) p;
- if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
- {
- p += sz;
- n -= sz;
- }
- else
- {
- *(WCHAR *) p = 0;
- p += sizeof(WCHAR);
- n -= sizeof(WCHAR);
- }
-
- sz = n;
- r = RegQueryValueExW( hKey, szObjectName, 0, &type, p, &sz );
- lpServiceConfig->lpServiceStartName = (LPWSTR) p;
- if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
- {
- p += sz;
- n -= sz;
- }
- else
- {
- *(WCHAR *) p = 0;
- p += sizeof(WCHAR);
- n -= sizeof(WCHAR);
- }
-
- sz = n;
- r = RegQueryValueExW( hKey, szDisplayName, 0, &type, p, &sz );
- lpServiceConfig->lpDisplayName = (LPWSTR) p;
- if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
- {
- p += sz;
- n -= sz;
- }
- else
- {
- *(WCHAR *) p = 0;
- p += sizeof(WCHAR);
- n -= sizeof(WCHAR);
- }
+ *lpServiceConfig = config;
+ bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
+ move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
+ move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
+ move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
+ move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
+ move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
+
+ if (bufpos - (LPBYTE)lpServiceConfig > cbBufSize)
+ ERR("Buffer overflow!\n");
TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl
index f25d4a3..f7ce1d9 100644
--- a/include/wine/svcctl.idl
+++ b/include/wine/svcctl.idl
@@ -24,6 +24,8 @@ import "wtypes.idl";
/*
* some defined for the C code
*/
+cpp_quote("#include \"winsvc.h\"");
+
cpp_quote("#define SVCCTL_TRANSPORT {'n','c','a','c','n','_','n','p',0}");
cpp_quote("#define SVCCTL_ENDPOINT {'\\\\','p','i','p','e','\\\\','s','v','c','c','t','l',0}");
@@ -50,6 +52,21 @@ cpp_quote("#define SVCCTL_STARTED_EVENT (const WCHAR[]){'_','_','w','i','n','e',
GUID uuid;
} POLICY_HANDLE;
+cpp_quote("#if 0 /* already defined in winsvc.h */")
+typedef struct _QUERY_SERVICE_CONFIGW {
+ DWORD dwServiceType;
+ DWORD dwStartType;
+ DWORD dwErrorControl;
+ [unique,string] LPWSTR lpBinaryPathName;
+ [unique,string] LPWSTR lpLoadOrderGroup;
+ DWORD dwTagId;
+ [unique,string] LPWSTR lpDependencies;
+ [unique,string] LPWSTR lpServiceStartName;
+ [unique,string] LPWSTR lpDisplayName;
+} QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW;
+cpp_quote("#endif")
+
+
/* Compatible with Windows function 0x00 */
DWORD svcctl_CloseServiceHandle(
[in] SvcCtlRpcHandle rpc_handle,
@@ -100,4 +117,13 @@ cpp_quote("#define SVCCTL_STARTED_EVENT (const WCHAR[]){'_','_','w','i','n','e',
[in] DWORD dwDesiredAccess,
[out] POLICY_HANDLE *phService
);
+
+ /* Windows function 0x11 must be using a different prototype - not compatible */
+ /* Robert Shearman thinks there should be a byte_count attribute but (as of Sep 2007)
+ * this isn't supported by widl nor by rpcrt4 */
+ DWORD svcctl_QueryServiceConfigW(
+ SvcCtlRpcHandle rpc_handle,
+ [in] POLICY_HANDLE *handle,
+ [out] QUERY_SERVICE_CONFIGW *config);
+
}
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index af5c346..1fe474f 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -362,6 +362,32 @@ DWORD svcctl_DeleteService(
return err;
}
+DWORD svcctl_QueryServiceConfigW(
+ SvcCtlRpcHandle rpc_handle,
+ POLICY_HANDLE *hService,
+ QUERY_SERVICE_CONFIGW *config)
+{
+ 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_QUERY_CONFIG, &service)) != 0)
+ return err;
+
+ lock_services();
+ config->dwServiceType = service->config.dwServiceType;
+ config->dwStartType = service->config.dwStartType;
+ config->dwErrorControl = service->config.dwErrorControl;
+ config->lpBinaryPathName = strdupW(service->config.lpBinaryPathName);
+ config->lpLoadOrderGroup = strdupW(service->config.lpLoadOrderGroup);
+ config->dwTagId = service->config.dwTagId;
+ config->lpDependencies = NULL; /* TODO */
+ config->lpServiceStartName = strdupW(service->config.lpServiceStartName);
+ config->lpDisplayName = strdupW(service->config.lpDisplayName);
+ unlock_services();
+ return ERROR_SUCCESS;
+}
+
DWORD svcctl_CloseServiceHandle(
SvcCtlRpcHandle rpc_handle,
POLICY_HANDLE *handle)
--
1.5.4
--------------080904080005010706000902--
More information about the wine-patches
mailing list