/*
* Uncomment the line below to start services
- * using the SERVICE_START_PENDING state
+ * 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
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 */
DWORD
ScmCreateNewServiceRecord(LPCWSTR lpServiceName,
- PSERVICE *lpServiceRecord)
+ PSERVICE* lpServiceRecord)
{
PSERVICE lpService = NULL;
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,
}
BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) +
- 2 * MAX_PATH * sizeof(WCHAR);
+ 2 * MAX_PATH * sizeof(WCHAR);
DirInfo = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
BufferLength);
static DWORD
ScmSendStartCommand(PSERVICE Service,
DWORD argc,
- LPWSTR *argv)
+ LPWSTR* argv)
{
PSCM_CONTROL_PACKET ControlPacket;
SCM_REPLY_PACKET ReplyPacket;
static DWORD
ScmStartUserModeService(PSERVICE Service,
DWORD argc,
- LPWSTR *argv)
+ LPWSTR* argv)
{
PROCESS_INFORMATION ProcessInformation;
STARTUPINFOW StartupInfo;
return ScmSendStartCommand(Service, argc, argv);
}
+ /* Otherwise start its process */
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo);
ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
if (dwError == ERROR_SUCCESS)
{
/* Send start command */
- dwError = ScmSendStartCommand(Service,
- argc,
- argv);
+ dwError = ScmSendStartCommand(Service, argc, argv);
}
else
{
}
-DWORD
-ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv)
+static DWORD
+ScmLoadService(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("ScmLoadService() 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;
}
Service->Status.dwCurrentState = SERVICE_RUNNING;
}
}
- else
+ else // if (Service->Status.dwServiceType & (SERVICE_WIN32 | SERVICE_INTERACTIVE_PROCESS))
{
/* Start user-mode service */
dwError = ScmCreateOrReferenceServiceImage(Service);
}
}
- LeaveCriticalSection(&ControlServiceCriticalSection);
-
- DPRINT("ScmStartService() done (Error %lu)\n", dwError);
+ DPRINT("ScmLoadService() done (Error %lu)\n", dwError);
if (dwError == ERROR_SUCCESS)
{
}
+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 = ScmLoadService(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)
(CurrentService->dwTag == CurrentGroup->TagArray[i]))
{
CurrentService->ServiceVisited = TRUE;
- ScmStartService(CurrentService, 0, NULL);
+ ScmLoadService(CurrentService, 0, NULL);
}
ServiceEntry = ServiceEntry->Flink;
(CurrentService->ServiceVisited == FALSE))
{
CurrentService->ServiceVisited = TRUE;
- ScmStartService(CurrentService, 0, NULL);
+ ScmLoadService(CurrentService, 0, NULL);
}
ServiceEntry = ServiceEntry->Flink;
(CurrentService->ServiceVisited == FALSE))
{
CurrentService->ServiceVisited = TRUE;
- ScmStartService(CurrentService, 0, NULL);
+ ScmLoadService(CurrentService, 0, NULL);
}
ServiceEntry = ServiceEntry->Flink;
(CurrentService->ServiceVisited == FALSE))
{
CurrentService->ServiceVisited = TRUE;
- ScmStartService(CurrentService, 0, NULL);
+ ScmLoadService(CurrentService, 0, NULL);
}
ServiceEntry = ServiceEntry->Flink;
CurrentService->ServiceVisited = FALSE;
ServiceEntry = ServiceEntry->Flink;
}
+
+
+ /* Release the service start lock, if needed, and the critical section */
+ if (Lock) ScmReleaseServiceStartLock(&Lock);
+
+done:
+ LeaveCriticalSection(&ControlServiceCriticalSection);
}