Index: base/system/services/database.c =================================================================== --- base/system/services/database.c (révision 58514) +++ base/system/services/database.c (copie de travail) @@ -21,7 +21,7 @@ * Uncomment the line below to start services * using the SERVICE_START_PENDING state */ -// #define USE_SERVICE_START_PENDING +#define USE_SERVICE_START_PENDING /* * Uncomment the line below to use asynchronous IO operations @@ -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/rpcserver.c =================================================================== --- base/system/services/rpcserver.c (révision 58514) +++ 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 58514) +++ base/system/services/services.c (copie de travail) @@ -22,6 +22,13 @@ #define PIPE_BUFSIZE 1024 #define PIPE_TIMEOUT 1000 +#ifndef SCM_START_EVENT /* Defined in include/reactos/services/services.h */ + #define SCM_START_EVENT L"SvcctrlStartEvent_A3752DX" +#endif +#define SCM_AUTOSTARTCOMPLETE_EVENT L"SC_AutoStartComplete" +#define LSA_RPC_SERVER_ACTIVE L"LSA_RPC_SERVER_ACTIVE" + +BOOL ScmInitialize = FALSE; BOOL ScmShutdown = FALSE; static HANDLE hScmShutdownEvent = NULL; @@ -77,35 +84,38 @@ BOOL -ScmCreateStartEvent(PHANDLE StartEvent) +ScmCreateControlEvent(PHANDLE Event, + LPCWSTR Name, + DWORD dwDesiredAccess) { + /* + * This function creates a generic non-inheritable event + * and return a handle to the caller. The caller must + * close this handle afterwards. + */ + HANDLE hEvent; - hEvent = CreateEventW(NULL, - TRUE, - FALSE, - L"SvcctrlStartEvent_A3752DX"); + hEvent = CreateEventW(NULL, TRUE, FALSE, Name); if (hEvent == NULL) { if (GetLastError() == ERROR_ALREADY_EXISTS) { - hEvent = OpenEventW(EVENT_ALL_ACCESS, - FALSE, - L"SvcctrlStartEvent_A3752DX"); - if (hEvent == NULL) - { - return FALSE; - } + hEvent = OpenEventW(dwDesiredAccess, FALSE, Name); } - else - { - return FALSE; - } } - *StartEvent = hEvent; - - return TRUE; + if (hEvent) + { + DPRINT("SERVICES: Created event %S with handle %x\n", Name, hEvent); + *Event = hEvent; + return TRUE; + } + else + { + DPRINT1("SERVICES: Failed to create event %S (Error %lu)\n", Name, GetLastError()); + return FALSE; + } } @@ -113,37 +123,24 @@ ScmWaitForLsa(VOID) { HANDLE hEvent; - DWORD dwError; - hEvent = CreateEventW(NULL, - TRUE, - FALSE, - L"LSA_RPC_SERVER_ACTIVE"); - if (hEvent == NULL) + if (!ScmCreateControlEvent(&hEvent, + LSA_RPC_SERVER_ACTIVE, + SYNCHRONIZE)) { - dwError = GetLastError(); - DPRINT1("Failed to create the notication event (Error %lu)\n", dwError); + DPRINT1("Failed to create the notification event (Error %lu)\n", GetLastError()); + } + else + { + DPRINT("Wait for the LSA server!\n"); + WaitForSingleObject(hEvent, INFINITE); + DPRINT("LSA server running!\n"); - if (dwError == ERROR_ALREADY_EXISTS) - { - hEvent = OpenEventW(SYNCHRONIZE, - FALSE, - L"LSA_RPC_SERVER_ACTIVE"); - if (hEvent == NULL) - { - DPRINT1("Could not open the notification event (Error %lu)\n", GetLastError()); - return; - } - } + CloseHandle(hEvent); } - DPRINT("Wait for the LSA server!\n"); - WaitForSingleObject(hEvent, INFINITE); - DPRINT("LSA server running!\n"); - - CloseHandle(hEvent); - DPRINT("ScmWaitForLsa() done\n"); + return; } @@ -351,23 +348,38 @@ int nShowCmd) { HANDLE hScmStartEvent = NULL; + HANDLE hScmAutoStartCompleteEvent = NULL; SC_RPC_LOCK Lock = NULL; BOOL bCanDeleteNamedPipeCriticalSection = FALSE; DWORD dwError; DPRINT("SERVICES: Service Control Manager\n"); - /* Create start event */ - if (!ScmCreateStartEvent(&hScmStartEvent)) + /* We are initializing ourselves */ + ScmInitialize = TRUE; + + /* Create the start event */ + if (!ScmCreateControlEvent(&hScmStartEvent, + SCM_START_EVENT, + EVENT_ALL_ACCESS)) { - DPRINT1("SERVICES: Failed to create start event\n"); + DPRINT1("SERVICES: Failed to create the start event\n"); goto done; } - DPRINT("SERVICES: created start event with handle %p.\n", hScmStartEvent); + /* Create the auto-start complete event */ + if (!ScmCreateControlEvent(&hScmAutoStartCompleteEvent, + SCM_AUTOSTARTCOMPLETE_EVENT, + EVENT_ALL_ACCESS)) + { + DPRINT1("SERVICES: Failed to create the auto-start complete event\n"); + goto done; + } + DPRINT("SERVICES: created auto-start complete event with handle %p.\n", hScmAutoStartCompleteEvent); + /* Create the shutdown event */ - hScmShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + hScmShutdownEvent = CreateEventW(NULL, TRUE, FALSE, NULL); if (hScmShutdownEvent == NULL) { DPRINT1("SERVICES: Failed to create shutdown event\n"); @@ -397,17 +409,23 @@ goto done; } + /* Wait for the LSA server */ + ScmWaitForLsa(); + /* 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) { @@ -418,25 +436,31 @@ /* Start the RPC server */ ScmStartRpcServer(); - DPRINT("SERVICES: Initialized.\n"); - /* Signal start event */ SetEvent(hScmStartEvent); + DPRINT("SERVICES: Initialized.\n"); + /* Register event handler (used for system shutdown) */ SetConsoleCtrlHandler(ShutdownHandlerRoutine, TRUE); - /* Wait for the LSA server */ - ScmWaitForLsa(); + // /* Wait for the LSA server */ + // ScmWaitForLsa(); /* Start auto-start services */ ScmAutoStartServices(); + /* Signal auto-start complete event */ + SetEvent(hScmAutoStartCompleteEvent); + /* FIXME: more to do ? */ /* Release the service start lock */ ScmReleaseServiceStartLock(&Lock); + /* Initialization finished */ + ScmInitialize = FALSE; + DPRINT("SERVICES: Running.\n"); /* Wait until the shutdown event gets signaled */ @@ -451,6 +475,10 @@ if (hScmShutdownEvent != NULL) CloseHandle(hScmShutdownEvent); + /* Close the auto-start complete event */ + if (hScmAutoStartCompleteEvent != NULL) + CloseHandle(hScmAutoStartCompleteEvent); + /* Close the start event */ if (hScmStartEvent != NULL) CloseHandle(hScmStartEvent); @@ -458,7 +486,6 @@ DPRINT("SERVICES: Finished.\n"); ExitThread(0); - return 0; } Index: base/system/services/services.h =================================================================== --- base/system/services/services.h (révision 58514) +++ 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;