Index: base/system/services/database.c =================================================================== --- base/system/services/database.c (révision 58508) +++ base/system/services/database.c (copie de travail) @@ -38,6 +38,7 @@ static RTL_RESOURCE DatabaseLock; static DWORD ResumeCount = 1; +/* The critical section synchronizes service controls commands */ static CRITICAL_SECTION ControlServiceCriticalSection; static DWORD PipeTimeout = 30000; /* 30 Seconds */ @@ -359,7 +360,7 @@ DWORD ScmCreateNewServiceRecord(LPCWSTR lpServiceName, - PSERVICE *lpServiceRecord) + PSERVICE* lpServiceRecord) { PSERVICE lpService = NULL; @@ -772,13 +773,11 @@ if (Service->Status.dwServiceType == SERVICE_KERNEL_DRIVER) { - RtlInitUnicodeString(&DirName, - L"\\Driver"); + RtlInitUnicodeString(&DirName, L"\\Driver"); } - else + else // if (Service->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER) { - RtlInitUnicodeString(&DirName, - L"\\FileSystem"); + RtlInitUnicodeString(&DirName, L"\\FileSystem"); } InitializeObjectAttributes(&ObjectAttributes, @@ -796,7 +795,7 @@ } BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) + - 2 * MAX_PATH * sizeof(WCHAR); + 2 * MAX_PATH * sizeof(WCHAR); DirInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BufferLength); @@ -1096,7 +1095,7 @@ static DWORD ScmSendStartCommand(PSERVICE Service, DWORD argc, - LPWSTR *argv) + LPWSTR* argv) { PSCM_CONTROL_PACKET ControlPacket; SCM_REPLY_PACKET ReplyPacket; @@ -1496,7 +1495,7 @@ static DWORD ScmStartUserModeService(PSERVICE Service, DWORD argc, - LPWSTR *argv) + LPWSTR* argv) { PROCESS_INFORMATION ProcessInformation; STARTUPINFOW StartupInfo; @@ -1512,6 +1511,7 @@ return ScmSendStartCommand(Service, argc, argv); } + /* Otherwise start its process */ ZeroMemory(&StartupInfo, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); ZeroMemory(&ProcessInformation, sizeof(ProcessInformation)); @@ -1551,9 +1551,7 @@ if (dwError == ERROR_SUCCESS) { /* Send start command */ - dwError = ScmSendStartCommand(Service, - argc, - argv); + dwError = ScmSendStartCommand(Service, argc, argv); } else { @@ -1569,24 +1567,22 @@ } -DWORD -ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv) +static DWORD +ScmReallyStartService(PSERVICE Service, + DWORD argc, + LPWSTR* argv) { PSERVICE_GROUP Group = Service->lpGroup; DWORD dwError = ERROR_SUCCESS; LPCWSTR ErrorLogStrings[2]; WCHAR szErrorBuffer[32]; - DPRINT("ScmStartService() called\n"); - + DPRINT("ScmReallyStartService() called\n"); DPRINT("Start Service %p (%S)\n", Service, Service->lpServiceName); - EnterCriticalSection(&ControlServiceCriticalSection); - if (Service->Status.dwCurrentState != SERVICE_STOPPED) { DPRINT("Service %S is already running!\n", Service->lpServiceName); - LeaveCriticalSection(&ControlServiceCriticalSection); return ERROR_SERVICE_ALREADY_RUNNING; } @@ -1602,7 +1598,7 @@ Service->Status.dwCurrentState = SERVICE_RUNNING; } } - else + else // if (Service->Status.dwServiceType & (SERVICE_WIN32 | SERVICE_INTERACTIVE_PROCESS)) { /* Start user-mode service */ dwError = ScmCreateOrReferenceServiceImage(Service); @@ -1625,10 +1621,8 @@ } } - LeaveCriticalSection(&ControlServiceCriticalSection); + DPRINT("ScmReallyStartService() done (Error %lu)\n", dwError); - DPRINT("ScmStartService() done (Error %lu)\n", dwError); - if (dwError == ERROR_SUCCESS) { if (Group != NULL) @@ -1677,18 +1671,81 @@ } +DWORD +ScmStartService(PSERVICE Service, + DWORD argc, + LPWSTR* argv) +{ + DWORD dwError = ERROR_SUCCESS; + SC_RPC_LOCK Lock = NULL; + + DPRINT("ScmStartService() called\n"); + DPRINT("Start Service %p (%S)\n", Service, Service->lpServiceName); + + /* Acquire the service control critical section, to synchronize starts */ + EnterCriticalSection(&ControlServiceCriticalSection); + + /* + * Acquire the user service start lock while the service is starting, if + * needed (i.e. if we are not starting it during the initialization phase). + * If we don't success, bail out. + */ + if (!ScmInitialize) + { + dwError = ScmAcquireServiceStartLock(TRUE, &Lock); + if (dwError != ERROR_SUCCESS) goto done; + } + + /* Really start the service */ + dwError = ScmReallyStartService(Service, argc, argv); + + /* Release the service start lock, if needed, and the critical section */ + if (Lock) ScmReleaseServiceStartLock(&Lock); + +done: + LeaveCriticalSection(&ControlServiceCriticalSection); + + DPRINT("ScmStartService() done (Error %lu)\n", dwError); + + return dwError; +} + + VOID ScmAutoStartServices(VOID) { + DWORD dwError = ERROR_SUCCESS; + SC_RPC_LOCK Lock = NULL; + PLIST_ENTRY GroupEntry; PLIST_ENTRY ServiceEntry; PSERVICE_GROUP CurrentGroup; PSERVICE CurrentService; WCHAR szSafeBootServicePath[MAX_PATH]; - DWORD dwError; HKEY hKey; ULONG i; + /* Acquire the service control critical section, to synchronize starts */ + EnterCriticalSection(&ControlServiceCriticalSection); + + /* + * Acquire the user service start lock while the service is starting, if + * needed (i.e. if we are not starting it during the initialization phase). + * If we don't success, bail out. + */ + if (!ScmInitialize) + { + /* + * Actually this code is never executed since we are called + * at initialization time, so that ScmInitialize == TRUE. + * But keep the code here if someday we are called later on + * for whatever reason... + */ + dwError = ScmAcquireServiceStartLock(TRUE, &Lock); + if (dwError != ERROR_SUCCESS) goto done; + } + + /* Clear 'ServiceVisited' flag (or set if not to start in Safe Mode) */ ServiceEntry = ServiceListHead.Flink; while (ServiceEntry != &ServiceListHead) @@ -1779,7 +1836,7 @@ (CurrentService->dwTag == CurrentGroup->TagArray[i])) { CurrentService->ServiceVisited = TRUE; - ScmStartService(CurrentService, 0, NULL); + ScmReallyStartService(CurrentService, 0, NULL); } ServiceEntry = ServiceEntry->Flink; @@ -1797,7 +1854,7 @@ (CurrentService->ServiceVisited == FALSE)) { CurrentService->ServiceVisited = TRUE; - ScmStartService(CurrentService, 0, NULL); + ScmReallyStartService(CurrentService, 0, NULL); } ServiceEntry = ServiceEntry->Flink; @@ -1817,7 +1874,7 @@ (CurrentService->ServiceVisited == FALSE)) { CurrentService->ServiceVisited = TRUE; - ScmStartService(CurrentService, 0, NULL); + ScmReallyStartService(CurrentService, 0, NULL); } ServiceEntry = ServiceEntry->Flink; @@ -1834,7 +1891,7 @@ (CurrentService->ServiceVisited == FALSE)) { CurrentService->ServiceVisited = TRUE; - ScmStartService(CurrentService, 0, NULL); + ScmReallyStartService(CurrentService, 0, NULL); } ServiceEntry = ServiceEntry->Flink; @@ -1848,6 +1905,13 @@ CurrentService->ServiceVisited = FALSE; ServiceEntry = ServiceEntry->Flink; } + + + /* Release the service start lock, if needed, and the critical section */ + if (Lock) ScmReleaseServiceStartLock(&Lock); + +done: + LeaveCriticalSection(&ControlServiceCriticalSection); } Index: base/system/services/driver.c =================================================================== --- base/system/services/driver.c (révision 58508) +++ base/system/services/driver.c (copie de travail) @@ -141,13 +141,11 @@ if (lpService->Status.dwServiceType == SERVICE_KERNEL_DRIVER) { - RtlInitUnicodeString(&DirName, - L"\\Driver"); + RtlInitUnicodeString(&DirName, L"\\Driver"); } - else + else // if (lpService->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER) { - RtlInitUnicodeString(&DirName, - L"\\FileSystem"); + RtlInitUnicodeString(&DirName, L"\\FileSystem"); } InitializeObjectAttributes(&ObjectAttributes, Index: base/system/services/lock.c =================================================================== --- base/system/services/lock.c (révision 58508) +++ base/system/services/lock.c (copie de travail) @@ -2,7 +2,7 @@ * PROJECT: ReactOS Service Control Manager * LICENSE: GPL - See COPYING in the top level directory * FILE: base/system/services/lock.c - * PURPOSE: Service lock functions + * PURPOSE: User-side Services Start Serialization Lock functions * COPYRIGHT: Copyright 2012 Hermès Bélusca */ @@ -16,6 +16,7 @@ /* GLOBALS *******************************************************************/ +/* The unique user service start lock of the SCM */ static PSTART_LOCK pServiceStartLock = NULL; Index: base/system/services/rpcserver.c =================================================================== --- base/system/services/rpcserver.c (révision 58508) +++ base/system/services/rpcserver.c (copie de travail) @@ -2895,7 +2895,6 @@ DWORD dwError = ERROR_SUCCESS; PSERVICE_HANDLE hSvc; PSERVICE lpService = NULL; - SC_RPC_LOCK Lock = NULL; #ifndef NDEBUG DWORD i; @@ -2941,17 +2940,9 @@ if (lpService->bDeleted) return ERROR_SERVICE_MARKED_FOR_DELETE; - /* Acquire the service start lock until the service has been started */ - dwError = ScmAcquireServiceStartLock(TRUE, &Lock); - if (dwError != ERROR_SUCCESS) - return dwError; - /* Start the service */ dwError = ScmStartService(lpService, argc, (LPWSTR*)argv); - /* Release the service start lock */ - ScmReleaseServiceStartLock(&Lock); - return dwError; } @@ -4171,7 +4162,6 @@ DWORD dwError = ERROR_SUCCESS; PSERVICE_HANDLE hSvc; PSERVICE lpService = NULL; - SC_RPC_LOCK Lock = NULL; LPWSTR *lpVector = NULL; DWORD i; DWORD dwLength; @@ -4244,17 +4234,9 @@ } } - /* Acquire the service start lock until the service has been started */ - dwError = ScmAcquireServiceStartLock(TRUE, &Lock); - if (dwError != ERROR_SUCCESS) - goto done; - /* Start the service */ dwError = ScmStartService(lpService, argc, lpVector); - /* Release the service start lock */ - ScmReleaseServiceStartLock(&Lock); - done: /* Free the Unicode argument vector */ if (lpVector != NULL) Index: base/system/services/services.c =================================================================== --- base/system/services/services.c (révision 58508) +++ base/system/services/services.c (copie de travail) @@ -22,6 +22,7 @@ #define PIPE_BUFSIZE 1024 #define PIPE_TIMEOUT 1000 +BOOL ScmInitialize = FALSE; BOOL ScmShutdown = FALSE; static HANDLE hScmShutdownEvent = NULL; @@ -357,6 +358,9 @@ DPRINT("SERVICES: Service Control Manager\n"); + /* We are initializing ourselves */ + ScmInitialize = TRUE; + /* Create start event */ if (!ScmCreateStartEvent(&hScmStartEvent)) { @@ -400,14 +404,17 @@ /* Update the services database */ ScmGetBootAndSystemDriverState(); - /* Register the Service Control Manager process with CSRSS */ + /* Register the Service Control Manager process with the ReactOS Subsystem */ if (!RegisterServicesProcess(GetCurrentProcessId())) { DPRINT1("SERVICES: Could not register SCM process\n"); goto done; } - /* Acquire the service start lock until autostart services have been started */ + /* + * Acquire the user service start lock until + * autostart services have been started. + */ dwError = ScmAcquireServiceStartLock(TRUE, &Lock); if (dwError != ERROR_SUCCESS) { @@ -437,6 +444,9 @@ /* Release the service start lock */ ScmReleaseServiceStartLock(&Lock); + /* Initialization finished */ + ScmInitialize = FALSE; + DPRINT("SERVICES: Running.\n"); /* Wait until the shutdown event gets signaled */ Index: base/system/services/services.h =================================================================== --- base/system/services/services.h (révision 58508) +++ base/system/services/services.h (copie de travail) @@ -86,6 +86,7 @@ extern LIST_ENTRY ServiceListHead; extern LIST_ENTRY GroupListHead; extern LIST_ENTRY ImageListHead; +extern BOOL ScmInitialize; extern BOOL ScmShutdown;