#include "services.h"
+#include <winuser.h>
+
#define NDEBUG
#include <debug.h>
/*
* 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
* on the service control pipes.
*/
-// #define USE_ASYNCHRONOUS_IO
+#define USE_ASYNCHRONOUS_IO
/* GLOBALS *******************************************************************/
LIST_ENTRY ServiceListHead;
static RTL_RESOURCE DatabaseLock;
-static DWORD dwResumeCount = 1;
+static DWORD ResumeCount = 1;
+/* The critical section synchronizes service control requests */
static CRITICAL_SECTION ControlServiceCriticalSection;
-static DWORD dwPipeTimeout = 30000; /* 30 Seconds */
+static DWORD PipeTimeout = 30000; /* 30 Seconds */
/* FUNCTIONS *****************************************************************/
}
/* Create '\\.\pipe\net\NtControlPipeXXX' instance */
- swprintf(szControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", ServiceCurrent);
+ swprintf(szControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%lu", ServiceCurrent);
DPRINT("PipeName: %S\n", szControlPipeName);
100,
8000,
4,
- dwPipeTimeout,
+ PipeTimeout,
NULL);
DPRINT("CreateNamedPipeW(%S) done\n", szControlPipeName);
if (pServiceImage->hControlPipe == INVALID_HANDLE_VALUE)
ImageEntry = ImageEntry->Flink;
}
- DPRINT1("Couldn't find a matching image\n");
+ DPRINT("Couldn't find a matching image\n");
return NULL;
if (pServiceImage == NULL)
{
/* Create a new service image */
- pServiceImage = (PSERVICE_IMAGE)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- sizeof(SERVICE_IMAGE) + ((wcslen(ImagePath.Buffer) + 1) * sizeof(WCHAR)));
+ pServiceImage = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ FIELD_OFFSET(SERVICE_IMAGE, szImagePath[ImagePath.Length / sizeof(WCHAR) + 1]));
if (pServiceImage == NULL)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
pServiceImage->dwImageRunCount = 1;
pServiceImage->hControlPipe = INVALID_HANDLE_VALUE;
- pServiceImage->hProcess = INVALID_HANDLE_VALUE;
/* Set the image path */
wcscpy(pServiceImage->szImagePath,
if (pServiceImage->hControlPipe != INVALID_HANDLE_VALUE)
CloseHandle(pServiceImage->hControlPipe);
- /* Close the process handle */
- if (pServiceImage->hProcess != INVALID_HANDLE_VALUE)
- CloseHandle(pServiceImage->hProcess);
-
/* Release the service image */
HeapFree(GetProcessHeap(), 0, pServiceImage);
}
DWORD
ScmCreateNewServiceRecord(LPCWSTR lpServiceName,
- PSERVICE *lpServiceRecord)
+ PSERVICE* lpServiceRecord)
{
PSERVICE lpService = NULL;
DPRINT("Service: '%S'\n", lpServiceName);
/* Allocate service entry */
- lpService = (SERVICE*)HeapAlloc(GetProcessHeap(),
+ lpService = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
- sizeof(SERVICE) + ((wcslen(lpServiceName) + 1) * sizeof(WCHAR)));
+ FIELD_OFFSET(SERVICE, szServiceName[wcslen(lpServiceName) + 1]));
if (lpService == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
lpService->lpDisplayName = lpService->lpServiceName;
/* Set the resume count */
- lpService->dwResumeCount = dwResumeCount++;
+ lpService->dwResumeCount = ResumeCount++;
/* Append service record */
InsertTailList(&ServiceListHead,
{
/* Find the maximum subkey length so that we can allocate a buffer */
dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
- &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
+ &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
if (!dwRet)
{
dwMaxSubkeyLen++;
- if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
+ if (dwMaxSubkeyLen > sizeof(szNameBuf) / sizeof(WCHAR))
+ {
/* Name too big: alloc a buffer for it */
- lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
+ lpszName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwMaxSubkeyLen * sizeof(WCHAR));
+ }
- if(!lpszName)
+ if (!lpszName)
dwRet = ERROR_NOT_ENOUGH_MEMORY;
else
{
HeapFree(GetProcessHeap(), 0, CurrentService);
}
}
-
+
if (dwError != ERROR_SUCCESS)
DPRINT1("Delete service failed: %S\n", CurrentService->lpServiceName);
}
}
-VOID
-WaitForLSA(VOID)
-{
- HANDLE hEvent;
- DWORD dwError;
-
- DPRINT("WaitForLSA() called\n");
-
- hEvent = CreateEventW(NULL,
- TRUE,
- FALSE,
- L"LSA_RPC_SERVER_ACTIVE");
- if (hEvent == NULL)
- {
- dwError = GetLastError();
- DPRINT1("Failed to create the notication event (Error %lu)\n", dwError);
-
- if (dwError == ERROR_ALREADY_EXISTS)
- {
- hEvent = OpenEventW(SYNCHRONIZE,
- FALSE,
- L"LSA_RPC_SERVER_ACTIVE");
- if (hEvent != NULL)
- {
- DPRINT1("Could not open the notification event!\n");
- return;
- }
- }
- }
-
- DPRINT("Wait for LSA!\n");
- WaitForSingleObject(hEvent, INFINITE);
- DPRINT("LSA is available!\n");
-
- CloseHandle(hEvent);
-
- DPRINT("WaitForLSA() done\n");
-}
-
-
DWORD
ScmCreateServiceDatabase(VOID)
{
RegCloseKey(hServicesKey);
- /* Wait for LSA */
- WaitForLSA();
+ /* Wait for the LSA server */
+ ScmWaitForLsa();
/* Delete services that are marked for delete */
ScmDeleteMarkedServices();
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");
+ ASSERT(Service->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER);
+ RtlInitUnicodeString(&DirName, L"\\FileSystem");
}
InitializeObjectAttributes(&ObjectAttributes,
}
BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) +
- 2 * MAX_PATH * sizeof(WCHAR);
- DirInfo = (OBJECT_DIRECTORY_INFORMATION*) HeapAlloc(GetProcessHeap(),
+ 2 * MAX_PATH * sizeof(WCHAR);
+ DirInfo = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
BufferLength);
DWORD dwError = ERROR_SUCCESS;
BOOL bResult;
#ifdef USE_ASYNCHRONOUS_IO
- OVERLAPPED Overlapped = {0, 0, 0, 0, 0};
+ OVERLAPPED Overlapped = {0};
#endif
DPRINT("ScmControlService() called\n");
+ /* Acquire the service control critical section, to synchronize requests */
EnterCriticalSection(&ControlServiceCriticalSection);
/* Calculate the total length of the start command line */
PacketSize = sizeof(SCM_CONTROL_PACKET);
- PacketSize += (wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR);
+ PacketSize += (DWORD)((wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR));
- ControlPacket = (SCM_CONTROL_PACKET*)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- PacketSize);
+ ControlPacket = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ PacketSize);
if (ControlPacket == NULL)
{
LeaveCriticalSection(&ControlServiceCriticalSection);
&Overlapped);
if (bResult == FALSE)
{
- DPRINT1("WriteFile() returned FALSE\n");
+ DPRINT("WriteFile() returned FALSE\n");
dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
{
- DPRINT1("dwError: ERROR_IO_PENDING\n");
+ DPRINT("dwError: ERROR_IO_PENDING\n");
dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
- dwPipeTimeout);
- DPRINT1("WaitForSingleObject() returned %lu\n", dwError);
+ PipeTimeout);
+ DPRINT("WaitForSingleObject() returned %lu\n", dwError);
if (dwError == WAIT_TIMEOUT)
{
dwError = ERROR_SERVICE_REQUEST_TIMEOUT;
goto Done;
}
- else if (dwError == ERROR_SUCCESS)
+ else if (dwError == WAIT_OBJECT_0)
{
bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
&Overlapped,
&Overlapped);
if (bResult == FALSE)
{
- DPRINT1("ReadFile() returned FALSE\n");
+ DPRINT("ReadFile() returned FALSE\n");
dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
{
- DPRINT1("dwError: ERROR_IO_PENDING\n");
+ DPRINT("dwError: ERROR_IO_PENDING\n");
dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
- dwPipeTimeout);
- DPRINT1("WaitForSingleObject() returned %lu\n", dwError);
+ PipeTimeout);
+ DPRINT("WaitForSingleObject() returned %lu\n", dwError);
if (dwError == WAIT_TIMEOUT)
{
dwError = ERROR_SERVICE_REQUEST_TIMEOUT;
goto Done;
}
- else if (dwError == ERROR_SUCCESS)
+ else if (dwError == WAIT_OBJECT_0)
{
bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
&Overlapped,
{
dwError = GetLastError();
DPRINT("WriteFile() failed (Error %lu)\n", dwError);
+
+ if ((dwError == ERROR_GEN_FAILURE) &&
+ (dwControl == SERVICE_CONTROL_STOP))
+ {
+ /* Service is already terminated */
+ Service->Status.dwCurrentState = SERVICE_STOPPED;
+ Service->Status.dwControlsAccepted = 0;
+ Service->Status.dwWin32ExitCode = ERROR_SERVICE_NOT_ACTIVE;
+ dwError = ERROR_SUCCESS;
+ }
goto Done;
}
static DWORD
ScmSendStartCommand(PSERVICE Service,
DWORD argc,
- LPWSTR *argv)
+ LPWSTR* argv)
{
PSCM_CONTROL_PACKET ControlPacket;
SCM_REPLY_PACKET ReplyPacket;
PWSTR pArgPtr;
BOOL bResult;
#ifdef USE_ASYNCHRONOUS_IO
- OVERLAPPED Overlapped = {0, 0, 0, 0, 0};
+ OVERLAPPED Overlapped = {0};
#endif
DPRINT("ScmSendStartCommand() called\n");
/* Calculate the total length of the start command line */
- PacketSize = sizeof(SCM_CONTROL_PACKET);
- PacketSize += (wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR);
+ PacketSize = sizeof(SCM_CONTROL_PACKET) +
+ (DWORD)((wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR));
/* Calculate the required packet size for the start arguments */
if (argc > 0 && argv != NULL)
for (i = 0; i < argc; i++)
{
DPRINT("Argv[%lu]: %S\n", i, argv[i]);
- PacketSize += (wcslen(argv[i]) + 1) * sizeof(WCHAR) + sizeof(PWSTR);
+ PacketSize += (DWORD)((wcslen(argv[i]) + 1) * sizeof(WCHAR) + sizeof(PWSTR));
}
}
/* Allocate a control packet */
- ControlPacket = (SCM_CONTROL_PACKET*)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- PacketSize);
+ ControlPacket = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ PacketSize);
if (ControlPacket == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
ControlPacket->dwSize = PacketSize;
- ControlPacket->dwControl = SERVICE_CONTROL_START;
+ ControlPacket->dwControl = (Service->Status.dwServiceType & SERVICE_WIN32_OWN_PROCESS)
+ ? SERVICE_CONTROL_START_OWN
+ : SERVICE_CONTROL_START_SHARE;
ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service;
ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
&Overlapped);
if (bResult == FALSE)
{
- DPRINT1("WriteFile() returned FALSE\n");
+ DPRINT("WriteFile() returned FALSE\n");
dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
{
- DPRINT1("dwError: ERROR_IO_PENDING\n");
+ DPRINT("dwError: ERROR_IO_PENDING\n");
dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
- dwPipeTimeout);
- DPRINT1("WaitForSingleObject() returned %lu\n", dwError);
+ PipeTimeout);
+ DPRINT("WaitForSingleObject() returned %lu\n", dwError);
if (dwError == WAIT_TIMEOUT)
{
dwError = ERROR_SERVICE_REQUEST_TIMEOUT;
goto Done;
}
- else if (dwError == ERROR_SUCCESS)
+ else if (dwError == WAIT_OBJECT_0)
{
bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
&Overlapped,
&Overlapped);
if (bResult == FALSE)
{
- DPRINT1("ReadFile() returned FALSE\n");
+ DPRINT("ReadFile() returned FALSE\n");
dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
{
- DPRINT1("dwError: ERROR_IO_PENDING\n");
+ DPRINT("dwError: ERROR_IO_PENDING\n");
dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
- dwPipeTimeout);
- DPRINT1("WaitForSingleObject() returned %lu\n", dwError);
+ PipeTimeout);
+ DPRINT("WaitForSingleObject() returned %lu\n", dwError);
if (dwError == WAIT_TIMEOUT)
{
dwError = ERROR_SERVICE_REQUEST_TIMEOUT;
goto Done;
}
- else if (dwError == ERROR_SUCCESS)
+ else if (dwError == WAIT_OBJECT_0)
{
bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
&Overlapped,
DWORD dwError = ERROR_SUCCESS;
BOOL bResult;
#ifdef USE_ASYNCHRONOUS_IO
- OVERLAPPED Overlapped = {0, 0, 0, 0, 0};
+ OVERLAPPED Overlapped = {0};
#endif
- DPRINT1("ScmWaitForServiceConnect()\n");
+ DPRINT("ScmWaitForServiceConnect()\n");
#ifdef USE_ASYNCHRONOUS_IO
Overlapped.hEvent = (HANDLE)NULL;
&Overlapped);
if (bResult == FALSE)
{
- DPRINT1("ConnectNamedPipe() returned FALSE\n");
+ DPRINT("ConnectNamedPipe() returned FALSE\n");
dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
{
- DPRINT1("dwError: ERROR_IO_PENDING\n");
+ DPRINT("dwError: ERROR_IO_PENDING\n");
dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
- dwPipeTimeout);
- DPRINT1("WaitForSingleObject() returned %lu\n", dwError);
+ PipeTimeout);
+ DPRINT("WaitForSingleObject() returned %lu\n", dwError);
if (dwError == WAIT_TIMEOUT)
{
+ DPRINT("WaitForSingleObject() returned WAIT_TIMEOUT\n");
+
bResult = CancelIo(Service->lpImage->hControlPipe);
if (bResult == FALSE)
{
return ERROR_SERVICE_REQUEST_TIMEOUT;
}
- else if (dwError == ERROR_SUCCESS)
+ else if (dwError == WAIT_OBJECT_0)
{
bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
&Overlapped,
}
}
- DPRINT1("Control pipe connected!\n");
+ DPRINT("Control pipe connected!\n");
Overlapped.hEvent = (HANDLE) NULL;
&Overlapped);
if (bResult == FALSE)
{
- DPRINT1("ReadFile() returned FALSE\n");
+ DPRINT("ReadFile() returned FALSE\n");
dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
{
- DPRINT1("dwError: ERROR_IO_PENDING\n");
+ DPRINT("dwError: ERROR_IO_PENDING\n");
dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
- dwPipeTimeout);
+ PipeTimeout);
if (dwError == WAIT_TIMEOUT)
{
- DPRINT1("WaitForSingleObject() returned WAIT_TIMEOUT\n");
+ DPRINT("WaitForSingleObject() returned WAIT_TIMEOUT\n");
bResult = CancelIo(Service->lpImage->hControlPipe);
if (bResult == FALSE)
return ERROR_SERVICE_REQUEST_TIMEOUT;
}
- else if (dwError == ERROR_SUCCESS)
+ else if (dwError == WAIT_OBJECT_0)
{
- DPRINT1("WaitForSingleObject() returned ERROR_SUCCESS\n");
+ DPRINT("WaitForSingleObject() returned WAIT_OBJECT_0\n");
- DPRINT1("Process Id: %lu\n", dwProcessId);
+ DPRINT("Process Id: %lu\n", dwProcessId);
bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
&Overlapped,
}
}
- DPRINT1("ScmWaitForServiceConnect() done\n");
+ DPRINT("ScmWaitForServiceConnect() done\n");
return ERROR_SUCCESS;
#else
DPRINT1("Reading the service control pipe failed (Error %lu)\n",
dwError);
}
+ else
+ {
+ dwError = ERROR_SUCCESS;
+ DPRINT("Read control pipe successfully\n");
+ }
}
else
{
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);
- StartupInfo.lpReserved = NULL;
- StartupInfo.lpDesktop = NULL;
- StartupInfo.lpTitle = NULL;
- StartupInfo.dwFlags = 0;
- StartupInfo.cbReserved2 = 0;
- StartupInfo.lpReserved2 = 0;
+ ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
Result = CreateProcessW(NULL,
Service->lpImage->szImagePath,
return dwError;
}
- DPRINT("Process Id: %lu Handle %lx\n",
+ DPRINT("Process Id: %lu Handle %p\n",
ProcessInformation.dwProcessId,
ProcessInformation.hProcess);
- DPRINT("Thread Id: %lu Handle %lx\n",
+ DPRINT("Thread Id: %lu Handle %p\n",
ProcessInformation.dwThreadId,
ProcessInformation.hThread);
/* Get process handle and id */
Service->lpImage->dwProcessId = ProcessInformation.dwProcessId;
- Service->lpImage->hProcess = ProcessInformation.hProcess;
/* Resume Thread */
ResumeThread(ProcessInformation.hThread);
if (dwError == ERROR_SUCCESS)
{
/* Send start command */
- dwError = ScmSendStartCommand(Service,
- argc,
- argv);
+ dwError = ScmSendStartCommand(Service, argc, argv);
}
else
{
DPRINT1("Connecting control pipe failed! (Error %lu)\n", dwError);
Service->lpImage->dwProcessId = 0;
- Service->lpImage->hProcess = NULL;
- CloseHandle(ProcessInformation.hProcess);
}
- /* Close thread handle */
+ /* Close thread and process handle */
CloseHandle(ProcessInformation.hThread);
+ CloseHandle(ProcessInformation.hProcess);
return dwError;
}
-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)
{
{
if (Service->dwErrorControl != SERVICE_ERROR_IGNORE)
{
+ /* Log a failed service start */
+ swprintf(szErrorBuffer, L"%lu", dwError);
ErrorLogStrings[0] = Service->lpServiceName;
- ErrorLogStrings[1] = L"Test";
+ ErrorLogStrings[1] = szErrorBuffer;
ScmLogError(EVENT_SERVICE_START_FAILED,
2,
ErrorLogStrings);
}
+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;
PLIST_ENTRY GroupEntry;
PLIST_ENTRY ServiceEntry;
PSERVICE_GROUP CurrentGroup;
PSERVICE CurrentService;
WCHAR szSafeBootServicePath[MAX_PATH];
- DWORD dwError;
HKEY hKey;
ULONG i;
+ /*
+ * This function MUST be called ONLY at initialization time.
+ * Therefore, no need to acquire the user service start lock.
+ */
+ ASSERT(ScmInitialize);
+
+ /* Acquire the service control critical section, to synchronize starts */
+ EnterCriticalSection(&ControlServiceCriticalSection);
+
/* 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 critical section */
+ LeaveCriticalSection(&ControlServiceCriticalSection);
}
L"ServicesPipeTimeout",
0,
NULL,
- (LPBYTE)&dwPipeTimeout,
+ (LPBYTE)&PipeTimeout,
&dwKeySize);
RegCloseKey(hKey);