From 67797880909e94fd325d6b1f9a1f46351b4ce4cd Mon Sep 17 00:00:00 2001 From: Mikolaj Zalewski Date: Tue, 25 Sep 2007 16:19:56 -0700 Subject: [PATCH] services.exe/advapi32: move QueryServiceConfig to services.exe --- dlls/advapi32/service.c | 207 +++++++++++------------------------------------ include/wine/svcctl.idl | 26 ++++++ programs/services/rpc.c | 26 ++++++ 3 files changed, 101 insertions(+), 158 deletions(-) diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index f031021..a7ad8dc 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -1918,6 +1918,28 @@ 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); + if (buf) + { + 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 move_string_to_buffer(NULL, &string); +} + /****************************************************************************** * QueryServiceConfigW [ADVAPI32.@] */ @@ -1926,12 +1948,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); @@ -1942,58 +1963,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 ) ) - { - sz = ExpandEnvironmentStringsW(str_buffer,NULL,0); - if( 0 == sz ) return FALSE; - total += sizeof(WCHAR) * sz; - } - else + if ((err = svcctl_QueryServiceConfigW(hsvc->hdr.rpc_handle, &hsvc->hdr.server_handle, &config)) != 0) { - /* FIXME: set last error */ - return FALSE; + TRACE("services.exe: error %d\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; @@ -2001,114 +1985,23 @@ 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( n < 0 ) + if (bufpos - (LPBYTE)lpServiceConfig > cbBufSize) ERR("Buffer overflow!\n"); TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) ); diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl index 70ee29b..ad0d51f 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 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, @@ -94,10 +111,17 @@ cpp_quote("#define SVCCTL_STARTED_EVENT /* Compatible with Windows function 0x10 */ DWORD svcctl_OpenServiceW( - SvcCtlRpcHandle rpc_handle, + SvcCtlRpcHandle rpc_handle, [in] POLICY_HANDLE *hSCManager, [in] LPCWSTR lpServiceName, [in] DWORD dwDesiredAccess, [out] POLICY_HANDLE *phService ); + + /* Windows function 0x11 must be using a different prototype - not compatible */ + 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 daa9ff2..4aefdd9 100644 --- a/programs/services/rpc.c +++ b/programs/services/rpc.c @@ -357,6 +357,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.4.1