diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index da2b81f163a..0724035b444 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -2112,8 +2112,8 @@ BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel, BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel, LPVOID lpInfo) { - HKEY hKey; struct sc_service *hsvc; + DWORD err; hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE); if (!hsvc) @@ -2121,26 +2121,21 @@ BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel, SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } - hKey = hsvc->hkey; - if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) + __TRY { - static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0}; - LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo; - if (sd->lpDescription) - { - TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription)); - if (sd->lpDescription[0] == 0) - RegDeleteValueW(hKey,szDescription); - else - RegSetValueExW(hKey, szDescription, 0, REG_SZ, - (LPVOID)sd->lpDescription, - sizeof(WCHAR)*(strlenW(sd->lpDescription)+1)); - } + err = svcctl_ChangeServiceConfig2W( hsvc->hdr.server_handle, dwInfoLevel, lpInfo ); } - else - FIXME("STUB: %p %d %p\n",hService, dwInfoLevel, lpInfo); - return TRUE; + __EXCEPT(rpc_filter) + { + err = map_exception_code(GetExceptionCode()); + } + __ENDTRY + + if (err != ERROR_SUCCESS) + SetLastError(err); + + return err == ERROR_SUCCESS; } /****************************************************************************** diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl index 7e5a0a68418..66abd30f954 100644 --- a/include/wine/svcctl.idl +++ b/include/wine/svcctl.idl @@ -89,8 +89,19 @@ typedef struct _SERVICE_STATUS { typedef enum _SC_STATUS_TYPE { SC_STATUS_PROCESS_INFO = 0 } SC_STATUS_TYPE; + +typedef struct _SERVICE_DESCRIPTIONW { + LPWSTR lpDescription; +} SERVICE_DESCRIPTIONW,*LPSERVICE_DESCRIPTIONW; + +#define SERVICE_CONFIG_DESCRIPTION 1 + cpp_quote("#endif") +typedef [switch_type(DWORD)] union +{ + [case (SERVICE_CONFIG_DESCRIPTION)] SERVICE_DESCRIPTIONW descr; +} SERVICE_CONFIG2W; /* Compatible with Windows function 0x00 */ DWORD svcctl_CloseServiceHandle( @@ -276,8 +287,11 @@ cpp_quote("#endif") /* Not compatible with Windows function 0x24 */ DWORD svcctl_ChangeServiceConfig2A(/* FIXME */); - /* Not compatible with Windows function 0x25 */ - DWORD svcctl_ChangeServiceConfig2W(/* FIXME */); + /* Untested with Windows function 0x25 */ + DWORD svcctl_ChangeServiceConfig2W( + [in] SC_RPC_HANDLE hService, + [in] DWORD InfoLevel, + [in,switch_is(InfoLevel)] SERVICE_CONFIG2W *config ); /* Not compatible with Windows function 0x26 */ DWORD svcctl_QueryServiceConfig2A(/* FIXME */); diff --git a/programs/services/rpc.c b/programs/services/rpc.c index 6cc2e4ad449..b6ca9f26dcd 100644 --- a/programs/services/rpc.c +++ b/programs/services/rpc.c @@ -609,6 +609,43 @@ DWORD svcctl_SetServiceStatus( return ERROR_SUCCESS; } +DWORD svcctl_ChangeServiceConfig2W( SC_RPC_HANDLE hService, DWORD level, SERVICE_CONFIG2W *config ) +{ + struct sc_service_handle *service; + DWORD err; + + if ((err = validate_service_handle(hService, SERVICE_CHANGE_CONFIG, &service)) != 0) + return err; + + switch (level) + { + case SERVICE_CONFIG_DESCRIPTION: + { + WCHAR *descr = NULL; + + if (config->descr.lpDescription[0]) + { + if (!(descr = strdupW( config->descr.lpDescription ))) + return ERROR_NOT_ENOUGH_MEMORY; + } + + WINE_TRACE( "changing service %p descr to %s\n", service, wine_dbgstr_w(descr) ); + service_lock_exclusive( service->service_entry ); + HeapFree( GetProcessHeap(), 0, service->service_entry->description ); + service->service_entry->description = descr; + save_service_config( service->service_entry ); + service_unlock( service->service_entry ); + } + break; + + default: + WINE_FIXME("level %u not implemented\n", level); + err = ERROR_INVALID_LEVEL; + break; + } + return err; +} + DWORD svcctl_QueryServiceStatusEx( SC_RPC_HANDLE hService, SC_STATUS_TYPE InfoLevel, @@ -1097,13 +1134,6 @@ DWORD svcctl_ChangeServiceConfig2A( return ERROR_CALL_NOT_IMPLEMENTED; } -DWORD svcctl_ChangeServiceConfig2W( - void) -{ - WINE_FIXME("\n"); - return ERROR_CALL_NOT_IMPLEMENTED; -} - DWORD svcctl_QueryServiceConfig2A( void) {