advapi32: Reimplemented ChangeServiceConfig2W in services.exe.
diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index da2b81f..0724035 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -2112,8 +2112,8 @@
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 @@
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 7e5a0a6..66abd30 100644
--- a/include/wine/svcctl.idl
+++ b/include/wine/svcctl.idl
@@ -89,8 +89,19 @@
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 @@
/* 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 6cc2e4a..b6ca9f2 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -609,6 +609,43 @@
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 @@
return ERROR_CALL_NOT_IMPLEMENTED;
}
-DWORD svcctl_ChangeServiceConfig2W(
- void)
-{
- WINE_FIXME("\n");
- return ERROR_CALL_NOT_IMPLEMENTED;
-}
-
DWORD svcctl_QueryServiceConfig2A(
void)
{