From a363b9a066ab10e384f74fe5e9b438c3a1b36999 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Miko=C5=82aj=20Zalewski?= Date: Sat, 15 Mar 2008 16:42:40 +0100 Subject: [PATCH] services: Move QueryServiceConfigW from advapi32.dll to services.exe. --- dlls/advapi32/service.c | 207 +++++++++++++----------------------------------- include/wine/svcctl.idl | 22 +++++ programs/services/rpc.c | 27 +++++++ 3 files changed, 102 insertions(+), 154 deletions(-) diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 6074afd460c..84d326b2d30 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -1850,6 +1850,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.@] */ @@ -1858,12 +1881,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); @@ -1874,58 +1896,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; @@ -1933,112 +1920,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; + *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); - 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); - } + 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 3f6e7bee03b..2a752972c7f 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 f3838d6cdda..d9c87c72484 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) { -- 2.11.4.GIT