services: Move QueryServiceConfigW from advapi32.dll 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 | 22 +++++
programs/services/rpc.c | 27 ++++++
3 files changed, 103 insertions(+), 155 deletions(-)
diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index a22c309..acb1e66 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -1849,6 +1849,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.@]
*/
@@ -1857,12 +1880,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);
@@ -1873,58 +1895,23 @@ 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 ) )
- {
- sz = ExpandEnvironmentStringsW(str_buffer,NULL,0);
- if( 0 == sz ) return FALSE;
+ memset(&config, 0, sizeof(config));
- total += sizeof(WCHAR) * sz;
- }
- else
+ if ((err = svcctl_QueryServiceConfigW(hsvc->hdr.server_handle, &config)) != 0)
{
- /* 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;
@@ -1932,112 +1919,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 d4e7081..ab189c3 100644
--- a/include/wine/svcctl.idl
+++ b/include/wine/svcctl.idl
@@ -24,6 +24,7 @@ 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}")
@@ -43,6 +44,21 @@ interface svcctl
typedef [handle] LPCWSTR MACHINE_HANDLEW;
typedef [context_handle] void *SC_RPC_HANDLE;
+cpp_quote("#if 0 /* already defined in winsvc.h */")
+typedef struct _QUERY_SERVICE_CONFIGW {
+ DWORD dwServiceType;
+ DWORD dwStartType;
+ DWORD dwErrorControl;
+ [unique] LPWSTR lpBinaryPathName;
+ [unique] LPWSTR lpLoadOrderGroup;
+ DWORD dwTagId;
+ [unique] LPWSTR lpDependencies;
+ [unique] LPWSTR lpServiceStartName;
+ [unique] LPWSTR lpDisplayName;
+} QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW;
+cpp_quote("#endif")
+
+
/* Compatible with Windows function 0x00 */
DWORD svcctl_CloseServiceHandle(
[in,out] SC_RPC_HANDLE *handle
@@ -88,4 +104,10 @@ interface svcctl
[in] DWORD dwDesiredAccess,
[out] SC_RPC_HANDLE *phService
);
+
+ /* Windows function 0x11 must be using a different prototype - not compatible */
+ DWORD svcctl_QueryServiceConfigW(
+ [in] SC_RPC_HANDLE hService,
+ [out] QUERY_SERVICE_CONFIGW *config);
+
}
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 8ef1e92..ca56a34 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -343,6 +343,33 @@ DWORD svcctl_DeleteService(
return err;
}
+DWORD svcctl_QueryServiceConfigW(
+ SC_RPC_HANDLE hService,
+ QUERY_SERVICE_CONFIGW *config)
+{
+ struct sc_service *service;
+ DWORD err;
+
+ WINE_TRACE("(%p)\n", config);
+
+ if ((err = validate_service_handle(hService, SERVICE_QUERY_CONFIG, &service)) != 0)
+ return err;
+
+ lock_services();
+ config->dwServiceType = service->service_entry->config.dwServiceType;
+ config->dwStartType = service->service_entry->config.dwStartType;
+ config->dwErrorControl = service->service_entry->config.dwErrorControl;
+ config->lpBinaryPathName = strdupW(service->service_entry->config.lpBinaryPathName);
+ config->lpLoadOrderGroup = strdupW(service->service_entry->config.lpLoadOrderGroup);
+ config->dwTagId = service->service_entry->config.dwTagId;
+ config->lpDependencies = NULL; /* TODO */
+ config->lpServiceStartName = strdupW(service->service_entry->config.lpServiceStartName);
+ config->lpDisplayName = strdupW(service->service_entry->config.lpDisplayName);
+ unlock_services();
+
+ return ERROR_SUCCESS;
+}
+
DWORD svcctl_CloseServiceHandle(
SC_RPC_HANDLE *handle)
{
--
1.5.3.GIT
--------------020702060306030905040607--
More information about the wine-patches
mailing list