#define MANAGER_TAG 0x72674D68 /* 'hMgr' */
#define SERVICE_TAG 0x63765368 /* 'hSvc' */
+#define INVALID_TAG 0xAABBCCDD
typedef struct _SCMGR_HANDLE
{
if (!Expanded)
{
DPRINT("Error allocating memory for boot driver name!\n");
+ RtlFreeUnicodeString(&NtPathName);
return ERROR_NOT_ENOUGH_MEMORY;
}
ExpandedLen = NtPathName.Length / sizeof(WCHAR);
wcsncpy(Expanded, NtPathName.Buffer, ExpandedLen);
Expanded[ExpandedLen] = UNICODE_NULL;
+ RtlFreeUnicodeString(&NtPathName);
if (ServiceNameLen > ExpandedLen &&
!_wcsnicmp(Expanded, CanonName, ExpandedLen))
{
+ HeapFree(GetProcessHeap(), 0, Expanded);
+
/* Only \SystemRoot\ is missing */
*RelativeName = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
if (*RelativeName == NULL)
{
DPRINT("Error allocating memory for boot driver name!\n");
- HeapFree(GetProcessHeap(), 0, Expanded);
return ERROR_NOT_ENOUGH_MEMORY;
}
wcscpy(*RelativeName, L"\\SystemRoot\\");
wcscat(*RelativeName, CanonName + ExpandedLen);
- RtlFreeUnicodeString(&NtPathName);
return ERROR_SUCCESS;
}
+ /* No longer need this */
+ HeapFree(GetProcessHeap(), 0, Expanded);
+
/* The most complex case starts here */
RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot");
InitializeObjectAttributes(&ObjectAttributes,
/* Open this symlink */
Status = NtOpenSymbolicLinkObject(&SymbolicLinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes);
-
if (NT_SUCCESS(Status))
{
- LinkTarget.Length = 0;
- LinkTarget.MaximumLength = 0;
-
DPRINT("Opened symbolic link object\n");
+ RtlInitEmptyUnicodeString(&LinkTarget, NULL, 0);
Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize);
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL)
{
/* Check if required buffer size is sane */
- if (BufferSize > 0xFFFD)
+ if (BufferSize > UNICODE_STRING_MAX_BYTES - sizeof(UNICODE_NULL))
{
DPRINT("Too large buffer required\n");
- if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
- HeapFree(GetProcessHeap(), 0, Expanded);
+ NtClose(SymbolicLinkHandle);
return ERROR_NOT_ENOUGH_MEMORY;
}
if (!LinkTarget.Buffer)
{
DPRINT("Unable to alloc buffer\n");
- if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
- HeapFree(GetProcessHeap(), 0, Expanded);
+ NtClose(SymbolicLinkHandle);
return ERROR_NOT_ENOUGH_MEMORY;
}
/* Do a real query now */
Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize);
+ NtClose(SymbolicLinkHandle);
if (NT_SUCCESS(Status))
{
DPRINT("LinkTarget: %wZ\n", &LinkTarget);
if (*RelativeName == NULL)
{
DPRINT("Unable to alloc buffer\n");
- if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
- HeapFree(GetProcessHeap(), 0, Expanded);
- RtlFreeUnicodeString(&NtPathName);
return ERROR_NOT_ENOUGH_MEMORY;
}
wcscpy(*RelativeName, L"\\SystemRoot\\");
wcscat(*RelativeName, CanonName+ExpandedLen+1);
- /* Cleanup */
- if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
- HeapFree(GetProcessHeap(), 0, Expanded);
- RtlFreeUnicodeString(&NtPathName);
-
/* Return success */
return ERROR_SUCCESS;
}
else
{
- if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
- HeapFree(GetProcessHeap(), 0, Expanded);
- RtlFreeUnicodeString(&NtPathName);
return ERROR_INVALID_PARAMETER;
}
}
else
{
DPRINT("Error, Status = %08X\n", Status);
- if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
- HeapFree(GetProcessHeap(), 0, Expanded);
- RtlFreeUnicodeString(&NtPathName);
return ERROR_INVALID_PARAMETER;
}
}
else
{
DPRINT("Error, Status = %08X\n", Status);
- if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
- HeapFree(GetProcessHeap(), 0, Expanded);
- RtlFreeUnicodeString(&NtPathName);
+ NtClose(SymbolicLinkHandle);
return ERROR_INVALID_PARAMETER;
}
}
{
/* Failure */
DPRINT("Error, Status = %08X\n", Status);
- HeapFree(GetProcessHeap(), 0, Expanded);
return ERROR_INVALID_PARAMETER;
}
}
if (dwError != ERROR_SUCCESS)
return dwError;
- dwSize = MAX_PATH;
+ dwSize = MAX_PATH * sizeof(WCHAR);
/* Check for the DependOnService Value */
dwError = RegQueryValueExW(hServiceEnumKey,
{
DPRINT("Found manager handle\n");
- /* FIXME: add handle cleanup code */
+ /* Make sure we don't access stale memory if someone tries to use this handle again. */
+ hManager->Handle.Tag = INVALID_TAG;
HeapFree(GetProcessHeap(), 0, hManager);
hManager = NULL;
{
DPRINT("Found service handle\n");
- /* Lock the service database exlusively */
+ /* Lock the service database exclusively */
ScmLockDatabaseExclusive();
/* Get the pointer to the service record */
lpService = hService->ServiceEntry;
- /* FIXME: add handle cleanup code */
+ /* Make sure we don't access stale memory if someone tries to use this handle again. */
+ hService->Handle.Tag = INVALID_TAG;
/* Free the handle */
HeapFree(GetProcessHeap(), 0, hService);
return ERROR_SUCCESS;
}
- /* There are no references and no runnning dependencies,
+ /* There are no references and no running dependencies,
it is now safe to delete the service */
/* Delete the Service Key */
- dwError = RegDeleteKeyW(hServicesKey,
- lpService->lpServiceName);
+ dwError = ScmDeleteRegKey(hServicesKey,
+ lpService->lpServiceName);
RegCloseKey(hServicesKey);
DWORD dwControlsAccepted;
DWORD dwCurrentState;
HKEY hServicesKey = NULL;
- LPCWSTR lpErrorStrings[2];
+ LPCWSTR lpLogStrings[2];
+ WCHAR szLogBuffer[80];
+ UINT uID;
DPRINT("RControlService() called\n");
if (dwError == ERROR_SUCCESS)
{
- if (dwControl != SERVICE_CONTROL_INTERROGATE)
+ if (dwControl == SERVICE_CONTROL_STOP ||
+ dwControl == SERVICE_CONTROL_PAUSE ||
+ dwControl == SERVICE_CONTROL_CONTINUE)
{
- /* Log a sucessful send control */
- lpErrorStrings[0] = lpService->lpDisplayName;
+ /* Log a successful send control */
- switch(dwControl)
+ switch (dwControl)
{
case SERVICE_CONTROL_STOP:
- lpErrorStrings[1] = L"stop";
+ uID = IDS_SERVICE_STOP;
break;
case SERVICE_CONTROL_PAUSE:
- lpErrorStrings[1] = L"pause";
+ uID = IDS_SERVICE_PAUSE;
break;
case SERVICE_CONTROL_CONTINUE:
- lpErrorStrings[1] = L"continue";
- break;
-
- default:
- lpErrorStrings[1] = L"other";
+ uID = IDS_SERVICE_RESUME;
break;
}
+ LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, 80);
+
+ lpLogStrings[0] = lpService->lpDisplayName;
+ lpLogStrings[1] = szLogBuffer;
ScmLogEvent(EVENT_SERVICE_CONTROL_SUCCESS,
EVENTLOG_INFORMATION_TYPE,
2,
- lpErrorStrings);
+ lpLogStrings);
}
}
DWORD dwBytesNeeded;
DWORD dwError;
-
- SECURITY_DESCRIPTOR ObjectDescriptor;
-
DPRINT("RQueryServiceObjectSecurity() called\n");
hSvc = ScmGetServiceFromHandle(hService);
/* Lock the service database */
ScmLockDatabaseShared();
-
- /* hack */
- Status = RtlCreateSecurityDescriptor(&ObjectDescriptor, SECURITY_DESCRIPTOR_REVISION);
-
- Status = RtlQuerySecurityObject(&ObjectDescriptor /* lpService->lpSecurityDescriptor */,
+ /* Retrieve the security descriptor */
+ Status = RtlQuerySecurityObject(lpService->pSecurityDescriptor,
dwSecurityInformation,
(PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
cbBufSize,
SC_RPC_HANDLE hService,
DWORD dwSecurityInformation,
LPBYTE lpSecurityDescriptor,
- DWORD dwSecuityDescriptorSize)
+ DWORD dwSecurityDescriptorSize)
{
PSERVICE_HANDLE hSvc;
PSERVICE lpService;
- ULONG DesiredAccess = 0;
- /* HANDLE hToken = NULL; */
- HKEY hServiceKey;
- /* NTSTATUS Status; */
+ ACCESS_MASK DesiredAccess = 0;
+ HANDLE hToken = NULL;
+ HKEY hServiceKey = NULL;
+ BOOL bDatabaseLocked = FALSE;
+ NTSTATUS Status;
DWORD dwError;
DPRINT("RSetServiceObjectSecurity() called\n");
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
DesiredAccess))
{
- DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
return ERROR_ACCESS_DENIED;
}
lpService = hSvc->ServiceEntry;
if (lpService == NULL)
{
- DPRINT("lpService == NULL!\n");
+ DPRINT1("lpService == NULL!\n");
return ERROR_INVALID_HANDLE;
}
RpcRevertToSelf();
#endif
- /* Lock the service database exclusive */
- ScmLockDatabaseExclusive();
-
-#if 0
+ /* Build the new security descriptor */
Status = RtlSetSecurityObject(dwSecurityInformation,
(PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
- &lpService->lpSecurityDescriptor,
+ &lpService->pSecurityDescriptor,
&ScmServiceMapping,
hToken);
if (!NT_SUCCESS(Status))
dwError = RtlNtStatusToDosError(Status);
goto Done;
}
-#endif
+ /* Lock the service database exclusive */
+ ScmLockDatabaseExclusive();
+ bDatabaseLocked = TRUE;
+
+ /* Open the service key */
dwError = ScmOpenServiceKey(lpService->lpServiceName,
READ_CONTROL | KEY_CREATE_SUB_KEY | KEY_SET_VALUE,
&hServiceKey);
if (dwError != ERROR_SUCCESS)
goto Done;
- UNIMPLEMENTED;
- dwError = ERROR_SUCCESS;
-// dwError = ScmWriteSecurityDescriptor(hServiceKey,
-// lpService->lpSecurityDescriptor);
+ /* Store the new security descriptor */
+ dwError = ScmWriteSecurityDescriptor(hServiceKey,
+ lpService->pSecurityDescriptor);
RegFlushKey(hServiceKey);
- RegCloseKey(hServiceKey);
Done:
+ if (hServiceKey != NULL)
+ RegCloseKey(hServiceKey);
+
+ /* Unlock service database */
+ if (bDatabaseLocked == TRUE)
+ ScmUnlockDatabase();
-#if 0
if (hToken != NULL)
NtClose(hToken);
-#endif
-
- /* Unlock service database */
- ScmUnlockDatabase();
DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError);
PSERVICE lpService;
DWORD dwPreviousState;
DWORD dwPreviousType;
- LPCWSTR lpErrorStrings[2];
- WCHAR szErrorBuffer[32];
+ LPCWSTR lpLogStrings[2];
+ WCHAR szLogBuffer[80];
+ UINT uID;
DPRINT("RSetServiceStatus() called\n");
DPRINT("hServiceStatus = %lu\n", hServiceStatus);
(lpServiceStatus->dwWin32ExitCode != ERROR_SUCCESS))
{
/* Log a failed service stop */
- swprintf(szErrorBuffer, L"%lu", lpServiceStatus->dwWin32ExitCode);
- lpErrorStrings[0] = lpService->lpDisplayName;
- lpErrorStrings[1] = szErrorBuffer;
+ swprintf(szLogBuffer, L"%lu", lpServiceStatus->dwWin32ExitCode);
+ lpLogStrings[0] = lpService->lpDisplayName;
+ lpLogStrings[1] = szLogBuffer;
ScmLogEvent(EVENT_SERVICE_EXIT_FAILED,
EVENTLOG_ERROR_TYPE,
2,
- lpErrorStrings);
+ lpLogStrings);
}
else if (lpServiceStatus->dwCurrentState != dwPreviousState &&
(lpServiceStatus->dwCurrentState == SERVICE_STOPPED ||
lpServiceStatus->dwCurrentState == SERVICE_PAUSED))
{
/* Log a successful service status change */
- lpErrorStrings[0] = lpService->lpDisplayName;
-
switch(lpServiceStatus->dwCurrentState)
{
case SERVICE_STOPPED:
- lpErrorStrings[1] = L"stopped";
+ uID = IDS_SERVICE_STOPPED;
break;
case SERVICE_RUNNING:
- lpErrorStrings[1] = L"running";
+ uID = IDS_SERVICE_RUNNING;
break;
case SERVICE_PAUSED:
- lpErrorStrings[1] = L"paused";
+ uID = IDS_SERVICE_PAUSED;
break;
}
+ LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, 80);
+ lpLogStrings[0] = lpService->lpDisplayName;
+ lpLogStrings[1] = szLogBuffer;
+
ScmLogEvent(EVENT_SERVICE_STATUS_SUCCESS,
EVENTLOG_INFORMATION_TYPE,
2,
- lpErrorStrings);
+ lpLogStrings);
}
DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState);
return ERROR_ACCESS_DENIED;
}
+ /* Check for invalid service type value */
+ if ((dwServiceType != SERVICE_NO_CHANGE) &&
+ (dwServiceType != SERVICE_KERNEL_DRIVER) &&
+ (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) &&
+ ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) &&
+ ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_SHARE_PROCESS))
+ return ERROR_INVALID_PARAMETER;
+
+ /* Check for invalid start type value */
+ if ((dwStartType != SERVICE_NO_CHANGE) &&
+ (dwStartType != SERVICE_BOOT_START) &&
+ (dwStartType != SERVICE_SYSTEM_START) &&
+ (dwStartType != SERVICE_AUTO_START) &&
+ (dwStartType != SERVICE_DEMAND_START) &&
+ (dwStartType != SERVICE_DISABLED))
+ return ERROR_INVALID_PARAMETER;
+
+ /* Only drivers can be boot start or system start services */
+ if ((dwStartType == SERVICE_BOOT_START) ||
+ (dwStartType == SERVICE_SYSTEM_START))
+ {
+ if ((dwServiceType != SERVICE_KERNEL_DRIVER) &&
+ (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER))
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* Check for invalid error control value */
+ if ((dwErrorControl != SERVICE_NO_CHANGE) &&
+ (dwErrorControl != SERVICE_ERROR_IGNORE) &&
+ (dwErrorControl != SERVICE_ERROR_NORMAL) &&
+ (dwErrorControl != SERVICE_ERROR_SEVERE) &&
+ (dwErrorControl != SERVICE_ERROR_CRITICAL))
+ return ERROR_INVALID_PARAMETER;
+
lpService = hSvc->ServiceEntry;
if (lpService == NULL)
{
goto done;
}
+ wcscpy(lpDisplayNameW, lpDisplayName);
if (lpService->lpDisplayName != lpService->lpServiceName)
HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
goto done;
}
+ /* Set the tag */
if (lpdwTagId != NULL)
{
dwError = ScmAssignNewTag(lpService);
if (lpPassword != NULL)
{
- /* FIXME: Decrypt and write password */
+ if (wcslen((LPWSTR)lpPassword) != 0)
+ {
+ /* FIXME: Decrypt the password */
+
+ /* Write the password */
+ dwError = ScmSetServicePassword(lpService->szServiceName,
+ (LPCWSTR)lpPassword);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+ else
+ {
+ /* Delete the password */
+ dwError = ScmSetServicePassword(lpService->szServiceName,
+ NULL);
+ if (dwError == ERROR_FILE_NOT_FOUND)
+ dwError = ERROR_SUCCESS;
+
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
}
done:
if ((dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) &&
(lpServiceStartName))
{
- return ERROR_INVALID_PARAMETER;
+ /* We allow LocalSystem to run interactive. */
+ if (wcsicmp(lpServiceStartName, L"LocalSystem"))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
}
if (lpdwTagId && (!lpLoadOrderGroup || !*lpLoadOrderGroup))
goto done;
}
+ /* Assign the default security descriptor */
+ if (dwServiceType & SERVICE_WIN32)
+ {
+ dwError = ScmCreateDefaultServiceSD(&lpService->pSecurityDescriptor);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
/* Write service data to the registry */
/* Create the service key */
dwError = ScmCreateServiceKey(lpServiceName,
goto done;
}
+ /* Set the service tag */
if (lpdwTagId != NULL)
{
dwError = RegSetValueExW(hServiceKey,
goto done;
}
- /* Write service start name */
+ /* Start name and password are only used by Win32 services */
if (dwServiceType & SERVICE_WIN32)
{
+ /* Write service start name */
lpObjectName = (lpServiceStartName != NULL) ? (LPWSTR)lpServiceStartName : L"LocalSystem";
dwError = RegSetValueExW(hServiceKey,
L"ObjectName",
(DWORD)((wcslen(lpObjectName) + 1) * sizeof(WCHAR)));
if (dwError != ERROR_SUCCESS)
goto done;
- }
- if (lpPassword != NULL)
- {
- /* FIXME: Decrypt and write password */
+ if (lpPassword != NULL && wcslen((LPWSTR)lpPassword) != 0)
+ {
+ /* FIXME: Decrypt the password */
+
+ /* Write the password */
+ dwError = ScmSetServicePassword(lpServiceName,
+ (LPCWSTR)lpPassword);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+DPRINT1("\n");
+ /* Write the security descriptor */
+ dwError = ScmWriteSecurityDescriptor(hServiceKey,
+ lpService->pSecurityDescriptor);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
}
dwError = ScmCreateServiceHandle(lpService,
dwDependSize);
HeapFree(GetProcessHeap(), 0, lpDependenciesW);
+
+ if (dwError != ERROR_SUCCESS)
+ goto done;
}
if (lpPassword != NULL)
{
- /* FIXME: Decrypt and write password */
+ if (wcslen((LPWSTR)lpPassword) != 0)
+ {
+ /* FIXME: Decrypt the password */
+
+ /* Write the password */
+ dwError = ScmSetServicePassword(lpService->szServiceName,
+ (LPCWSTR)lpPassword);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+ else
+ {
+ /* Delete the password */
+ dwError = ScmSetServicePassword(lpService->szServiceName,
+ NULL);
+ if (dwError == ERROR_FILE_NOT_FOUND)
+ dwError = ERROR_SUCCESS;
+
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
}
done:
LPWSTR lpLoadOrderGroup,
LPDWORD lpState)
{
- UNIMPLEMENTED;
- return ERROR_CALL_NOT_IMPLEMENTED;
+ PMANAGER_HANDLE hManager;
+ PSERVICE_GROUP pServiceGroup;
+ DWORD dwError = ERROR_SUCCESS;
+
+ DPRINT("RI_ScGetCurrentGroupStateW() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hManager = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hManager == NULL)
+ {
+ DPRINT1("Invalid service manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* Check for SC_MANAGER_ENUMERATE_SERVICE access right */
+ if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
+ SC_MANAGER_ENUMERATE_SERVICE))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n",
+ hManager->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ /* Lock the service database shared */
+ ScmLockDatabaseShared();
+
+ /* Get the group list entry */
+ pServiceGroup = ScmGetServiceGroupByName(lpLoadOrderGroup);
+ if (pServiceGroup == NULL)
+ {
+ dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+ goto done;
+ }
+
+ /* FIXME: Return the group state */
+ *lpState = 0;
+
+done:
+ /* Unlock the service database */
+ ScmUnlockDatabase();
+
+ DPRINT("RI_ScGetCurrentGroupStateW() done (Error %lu)\n", dwError);
+
+ return dwError;
}
if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
{
LPSERVICE_DESCRIPTIONW lpServiceDescriptionW;
- //LPSERVICE_DESCRIPTIONA lpServiceDescriptionA;
+ LPSERVICE_DESCRIPTIONA lpServiceDescriptionA;
- //lpServiceDescriptionA = Info.psd;
+ lpServiceDescriptionA = Info.psd;
- ///if (lpServiceDescriptionA &&
- ///lpServiceDescriptionA->lpDescription)
- ///{
- dwLength = (DWORD)((strlen(Info.lpDescription) + 1) * sizeof(WCHAR));
+ if (lpServiceDescriptionA &&
+ lpServiceDescriptionA->lpDescription)
+ {
+ dwLength = (DWORD)((strlen(lpServiceDescriptionA->lpDescription) + 1) * sizeof(WCHAR));
lpServiceDescriptionW = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
MultiByteToWideChar(CP_ACP,
0,
- Info.lpDescription,
+ lpServiceDescriptionA->lpDescription,
-1,
lpServiceDescriptionW->lpDescription,
dwLength);
ptr = lpServiceDescriptionW;
InfoW.psd = lpServiceDescriptionW;
- ///}
+ }
}
else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
{
static DWORD
-ScmSetFailureActions(PSERVICE_HANDLE hSvc,
- PSERVICE lpService,
- HKEY hServiceKey,
+ScmSetFailureActions(HKEY hServiceKey,
LPSERVICE_FAILURE_ACTIONSW lpFailureActions)
{
LPSERVICE_FAILURE_ACTIONSW lpReadBuffer = NULL;
LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer = NULL;
- BOOL bIsActionRebootSet = FALSE;
- DWORD dwDesiredAccess = SERVICE_CHANGE_CONFIG;
DWORD dwRequiredSize = 0;
DWORD dwType = 0;
- DWORD i = 0;
DWORD dwError;
/* There is nothing to be done if we have no failure actions */
return ERROR_SUCCESS;
/*
- * 1- Check whether or not we can set
- * failure actions for this service.
- */
-
- /* Failure actions can only be set for Win32 services, not for drivers */
- if (lpService->Status.dwServiceType & SERVICE_DRIVER)
- return ERROR_CANNOT_DETECT_DRIVER_FAILURE;
-
- /*
- * If the service controller handles the SC_ACTION_RESTART action,
- * hService must have the SERVICE_START access right.
- *
- * If you specify SC_ACTION_REBOOT, the caller must have the
- * SE_SHUTDOWN_NAME privilege.
- */
- if (lpFailureActions->cActions > 0 &&
- lpFailureActions->lpsaActions != NULL)
- {
- for (i = 0; i < lpFailureActions->cActions; ++i)
- {
- if (lpFailureActions->lpsaActions[i].Type == SC_ACTION_RESTART)
- dwDesiredAccess |= SERVICE_START;
- else if (lpFailureActions->lpsaActions[i].Type == SC_ACTION_REBOOT)
- bIsActionRebootSet = TRUE;
- }
- }
-
- /* Re-check the access rights */
- if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
- dwDesiredAccess))
- {
- DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
- return ERROR_ACCESS_DENIED;
- }
-
- /* FIXME: Check if the caller has the SE_SHUTDOWN_NAME privilege */
- if (bIsActionRebootSet)
- {
- }
-
- /*
- * 2- Retrieve the original value of FailureActions.
+ * 1- Retrieve the original value of FailureActions.
*/
/* Query value length */
lpReadBuffer->lpCommand = NULL;
/*
- * 3- Initialize the new value to set.
+ * 2- Initialize the new value to set.
*/
dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
PSERVICE_HANDLE hSvc;
PSERVICE lpService = NULL;
HKEY hServiceKey = NULL;
+ ACCESS_MASK RequiredAccess = SERVICE_CHANGE_CONFIG;
DPRINT("RChangeServiceConfig2W() called\n");
DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
hSvc = ScmGetServiceFromHandle(hService);
if (hSvc == NULL)
{
- DPRINT1("Invalid service handle!\n");
+ DPRINT("Invalid service handle!\n");
return ERROR_INVALID_HANDLE;
}
+ if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
+ RequiredAccess |= SERVICE_START;
+
+ /* Check the access rights */
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
- SERVICE_CHANGE_CONFIG))
+ RequiredAccess))
{
DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
return ERROR_ACCESS_DENIED;
}
+ if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
+ {
+ /* FIXME: Check if the caller has the SE_SHUTDOWN_NAME privilege */
+
+ }
+
lpService = hSvc->ServiceEntry;
if (lpService == NULL)
{
return ERROR_INVALID_HANDLE;
}
+ /* Failure actions can only be set for Win32 services, not for drivers */
+ if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
+ {
+ if (lpService->Status.dwServiceType & SERVICE_DRIVER)
+ return ERROR_CANNOT_DETECT_DRIVER_FAILURE;
+ }
+
/* Lock the service database exclusively */
ScmLockDatabaseExclusive();
}
else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
{
- dwError = ScmSetFailureActions(hSvc,
- lpService,
- hServiceKey,
+ dwError = ScmSetFailureActions(hServiceKey,
(LPSERVICE_FAILURE_ACTIONSW)Info.psfa);
}
&lpService->Status,
sizeof(SERVICE_STATUS));
- lpStatus->dwProcessId = (lpService->lpImage != NULL) ? lpService->lpImage->dwProcessId : 0; /* FIXME */
+ /* Copy the service process ID */
+ if ((lpService->Status.dwCurrentState == SERVICE_STOPPED) || (lpService->lpImage == NULL))
+ lpStatus->dwProcessId = 0;
+ else
+ lpStatus->dwProcessId = lpService->lpImage->dwProcessId;
+
lpStatus->dwServiceFlags = 0; /* FIXME */
/* Unlock the service database */
if (!pszGroupNameW)
{
DPRINT("Failed to allocate buffer!\n");
- return ERROR_NOT_ENOUGH_MEMORY;
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto Done;
}
MultiByteToWideChar(CP_ACP,
if (!lpStatusPtrW)
{
DPRINT("Failed to allocate buffer!\n");
- return ERROR_NOT_ENOUGH_MEMORY;
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto Done;
}
}
&lpStatusPtrIncrW->ServiceStatusProcess,
sizeof(SERVICE_STATUS));
- lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrIncrW->ServiceStatusProcess.dwProcessId; /* FIXME */
+ /* Copy the service process ID */
+ lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrIncrW->ServiceStatusProcess.dwProcessId;
+
lpStatusPtrA->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
lpStatusPtrIncrW++;
memcpy(&lpStatusPtr->ServiceStatusProcess,
&CurrentService->Status,
sizeof(SERVICE_STATUS));
- lpStatusPtr->ServiceStatusProcess.dwProcessId =
- (CurrentService->lpImage != NULL) ? CurrentService->lpImage->dwProcessId : 0; /* FIXME */
+
+ /* Copy the service process ID */
+ if ((CurrentService->Status.dwCurrentState == SERVICE_STOPPED) || (CurrentService->lpImage == NULL))
+ lpStatusPtr->ServiceStatusProcess.dwProcessId = 0;
+ else
+ lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->lpImage->dwProcessId;
+
lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
lpStatusPtr++;