Commit b8704a49 authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

services: Added support for SERVICE_CONFIG_PRESHUTDOWN_INFO.

parent eeb5c93a
...@@ -114,6 +114,10 @@ typedef struct _SERVICE_FAILURE_ACTIONSW { ...@@ -114,6 +114,10 @@ typedef struct _SERVICE_FAILURE_ACTIONSW {
[size_is(cActions)] SC_ACTION *lpsaActions; [size_is(cActions)] SC_ACTION *lpsaActions;
} SERVICE_FAILURE_ACTIONSW,*LPSERVICE_FAILURE_ACTIONSW; } SERVICE_FAILURE_ACTIONSW,*LPSERVICE_FAILURE_ACTIONSW;
typedef struct _SERVICE_PRESHUTDOWN_INFO {
DWORD dwPreshutdownTimeout;
} SERVICE_PRESHUTDOWN_INFO,*LPSERVICE_PRESHUTDOWN_INFO;
#define SERVICE_CONFIG_DESCRIPTION 1 #define SERVICE_CONFIG_DESCRIPTION 1
#define SERVICE_CONFIG_FAILURE_ACTIONS 2 #define SERVICE_CONFIG_FAILURE_ACTIONS 2
#define SERVICE_CONFIG_DELAYED_AUTO_START_INFO 3 #define SERVICE_CONFIG_DELAYED_AUTO_START_INFO 3
...@@ -134,6 +138,7 @@ typedef [switch_type(DWORD)] union ...@@ -134,6 +138,7 @@ typedef [switch_type(DWORD)] union
{ {
[case (SERVICE_CONFIG_DESCRIPTION)] SERVICE_DESCRIPTIONW descr; [case (SERVICE_CONFIG_DESCRIPTION)] SERVICE_DESCRIPTIONW descr;
[case (SERVICE_CONFIG_FAILURE_ACTIONS)] SERVICE_FAILURE_ACTIONSW actions; [case (SERVICE_CONFIG_FAILURE_ACTIONS)] SERVICE_FAILURE_ACTIONSW actions;
[case (SERVICE_CONFIG_PRESHUTDOWN_INFO)] SERVICE_PRESHUTDOWN_INFO preshutdown;
} SERVICE_CONFIG2W; } SERVICE_CONFIG2W;
/* Compatible with Windows function 0x00 */ /* Compatible with Windows function 0x00 */
......
...@@ -737,6 +737,14 @@ DWORD __cdecl svcctl_ChangeServiceConfig2W( SC_RPC_HANDLE hService, DWORD level, ...@@ -737,6 +737,14 @@ DWORD __cdecl svcctl_ChangeServiceConfig2W( SC_RPC_HANDLE hService, DWORD level,
wine_dbgstr_w(config->actions.lpRebootMsg), wine_dbgstr_w(config->actions.lpRebootMsg),
wine_dbgstr_w(config->actions.lpCommand) ); wine_dbgstr_w(config->actions.lpCommand) );
break; break;
case SERVICE_CONFIG_PRESHUTDOWN_INFO:
WINE_TRACE( "changing service %p preshutdown timeout to %d\n",
service, config->preshutdown.dwPreshutdownTimeout );
service_lock_exclusive( service->service_entry );
service->service_entry->preshutdown_timeout = config->preshutdown.dwPreshutdownTimeout;
save_service_config( service->service_entry );
service_unlock( service->service_entry );
break;
default: default:
WINE_FIXME("level %u not implemented\n", level); WINE_FIXME("level %u not implemented\n", level);
err = ERROR_INVALID_LEVEL; err = ERROR_INVALID_LEVEL;
...@@ -781,6 +789,18 @@ DWORD __cdecl svcctl_QueryServiceConfig2W( SC_RPC_HANDLE hService, DWORD level, ...@@ -781,6 +789,18 @@ DWORD __cdecl svcctl_QueryServiceConfig2W( SC_RPC_HANDLE hService, DWORD level,
} }
break; break;
case SERVICE_CONFIG_PRESHUTDOWN_INFO:
service_lock_shared(service->service_entry);
*needed = sizeof(SERVICE_PRESHUTDOWN_INFO);
if (size >= *needed)
((LPSERVICE_PRESHUTDOWN_INFO)buffer)->dwPreshutdownTimeout =
service->service_entry->preshutdown_timeout;
else err = ERROR_INSUFFICIENT_BUFFER;
service_unlock(service->service_entry);
break;
default: default:
WINE_FIXME("level %u not implemented\n", level); WINE_FIXME("level %u not implemented\n", level);
err = ERROR_INVALID_LEVEL; err = ERROR_INVALID_LEVEL;
......
...@@ -41,6 +41,7 @@ struct scmdatabase *active_database; ...@@ -41,6 +41,7 @@ struct scmdatabase *active_database;
DWORD service_pipe_timeout = 10000; DWORD service_pipe_timeout = 10000;
DWORD service_kill_timeout = 20000; DWORD service_kill_timeout = 20000;
static DWORD default_preshutdown_timeout = 180000;
static void *env = NULL; static void *env = NULL;
static const int is_win64 = (sizeof(void *) > sizeof(int)); static const int is_win64 = (sizeof(void *) > sizeof(int));
...@@ -64,6 +65,7 @@ static const WCHAR SZ_DEPEND_ON_GROUP[] = {'D','e','p','e','n','d','O','n','G' ...@@ -64,6 +65,7 @@ static const WCHAR SZ_DEPEND_ON_GROUP[] = {'D','e','p','e','n','d','O','n','G'
static const WCHAR SZ_OBJECT_NAME[] = {'O','b','j','e','c','t','N','a','m','e',0}; static const WCHAR SZ_OBJECT_NAME[] = {'O','b','j','e','c','t','N','a','m','e',0};
static const WCHAR SZ_TAG[] = {'T','a','g',0}; static const WCHAR SZ_TAG[] = {'T','a','g',0};
static const WCHAR SZ_DESCRIPTION[] = {'D','e','s','c','r','i','p','t','i','o','n',0}; static const WCHAR SZ_DESCRIPTION[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
static const WCHAR SZ_PRESHUTDOWN[] = {'P','r','e','s','h','u','t','d','o','w','n','T','i','m','e','o','u','t',0};
DWORD service_create(LPCWSTR name, struct service_entry **entry) DWORD service_create(LPCWSTR name, struct service_entry **entry)
...@@ -80,6 +82,7 @@ DWORD service_create(LPCWSTR name, struct service_entry **entry) ...@@ -80,6 +82,7 @@ DWORD service_create(LPCWSTR name, struct service_entry **entry)
(*entry)->control_pipe = INVALID_HANDLE_VALUE; (*entry)->control_pipe = INVALID_HANDLE_VALUE;
(*entry)->status.dwCurrentState = SERVICE_STOPPED; (*entry)->status.dwCurrentState = SERVICE_STOPPED;
(*entry)->status.dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED; (*entry)->status.dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED;
(*entry)->preshutdown_timeout = default_preshutdown_timeout;
/* all other fields are zero */ /* all other fields are zero */
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
...@@ -130,6 +133,8 @@ static DWORD load_service_config(HKEY hKey, struct service_entry *entry) ...@@ -130,6 +133,8 @@ static DWORD load_service_config(HKEY hKey, struct service_entry *entry)
return err; return err;
if ((err = load_reg_dword(hKey, SZ_TAG, &entry->config.dwTagId)) != 0) if ((err = load_reg_dword(hKey, SZ_TAG, &entry->config.dwTagId)) != 0)
return err; return err;
if ((err = load_reg_dword(hKey, SZ_PRESHUTDOWN, &entry->preshutdown_timeout)) != 0)
return err;
WINE_TRACE("Image path = %s\n", wine_dbgstr_w(entry->config.lpBinaryPathName) ); WINE_TRACE("Image path = %s\n", wine_dbgstr_w(entry->config.lpBinaryPathName) );
WINE_TRACE("Group = %s\n", wine_dbgstr_w(entry->config.lpLoadOrderGroup) ); WINE_TRACE("Group = %s\n", wine_dbgstr_w(entry->config.lpLoadOrderGroup) );
...@@ -206,9 +211,10 @@ DWORD save_service_config(struct service_entry *entry) ...@@ -206,9 +211,10 @@ DWORD save_service_config(struct service_entry *entry)
goto cleanup; goto cleanup;
if ((err = RegSetValueExW(hKey, SZ_ERROR, 0, REG_DWORD, (LPBYTE)&entry->config.dwErrorControl, sizeof(DWORD))) != 0) if ((err = RegSetValueExW(hKey, SZ_ERROR, 0, REG_DWORD, (LPBYTE)&entry->config.dwErrorControl, sizeof(DWORD))) != 0)
goto cleanup; goto cleanup;
if ((err = RegSetValueExW(hKey, SZ_TYPE, 0, REG_DWORD, (LPBYTE)&entry->config.dwServiceType, sizeof(DWORD))) != 0) if ((err = RegSetValueExW(hKey, SZ_TYPE, 0, REG_DWORD, (LPBYTE)&entry->config.dwServiceType, sizeof(DWORD))) != 0)
goto cleanup; goto cleanup;
if ((err = RegSetValueExW(hKey, SZ_PRESHUTDOWN, 0, REG_DWORD, (LPBYTE)&entry->preshutdown_timeout, sizeof(DWORD))) != 0)
goto cleanup;
if (entry->config.dwTagId) if (entry->config.dwTagId)
err = RegSetValueExW(hKey, SZ_TAG, 0, REG_DWORD, (LPBYTE)&entry->config.dwTagId, sizeof(DWORD)); err = RegSetValueExW(hKey, SZ_TAG, 0, REG_DWORD, (LPBYTE)&entry->config.dwTagId, sizeof(DWORD));
......
...@@ -39,6 +39,7 @@ struct service_entry ...@@ -39,6 +39,7 @@ struct service_entry
LPWSTR name; LPWSTR name;
SERVICE_STATUS_PROCESS status; SERVICE_STATUS_PROCESS status;
QUERY_SERVICE_CONFIGW config; QUERY_SERVICE_CONFIGW config;
DWORD preshutdown_timeout;
LPWSTR description; LPWSTR description;
LPWSTR dependOnServices; LPWSTR dependOnServices;
LPWSTR dependOnGroups; LPWSTR dependOnGroups;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment