From 4c01feb7146a47df41eedd1da0bb540a37d7d7de Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Thu, 18 Aug 2016 09:30:33 +0200 Subject: [PATCH] services: Hold startup lock before calling service_start. Signed-off-by: Sebastian Lackner Signed-off-by: Alexandre Julliard --- programs/services/rpc.c | 9 ++++++--- programs/services/services.c | 15 ++++----------- programs/services/services.h | 2 +- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/programs/services/rpc.c b/programs/services/rpc.c index 977ddb63dec..4cab79ec28d 100644 --- a/programs/services/rpc.c +++ b/programs/services/rpc.c @@ -1071,8 +1071,12 @@ DWORD __cdecl svcctl_StartServiceW( if (service->service_entry->config.dwStartType == SERVICE_DISABLED) return ERROR_SERVICE_DISABLED; + if (!scmdatabase_lock_startup(service->service_entry->db)) + return ERROR_SERVICE_DATABASE_LOCKED; + err = service_start(service->service_entry, dwNumServiceArgs, lpServiceArgVectors); + scmdatabase_unlock_startup(service->service_entry->db); return err; } @@ -1226,9 +1230,8 @@ DWORD __cdecl svcctl_LockServiceDatabase( if ((err = validate_scm_handle(hSCManager, SC_MANAGER_LOCK, &manager)) != ERROR_SUCCESS) return err; - err = scmdatabase_lock_startup(manager->db); - if (err != ERROR_SUCCESS) - return err; + if (!scmdatabase_lock_startup(manager->db)) + return ERROR_SERVICE_DATABASE_LOCKED; lock = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sc_lock)); if (!lock) diff --git a/programs/services/services.c b/programs/services/services.c index 177acf10e4b..9156dbc6d68 100644 --- a/programs/services/services.c +++ b/programs/services/services.c @@ -352,6 +352,7 @@ static void scmdatabase_autostart_services(struct scmdatabase *db) size = i; scmdatabase_unlock(db); + while (!scmdatabase_lock_startup(db)) Sleep(10); for (i = 0; i < size; i++) { @@ -364,6 +365,7 @@ static void scmdatabase_autostart_services(struct scmdatabase *db) release_service(service); } + scmdatabase_unlock_startup(db); HeapFree(GetProcessHeap(), 0, services_list); } @@ -608,11 +610,9 @@ static DWORD scmdatabase_load_services(struct scmdatabase *db) return ERROR_SUCCESS; } -DWORD scmdatabase_lock_startup(struct scmdatabase *db) +BOOL scmdatabase_lock_startup(struct scmdatabase *db) { - if (InterlockedCompareExchange(&db->service_start_lock, TRUE, FALSE)) - return ERROR_SERVICE_DATABASE_LOCKED; - return ERROR_SUCCESS; + return !InterlockedCompareExchange(&db->service_start_lock, TRUE, FALSE); } void scmdatabase_unlock_startup(struct scmdatabase *db) @@ -904,10 +904,6 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR * struct process_entry *process = NULL; DWORD err; - err = scmdatabase_lock_startup(service->db); - if (err != ERROR_SUCCESS) - return err; - err = service_start_process(service, &process); if (err == ERROR_SUCCESS) { @@ -928,10 +924,7 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR * release_process(process); } - scmdatabase_unlock_startup(service->db); - WINE_TRACE("returning %d\n", err); - return err; } diff --git a/programs/services/services.h b/programs/services/services.h index a3ecdf280db..fb1374e4c03 100644 --- a/programs/services/services.h +++ b/programs/services/services.h @@ -72,7 +72,7 @@ struct service_entry *scmdatabase_find_service(struct scmdatabase *db, LPCWSTR n struct service_entry *scmdatabase_find_service_by_displayname(struct scmdatabase *db, LPCWSTR name); DWORD scmdatabase_add_service(struct scmdatabase *db, struct service_entry *entry); -DWORD scmdatabase_lock_startup(struct scmdatabase *db); +BOOL scmdatabase_lock_startup(struct scmdatabase *db); void scmdatabase_unlock_startup(struct scmdatabase *db); void scmdatabase_lock(struct scmdatabase *db); -- 2.11.4.GIT