-- v2: services: Add support for ChangeServiceConfig2(SERVICE_CONFIG_DELAYED_AUTO_START_INFO). advapi32/tests: Add some tests for SERVICE_CONFIG_DELAYED_AUTO_START_INFO.
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/advapi32/tests/service.c | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index f701197f372..ef4de0b1845 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -2213,6 +2213,7 @@ static void test_queryconfig2(void) LPSERVICE_DESCRIPTIONA pConfig = (LPSERVICE_DESCRIPTIONA)buffer; LPSERVICE_DESCRIPTIONW pConfigW = (LPSERVICE_DESCRIPTIONW)buffer; SERVICE_PRESHUTDOWN_INFO preshutdown_info; + SERVICE_DELAYED_AUTO_START_INFO auto_start_info; static const CHAR servicename [] = "winetest_query_config2"; static const CHAR displayname [] = "Winetest dummy service"; static const CHAR pathname [] = "we_dont_care.exe"; @@ -2443,6 +2444,7 @@ static void test_queryconfig2(void) "expected lpDescription to be null, got %s\n", wine_dbgstr_w(pConfigW->lpDescription));
SetLastError(0xdeadbeef); + needed = 0; ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO, (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed); if(!ret && GetLastError()==ERROR_INVALID_LEVEL) @@ -2470,6 +2472,44 @@ static void test_queryconfig2(void) ok(preshutdown_info.dwPreshutdownTimeout == -1, "New PreshutdownTimeout = %ld\n", preshutdown_info.dwPreshutdownTimeout);
+ SetLastError(0xdeadbeef); + needed = 0; + auto_start_info.fDelayedAutostart = 0xdeadbeef; + ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, + (LPBYTE)&auto_start_info, sizeof(auto_start_info), &needed); + todo_wine + ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError()); + todo_wine + ok(needed == sizeof(auto_start_info), "needed = %ld\n", needed); + todo_wine + ok(auto_start_info.fDelayedAutostart == 0, "fDelayedAutostart = %d\n", auto_start_info.fDelayedAutostart); + + SetLastError(0xdeadbeef); + auto_start_info.fDelayedAutostart = 3; + ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, + (LPBYTE)&auto_start_info); + ok(!ret, "expected ChangeServiceConfig2A to fail\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %ld\n", GetLastError()); + + SetLastError(0xdeadbeef); + auto_start_info.fDelayedAutostart = 1; + ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, + (LPBYTE)&auto_start_info); + todo_wine + ok(ret, "expected ChangeServiceConfig2A to succeed (%ld)\n", GetLastError()); + + SetLastError(0xdeadbeef); + needed = 0; + auto_start_info.fDelayedAutostart = 0xdeadbeef; + ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, + (LPBYTE)&auto_start_info, sizeof(auto_start_info), &needed); + todo_wine + ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError()); + todo_wine + ok(needed == sizeof(auto_start_info), "needed = %ld\n", needed); + todo_wine + ok(auto_start_info.fDelayedAutostart == 1, "fDelayedAutostart = %d\n", auto_start_info.fDelayedAutostart); + cleanup: DeleteService(svc_handle); CloseServiceHandle(svc_handle);
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/advapi32/tests/service.c | 1 - dlls/sechost/service.c | 2 +- programs/services/rpc.c | 12 ++++++++++++ programs/services/services.c | 8 ++++++++ 4 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index ef4de0b1845..3f1a9015429 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -2495,7 +2495,6 @@ static void test_queryconfig2(void) auto_start_info.fDelayedAutostart = 1; ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, (LPBYTE)&auto_start_info); - todo_wine ok(ret, "expected ChangeServiceConfig2A to succeed (%ld)\n", GetLastError());
SetLastError(0xdeadbeef); diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index 915b0b4ebe0..159f9e1d2a3 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -500,7 +500,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH ChangeServiceConfig2A( SC_HANDLE service, DWORD le free( faw.lpRebootMsg ); free( faw.lpCommand ); } - else if (level == SERVICE_CONFIG_PRESHUTDOWN_INFO) + else if (level == SERVICE_CONFIG_PRESHUTDOWN_INFO || level == SERVICE_CONFIG_DELAYED_AUTO_START_INFO) { r = ChangeServiceConfig2W( service, level, info ); } diff --git a/programs/services/rpc.c b/programs/services/rpc.c index 835516861f0..5bc692a3e18 100644 --- a/programs/services/rpc.c +++ b/programs/services/rpc.c @@ -975,6 +975,18 @@ DWORD __cdecl svcctl_ChangeServiceConfig2W( SC_RPC_HANDLE hService, SC_RPC_CONFI save_service_config( service->service_entry ); service_unlock( service->service_entry ); break; + case SERVICE_CONFIG_DELAYED_AUTO_START_INFO: + WINE_TRACE( "SERVICE_CONFIG_DELAYED_AUTO_START_INFO: fDelayedAutostart %d\n", + config.delayedstart->fDelayedAutostart); + + if (config.delayedstart->fDelayedAutostart && config.delayedstart->fDelayedAutostart != 1) + return ERROR_INVALID_PARAMETER; + + service_lock( service->service_entry ); + service->service_entry->delayed_autostart = config.delayedstart->fDelayedAutostart; + save_service_config( service->service_entry ); + service_unlock( service->service_entry ); + break; default: WINE_FIXME("level %lu not implemented\n", config.dwInfoLevel); err = ERROR_INVALID_LEVEL; diff --git a/programs/services/services.c b/programs/services/services.c index 273a146c784..9636752438e 100644 --- a/programs/services/services.c +++ b/programs/services/services.c @@ -275,6 +275,14 @@ DWORD save_service_config(struct service_entry *entry) goto cleanup; if ((err = RegSetValueExW(hKey, SZ_PRESHUTDOWN, 0, REG_DWORD, (LPBYTE)&entry->preshutdown_timeout, sizeof(DWORD))) != 0) goto cleanup; + + if (entry->delayed_autostart) + err = RegSetValueExW(hKey, SZ_DELAYED_AUTOSTART, 0, REG_DWORD, (LPBYTE)&entry->delayed_autostart, sizeof(DWORD)); + else + err = RegDeleteValueW(hKey, SZ_DELAYED_AUTOSTART); + if (err != 0 && err != ERROR_FILE_NOT_FOUND) + goto cleanup; + if (entry->is_wow64) { const DWORD is_wow64 = 1;