#include "services.h"
#include <userenv.h>
+#include <strsafe.h>
+
+#include <reactos/undocuser.h>
#define NDEBUG
#include <debug.h>
static RTL_RESOURCE DatabaseLock;
static DWORD ResumeCount = 1;
static DWORD NoInteractiveServices = 0;
+static DWORD ServiceTag = 0;
/* The critical section synchronizes service control requests */
static CRITICAL_SECTION ControlServiceCriticalSection;
/* FUNCTIONS *****************************************************************/
+static
+BOOL
+ScmIsSecurityService(
+ _In_ PSERVICE_IMAGE pServiceImage)
+{
+ return (wcsstr(pServiceImage->pszImagePath, L"\\system32\\lsass.exe") != NULL);
+}
+
+
static DWORD
-ScmCreateNewControlPipe(PSERVICE_IMAGE pServiceImage)
+ScmCreateNewControlPipe(
+ _In_ PSERVICE_IMAGE pServiceImage,
+ _In_ BOOL bSecurityServiceProcess)
{
WCHAR szControlPipeName[MAX_PATH + 1];
+ SECURITY_ATTRIBUTES SecurityAttributes;
HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE;
- DWORD ServiceCurrent = 0;
- DWORD KeyDisposition;
+ DWORD dwServiceCurrent = 1;
+ DWORD dwKeyDisposition;
DWORD dwKeySize;
DWORD dwError;
/* Get the service number */
- /* TODO: Create registry entry with correct write access */
- dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
- L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent", 0, NULL,
- REG_OPTION_VOLATILE,
- KEY_WRITE | KEY_READ,
- NULL,
- &hServiceCurrentKey,
- &KeyDisposition);
- if (dwError != ERROR_SUCCESS)
- {
- DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError);
- return dwError;
- }
-
- if (KeyDisposition == REG_OPENED_EXISTING_KEY)
+ if (bSecurityServiceProcess == FALSE)
{
- dwKeySize = sizeof(DWORD);
- dwError = RegQueryValueExW(hServiceCurrentKey,
- L"", 0, NULL, (BYTE*)&ServiceCurrent, &dwKeySize);
-
+ /* TODO: Create registry entry with correct write access */
+ dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent",
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ KEY_WRITE | KEY_READ,
+ NULL,
+ &hServiceCurrentKey,
+ &dwKeyDisposition);
if (dwError != ERROR_SUCCESS)
{
- RegCloseKey(hServiceCurrentKey);
- DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError);
+ DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError);
return dwError;
}
- ServiceCurrent++;
- }
+ if (dwKeyDisposition == REG_OPENED_EXISTING_KEY)
+ {
+ dwKeySize = sizeof(DWORD);
+ dwError = RegQueryValueExW(hServiceCurrentKey,
+ L"",
+ 0,
+ NULL,
+ (BYTE*)&dwServiceCurrent,
+ &dwKeySize);
+ if (dwError != ERROR_SUCCESS)
+ {
+ RegCloseKey(hServiceCurrentKey);
+ DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError);
+ return dwError;
+ }
+
+ dwServiceCurrent++;
+ }
- dwError = RegSetValueExW(hServiceCurrentKey, L"", 0, REG_DWORD, (BYTE*)&ServiceCurrent, sizeof(ServiceCurrent));
+ dwError = RegSetValueExW(hServiceCurrentKey,
+ L"",
+ 0,
+ REG_DWORD,
+ (BYTE*)&dwServiceCurrent,
+ sizeof(dwServiceCurrent));
- RegCloseKey(hServiceCurrentKey);
+ RegCloseKey(hServiceCurrentKey);
- if (dwError != ERROR_SUCCESS)
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError);
+ return dwError;
+ }
+ }
+ else
{
- DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError);
- return dwError;
+ dwServiceCurrent = 0;
}
/* Create '\\.\pipe\net\NtControlPipeXXX' instance */
- swprintf(szControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%lu", ServiceCurrent);
+ StringCchPrintfW(szControlPipeName, ARRAYSIZE(szControlPipeName),
+ L"\\\\.\\pipe\\net\\NtControlPipe%lu", dwServiceCurrent);
DPRINT("PipeName: %S\n", szControlPipeName);
+ SecurityAttributes.nLength = sizeof(SecurityAttributes);
+ SecurityAttributes.lpSecurityDescriptor = pPipeSD;
+ SecurityAttributes.bInheritHandle = FALSE;
+
pServiceImage->hControlPipe = CreateNamedPipeW(szControlPipeName,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
8000,
4,
PipeTimeout,
- NULL);
+ &SecurityAttributes);
DPRINT("CreateNamedPipeW(%S) done\n", szControlPipeName);
if (pServiceImage->hControlPipe == INVALID_HANDLE_VALUE)
{
}
+DWORD
+ScmGetServiceNameFromTag(IN PTAG_INFO_NAME_FROM_TAG_IN_PARAMS InParams,
+ OUT PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS *OutParams)
+{
+ PLIST_ENTRY ServiceEntry;
+ PSERVICE CurrentService;
+ PSERVICE_IMAGE CurrentImage;
+ PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS OutBuffer = NULL;
+ DWORD dwError;
+
+ /* Lock the database */
+ ScmLockDatabaseExclusive();
+
+ /* Find the matching service */
+ ServiceEntry = ServiceListHead.Flink;
+ while (ServiceEntry != &ServiceListHead)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
+
+ /* We must match the tag */
+ if (CurrentService->dwTag == InParams->dwTag &&
+ CurrentService->lpImage != NULL)
+ {
+ CurrentImage = CurrentService->lpImage;
+ /* And matching the PID */
+ if (CurrentImage->dwProcessId == InParams->dwPid)
+ {
+ break;
+ }
+ }
+
+ ServiceEntry = ServiceEntry->Flink;
+ }
+
+ /* No match! */
+ if (ServiceEntry == &ServiceListHead)
+ {
+ dwError = ERROR_RETRY;
+ goto Cleanup;
+ }
+
+ /* Allocate the output buffer */
+ OutBuffer = MIDL_user_allocate(sizeof(TAG_INFO_NAME_FROM_TAG_OUT_PARAMS));
+ if (OutBuffer == NULL)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto Cleanup;
+ }
+
+ /* And the buffer for the name */
+ OutBuffer->pszName = MIDL_user_allocate(wcslen(CurrentService->lpServiceName) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
+ if (OutBuffer->pszName == NULL)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto Cleanup;
+ }
+
+ /* Fill in output data */
+ wcscpy(OutBuffer->pszName, CurrentService->lpServiceName);
+ OutBuffer->TagType = TagTypeService;
+
+ /* And return */
+ *OutParams = OutBuffer;
+ dwError = ERROR_SUCCESS;
+
+Cleanup:
+
+ /* Unlock database */
+ ScmUnlockDatabase();
+
+ /* If failure, free allocated memory */
+ if (dwError != ERROR_SUCCESS)
+ {
+ if (OutBuffer != NULL)
+ {
+ MIDL_user_free(OutBuffer);
+ }
+ }
+
+ /* Return error/success */
+ return dwError;
+}
+
+
static
BOOL
ScmIsSameServiceAccount(
_In_ PCWSTR pszAccountName1,
_In_ PCWSTR pszAccountName2)
{
- if (pszAccountName1 == NULL && pszAccountName2 == NULL)
+ if (pszAccountName1 == NULL &&
+ pszAccountName2 == NULL)
return TRUE;
- if (pszAccountName1 == NULL && pszAccountName2 && wcscmp(pszAccountName2, L"LocalSystem") == 0)
+ if (pszAccountName1 == NULL &&
+ pszAccountName2 != NULL &&
+ _wcsicmp(pszAccountName2, L"LocalSystem") == 0)
return TRUE;
- if (pszAccountName2 == NULL && pszAccountName1 && wcscmp(pszAccountName1, L"LocalSystem") == 0)
+ if (pszAccountName1 != NULL &&
+ pszAccountName2 == NULL &&
+ _wcsicmp(pszAccountName1, L"LocalSystem") == 0)
return TRUE;
- if (pszAccountName1 && pszAccountName2 && wcscmp(pszAccountName1, pszAccountName2) == 0)
+ if (pszAccountName1 != NULL &&
+ pszAccountName2 != NULL &&
+ _wcsicmp(pszAccountName1, pszAccountName2) == 0)
return TRUE;
return FALSE;
_In_ PCWSTR pszAccountName)
{
if (pszAccountName == NULL ||
- wcscmp(pszAccountName, L"LocalSystem") == 0)
+ _wcsicmp(pszAccountName, L"LocalSystem") == 0)
return TRUE;
return FALSE;
}
+static
+BOOL
+ScmEnableBackupRestorePrivileges(
+ _In_ HANDLE hToken,
+ _In_ BOOL bEnable)
+{
+ PTOKEN_PRIVILEGES pTokenPrivileges = NULL;
+ DWORD dwSize;
+ BOOL bRet = FALSE;
+
+ DPRINT("ScmEnableBackupRestorePrivileges(%p %d)\n", hToken, bEnable);
+
+ dwSize = sizeof(TOKEN_PRIVILEGES) + 2 * sizeof(LUID_AND_ATTRIBUTES);
+ pTokenPrivileges = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
+ if (pTokenPrivileges == NULL)
+ {
+ DPRINT1("Failed to allocate the privilege buffer!\n");
+ goto done;
+ }
+
+ pTokenPrivileges->PrivilegeCount = 2;
+ pTokenPrivileges->Privileges[0].Luid.LowPart = SE_BACKUP_PRIVILEGE;
+ pTokenPrivileges->Privileges[0].Luid.HighPart = 0;
+ pTokenPrivileges->Privileges[0].Attributes = (bEnable ? SE_PRIVILEGE_ENABLED : 0);
+ pTokenPrivileges->Privileges[1].Luid.LowPart = SE_RESTORE_PRIVILEGE;
+ pTokenPrivileges->Privileges[1].Luid.HighPart = 0;
+ pTokenPrivileges->Privileges[1].Attributes = (bEnable ? SE_PRIVILEGE_ENABLED : 0);
+
+ bRet = AdjustTokenPrivileges(hToken, FALSE, pTokenPrivileges, 0, NULL, NULL);
+ if (!bRet)
+ {
+ DPRINT1("AdjustTokenPrivileges() failed with error %lu\n", GetLastError());
+ }
+ else if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
+ {
+ DPRINT1("AdjustTokenPrivileges() succeeded, but with not all privileges assigned\n");
+ bRet = FALSE;
+ }
+
+done:
+ if (pTokenPrivileges != NULL)
+ HeapFree(GetProcessHeap(), 0, pTokenPrivileges);
+
+ return bRet;
+}
+
+
static
DWORD
ScmLogonService(
IN PSERVICE pService,
IN PSERVICE_IMAGE pImage)
{
-#if 0
PROFILEINFOW ProfileInfo;
PWSTR pszUserName = NULL;
PWSTR pszDomainName = NULL;
PWSTR pszPassword = NULL;
PWSTR ptr;
DWORD dwError = ERROR_SUCCESS;
-#endif
DPRINT("ScmLogonService(%p %p)\n", pService, pImage);
-
DPRINT("Service %S\n", pService->lpServiceName);
if (ScmIsLocalSystemAccount(pImage->pszAccountName))
return ERROR_SUCCESS;
- // FIXME: Always assume LocalSystem
- return ERROR_SUCCESS;
-
-#if 0
/* Get the user and domain names */
ptr = wcschr(pImage->pszAccountName, L'\\');
if (ptr != NULL)
{
*ptr = L'\0';
-
pszUserName = ptr + 1;
pszDomainName = pImage->pszAccountName;
}
else
{
+ // ERROR_INVALID_SERVICE_ACCOUNT
pszUserName = pImage->pszAccountName;
pszDomainName = NULL;
}
DPRINT("Domain: %S User: %S Password: %S\n", pszDomainName, pszUserName, pszPassword);
- /* Service logon */
+ /* Do the service logon */
if (!LogonUserW(pszUserName,
pszDomainName,
pszPassword,
{
dwError = GetLastError();
DPRINT1("LogonUserW() failed (Error %lu)\n", dwError);
+
+ /* Normalize the returned error */
+ dwError = ERROR_SERVICE_LOGON_FAILED;
goto done;
}
- // FIXME: Call LoadUserProfileW to be able to initialize a per-user
- // environment block, with user-specific environment variables as
- // %USERNAME%, %USERPROFILE%, and %ALLUSERSPROFILE% correctly initialized!!
-
- /* Load the user profile, so that the per-user environment variables can be initialized */
+ /* Load the user profile; the per-user environment variables are thus correctly initialized */
ZeroMemory(&ProfileInfo, sizeof(ProfileInfo));
ProfileInfo.dwSize = sizeof(ProfileInfo);
ProfileInfo.dwFlags = PI_NOUI;
// ProfileInfo.lpPolicyPath = NULL;
// ProfileInfo.hProfile = NULL;
+ ScmEnableBackupRestorePrivileges(pImage->hToken, TRUE);
if (!LoadUserProfileW(pImage->hToken, &ProfileInfo))
- {
dwError = GetLastError();
+ ScmEnableBackupRestorePrivileges(pImage->hToken, FALSE);
+
+ if (dwError != ERROR_SUCCESS)
+ {
DPRINT1("LoadUserProfileW() failed (Error %lu)\n", dwError);
goto done;
}
*ptr = L'\\';
return dwError;
-#endif
}
DWORD dwError = ERROR_SUCCESS;
DWORD dwRecordSize;
LPWSTR pString;
+ BOOL bSecurityService;
DPRINT("ScmCreateOrReferenceServiceImage(%p)\n", pService);
goto done;
}
+ bSecurityService = ScmIsSecurityService(pServiceImage);
+
/* Create the control pipe */
- dwError = ScmCreateNewControlPipe(pServiceImage);
+ dwError = ScmCreateNewControlPipe(pServiceImage,
+ bSecurityService);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("ScmCreateNewControlPipe() failed (Error %lu)\n", dwError);
/* Unload the user profile */
if (pServiceImage->hProfile != NULL)
+ {
+ ScmEnableBackupRestorePrivileges(pServiceImage->hToken, TRUE);
UnloadUserProfile(pServiceImage->hToken, pServiceImage->hProfile);
+ ScmEnableBackupRestorePrivileges(pServiceImage->hToken, FALSE);
+ }
/* Close the logon token */
if (pServiceImage->hToken != NULL)
goto done;
}
+ if (bSecurityService)
+ {
+ SetSecurityServicesEvent();
+ }
+
/* FIXME: Add more initialization code here */
}
-static VOID
-ScmDereferenceServiceImage(PSERVICE_IMAGE pServiceImage)
+VOID
+ScmRemoveServiceImage(PSERVICE_IMAGE pServiceImage)
{
- DPRINT1("ScmDereferenceServiceImage() called\n");
-
- pServiceImage->dwImageRunCount--;
+ DPRINT1("ScmRemoveServiceImage() called\n");
- if (pServiceImage->dwImageRunCount == 0)
- {
- DPRINT1("dwImageRunCount == 0\n");
-
- /* FIXME: Terminate the process */
+ /* FIXME: Terminate the process */
- /* Remove the service image from the list */
- RemoveEntryList(&pServiceImage->ImageListEntry);
+ /* Remove the service image from the list */
+ RemoveEntryList(&pServiceImage->ImageListEntry);
- /* Close the process handle */
- if (pServiceImage->hProcess != INVALID_HANDLE_VALUE)
- CloseHandle(pServiceImage->hProcess);
+ /* Close the process handle */
+ if (pServiceImage->hProcess != INVALID_HANDLE_VALUE)
+ CloseHandle(pServiceImage->hProcess);
- /* Close the control pipe */
- if (pServiceImage->hControlPipe != INVALID_HANDLE_VALUE)
- CloseHandle(pServiceImage->hControlPipe);
+ /* Close the control pipe */
+ if (pServiceImage->hControlPipe != INVALID_HANDLE_VALUE)
+ CloseHandle(pServiceImage->hControlPipe);
- /* Unload the user profile */
- if (pServiceImage->hProfile != NULL)
- UnloadUserProfile(pServiceImage->hToken, pServiceImage->hProfile);
+ /* Unload the user profile */
+ if (pServiceImage->hProfile != NULL)
+ {
+ ScmEnableBackupRestorePrivileges(pServiceImage->hToken, TRUE);
+ UnloadUserProfile(pServiceImage->hToken, pServiceImage->hProfile);
+ ScmEnableBackupRestorePrivileges(pServiceImage->hToken, FALSE);
+ }
- /* Close the logon token */
- if (pServiceImage->hToken != NULL)
- CloseHandle(pServiceImage->hToken);
+ /* Close the logon token */
+ if (pServiceImage->hToken != NULL)
+ CloseHandle(pServiceImage->hToken);
- /* Release the service image */
- HeapFree(GetProcessHeap(), 0, pServiceImage);
- }
+ /* Release the service image */
+ HeapFree(GetProcessHeap(), 0, pServiceImage);
}
}
+DWORD
+ScmGenerateServiceTag(PSERVICE lpServiceRecord)
+{
+ /* Check for an overflow */
+ if (ServiceTag == -1)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ /* This is only valid for Win32 services */
+ if (!(lpServiceRecord->Status.dwServiceType & SERVICE_WIN32))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* Increment the tag counter and set it */
+ ServiceTag = ServiceTag % 0xFFFFFFFF + 1;
+ lpServiceRecord->dwTag = ServiceTag;
+
+ return ERROR_SUCCESS;
+}
+
+
DWORD
ScmCreateNewServiceRecord(LPCWSTR lpServiceName,
- PSERVICE* lpServiceRecord)
+ PSERVICE *lpServiceRecord,
+ DWORD dwServiceType,
+ DWORD dwStartType)
{
PSERVICE lpService = NULL;
lpService->lpServiceName = lpService->szServiceName;
lpService->lpDisplayName = lpService->lpServiceName;
+ /* Set the start type */
+ lpService->dwStartType = dwStartType;
+
/* Set the resume count */
lpService->dwResumeCount = ResumeCount++;
&lpService->ServiceListEntry);
/* Initialize the service status */
+ lpService->Status.dwServiceType = dwServiceType;
lpService->Status.dwCurrentState = SERVICE_STOPPED;
lpService->Status.dwControlsAccepted = 0;
- lpService->Status.dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED;
+ lpService->Status.dwWin32ExitCode =
+ (dwStartType == SERVICE_DISABLED) ? ERROR_SERVICE_DISABLED : ERROR_SERVICE_NEVER_STARTED;
lpService->Status.dwServiceSpecificExitCode = 0;
lpService->Status.dwCheckPoint = 0;
- lpService->Status.dwWaitHint = 2000; /* 2 seconds */
+ lpService->Status.dwWaitHint =
+ (dwServiceType & SERVICE_DRIVER) ? 0 : 2000; /* 2 seconds */
return ERROR_SUCCESS;
}
/* Dereference the service image */
if (lpService->lpImage)
- ScmDereferenceServiceImage(lpService->lpImage);
+ {
+ lpService->lpImage->dwImageRunCount--;
+
+ if (lpService->lpImage->dwImageRunCount == 0)
+ {
+ ScmRemoveServiceImage(lpService->lpImage);
+ lpService->lpImage = NULL;
+ }
+ }
/* Decrement the group reference counter */
ScmSetServiceGroup(lpService, NULL);
DPRINT("Display name: %S\n", lpDisplayName);
dwError = ScmCreateNewServiceRecord(lpServiceName,
- &lpService);
+ &lpService,
+ dwServiceType,
+ dwStartType);
if (dwError != ERROR_SUCCESS)
goto done;
- lpService->Status.dwServiceType = dwServiceType;
- lpService->dwStartType = dwStartType;
lpService->dwErrorControl = dwErrorControl;
lpService->dwTag = dwTagId;
if (ScmIsDeleteFlagSet(hServiceKey))
lpService->bDeleted = TRUE;
+ else
+ ScmGenerateServiceTag(lpService);
if (lpService->Status.dwServiceType & SERVICE_WIN32)
{
/* Mark service as 'running' */
Service->Status.dwCurrentState = SERVICE_RUNNING;
+ Service->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+ Service->Status.dwWin32ExitCode = ERROR_SUCCESS;
+ Service->Status.dwServiceSpecificExitCode = 0;
+ Service->Status.dwCheckPoint = 0;
+ Service->Status.dwWaitHint = 0;
/* Mark the service group as 'running' */
if (Service->lpGroup != NULL)
DWORD
-ScmControlService(PSERVICE Service,
+ScmControlService(HANDLE hControlPipe,
+ PWSTR pServiceName,
+ SERVICE_STATUS_HANDLE hServiceStatus,
DWORD dwControl)
{
PSCM_CONTROL_PACKET ControlPacket;
/* Calculate the total length of the start command line */
PacketSize = sizeof(SCM_CONTROL_PACKET);
- PacketSize += (DWORD)((wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR));
+ PacketSize += (DWORD)((wcslen(pServiceName) + 1) * sizeof(WCHAR));
ControlPacket = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
ControlPacket->dwSize = PacketSize;
ControlPacket->dwControl = dwControl;
- ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service;
+ ControlPacket->hServiceStatus = hServiceStatus;
ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
Ptr = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
- wcscpy(Ptr, Service->lpServiceName);
+ wcscpy(Ptr, pServiceName);
ControlPacket->dwArgumentsCount = 0;
ControlPacket->dwArgumentsOffset = 0;
- bResult = WriteFile(Service->lpImage->hControlPipe,
+ bResult = WriteFile(hControlPipe,
ControlPacket,
PacketSize,
&dwWriteCount,
{
DPRINT("dwError: ERROR_IO_PENDING\n");
- dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
+ dwError = WaitForSingleObject(hControlPipe,
PipeTimeout);
DPRINT("WaitForSingleObject() returned %lu\n", dwError);
if (dwError == WAIT_TIMEOUT)
{
- bResult = CancelIo(Service->lpImage->hControlPipe);
+ bResult = CancelIo(hControlPipe);
if (bResult == FALSE)
{
DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
}
else if (dwError == WAIT_OBJECT_0)
{
- bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
+ bResult = GetOverlappedResult(hControlPipe,
&Overlapped,
&dwWriteCount,
TRUE);
/* Read the reply */
Overlapped.hEvent = (HANDLE) NULL;
- bResult = ReadFile(Service->lpImage->hControlPipe,
+ bResult = ReadFile(hControlPipe,
&ReplyPacket,
sizeof(SCM_REPLY_PACKET),
&dwReadCount,
{
DPRINT("dwError: ERROR_IO_PENDING\n");
- dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
+ dwError = WaitForSingleObject(hControlPipe,
PipeTimeout);
DPRINT("WaitForSingleObject() returned %lu\n", dwError);
if (dwError == WAIT_TIMEOUT)
{
- bResult = CancelIo(Service->lpImage->hControlPipe);
+ bResult = CancelIo(hControlPipe);
if (bResult == FALSE)
{
DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
}
else if (dwError == WAIT_OBJECT_0)
{
- bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
+ bResult = GetOverlappedResult(hControlPipe,
&Overlapped,
&dwReadCount,
TRUE);
dwError = ReplyPacket.dwError;
}
- if (dwError == ERROR_SUCCESS &&
- dwControl == SERVICE_CONTROL_STOP)
- {
- ScmDereferenceServiceImage(Service->lpImage);
- Service->lpImage = NULL;
- }
-
LeaveCriticalSection(&ControlServiceCriticalSection);
DPRINT("ScmControlService() done\n");
? SERVICE_CONTROL_START_OWN
: SERVICE_CONTROL_START_SHARE;
ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service;
+ ControlPacket->dwServiceTag = Service->dwTag;
/* Copy the start command line */
ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
}
}
- if (dwProcessId != Service->lpImage->dwProcessId)
+ if ((ScmIsSecurityService(Service->lpImage) == FALSE)&&
+ (dwProcessId != Service->lpImage->dwProcessId))
{
#if 0
_ultow(Service->lpImage->dwProcessId, szBuffer1, 10);
StartupInfo.cb = sizeof(StartupInfo);
ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
- /* Use the interactive desktop if the service is interactive */
- if ((NoInteractiveServices == 0) &&
- (Service->Status.dwServiceType & SERVICE_INTERACTIVE_PROCESS))
- StartupInfo.lpDesktop = L"WinSta0\\Default";
-
if (Service->lpImage->hToken)
{
/* User token: Run the service under the user account */
lpEnvironment = NULL;
}
- Result = CreateProcessW(NULL,
- Service->lpImage->pszImagePath,
- NULL,
- NULL,
- FALSE,
- CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS | CREATE_SUSPENDED,
- lpEnvironment,
- NULL,
- &StartupInfo,
- &ProcessInformation);
- if (!Result)
- dwError = GetLastError();
+ /* Use the interactive desktop if the service is interactive */
+ if ((NoInteractiveServices == 0) &&
+ (Service->Status.dwServiceType & SERVICE_INTERACTIVE_PROCESS))
+ {
+ StartupInfo.dwFlags |= STARTF_INHERITDESKTOP;
+ StartupInfo.lpDesktop = L"WinSta0\\Default";
+ }
+
+ if (!ScmIsSecurityService(Service->lpImage))
+ {
+ Result = CreateProcessW(NULL,
+ Service->lpImage->pszImagePath,
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS | CREATE_SUSPENDED,
+ lpEnvironment,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation);
+ if (!Result)
+ dwError = GetLastError();
+ }
+ else
+ {
+ Result = TRUE;
+ dwError = ERROR_SUCCESS;
+ }
}
if (lpEnvironment)
if (Service->Status.dwServiceType & SERVICE_DRIVER)
{
- /* Load driver */
- dwError = ScmLoadDriver(Service);
- if (dwError == ERROR_SUCCESS)
- {
- Service->Status.dwCurrentState = SERVICE_RUNNING;
- Service->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
- }
+ /* Start the driver */
+ dwError = ScmStartDriver(Service);
}
else // if (Service->Status.dwServiceType & (SERVICE_WIN32 | SERVICE_INTERACTIVE_PROCESS))
{
}
else
{
- ScmDereferenceServiceImage(Service->lpImage);
- Service->lpImage = NULL;
+ Service->lpImage->dwImageRunCount--;
+ if (Service->lpImage->dwImageRunCount == 0)
+ {
+ ScmRemoveServiceImage(Service->lpImage);
+ Service->lpImage = NULL;
+ }
}
}
}
if (Service->dwErrorControl != SERVICE_ERROR_IGNORE)
{
/* Log a failed service start */
- swprintf(szLogBuffer, L"%lu", dwError);
+ StringCchPrintfW(szLogBuffer, ARRAYSIZE(szLogBuffer),
+ L"%lu", dwError);
lpLogStrings[0] = Service->lpServiceName;
lpLogStrings[1] = szLogBuffer;
ScmLogEvent(EVENT_SERVICE_START_FAILED,
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
/* Build the safe boot path */
- wcscpy(szSafeBootServicePath,
- L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot");
+ StringCchCopyW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
+ L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot");
switch (SafeBootEnabled)
{
/* NOTE: Assumes MINIMAL (1) and DSREPAIR (3) load same items */
case 1:
case 3:
- wcscat(szSafeBootServicePath, L"\\Minimal\\");
+ StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
+ L"\\Minimal\\");
break;
case 2:
- wcscat(szSafeBootServicePath, L"\\Network\\");
+ StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
+ L"\\Network\\");
break;
}
RegCloseKey(hKey);
/* Finish Safe Boot path off */
- wcsncat(szSafeBootServicePath,
- CurrentService->lpServiceName,
- MAX_PATH - wcslen(szSafeBootServicePath));
+ StringCchCatW(szSafeBootServicePath, ARRAYSIZE(szSafeBootServicePath),
+ CurrentService->lpServiceName);
/* Check that the key is in the Safe Boot path */
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
{
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
- if (CurrentService->Status.dwCurrentState == SERVICE_RUNNING ||
- CurrentService->Status.dwCurrentState == SERVICE_START_PENDING)
+ if ((CurrentService->Status.dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN) &&
+ (CurrentService->Status.dwCurrentState == SERVICE_RUNNING ||
+ CurrentService->Status.dwCurrentState == SERVICE_START_PENDING))
{
- /* shutdown service */
- DPRINT("Shutdown service: %S\n", CurrentService->szServiceName);
- ScmControlService(CurrentService, SERVICE_CONTROL_SHUTDOWN);
+ /* Send the shutdown notification */
+ DPRINT("Shutdown service: %S\n", CurrentService->lpServiceName);
+ ScmControlService(CurrentService->lpImage->hControlPipe,
+ CurrentService->lpServiceName,
+ (SERVICE_STATUS_HANDLE)CurrentService,
+ SERVICE_CONTROL_SHUTDOWN);
}
ServiceEntry = ServiceEntry->Flink;