mirror of
https://github.com/reactos/reactos.git
synced 2025-08-01 19:33:23 +00:00
[SERVICES]
Fix yet another MSDN bug: ChangeServiceConfig2 ALWAYS requires SERVICE_CHANGE_CONFIG and SERVICE_START access rights and an enabled SE_SHUTDOWN_PRIVILEGE privilege when you try to set the failure actions. Otherwise, you will just get a STATUS_ACCESS_DENIED. - Remove the access and privilege checks from ScmSetFailureActions and move them to RChangeServiceConfig2W. svn path=/trunk/; revision=71814
This commit is contained in:
parent
8fdfbb5bd0
commit
8b24e1b048
1 changed files with 24 additions and 54 deletions
|
@ -5018,18 +5018,13 @@ DWORD RChangeServiceConfig2A(
|
||||||
|
|
||||||
|
|
||||||
static DWORD
|
static DWORD
|
||||||
ScmSetFailureActions(PSERVICE_HANDLE hSvc,
|
ScmSetFailureActions(HKEY hServiceKey,
|
||||||
PSERVICE lpService,
|
|
||||||
HKEY hServiceKey,
|
|
||||||
LPSERVICE_FAILURE_ACTIONSW lpFailureActions)
|
LPSERVICE_FAILURE_ACTIONSW lpFailureActions)
|
||||||
{
|
{
|
||||||
LPSERVICE_FAILURE_ACTIONSW lpReadBuffer = NULL;
|
LPSERVICE_FAILURE_ACTIONSW lpReadBuffer = NULL;
|
||||||
LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer = NULL;
|
LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer = NULL;
|
||||||
BOOL bIsActionRebootSet = FALSE;
|
|
||||||
DWORD dwDesiredAccess = SERVICE_CHANGE_CONFIG;
|
|
||||||
DWORD dwRequiredSize = 0;
|
DWORD dwRequiredSize = 0;
|
||||||
DWORD dwType = 0;
|
DWORD dwType = 0;
|
||||||
DWORD i = 0;
|
|
||||||
DWORD dwError;
|
DWORD dwError;
|
||||||
|
|
||||||
/* There is nothing to be done if we have no failure actions */
|
/* There is nothing to be done if we have no failure actions */
|
||||||
|
@ -5037,48 +5032,7 @@ ScmSetFailureActions(PSERVICE_HANDLE hSvc,
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1- Check whether or not we can set
|
* 1- Retrieve the original value of FailureActions.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Query value length */
|
/* Query value length */
|
||||||
|
@ -5145,7 +5099,7 @@ ScmSetFailureActions(PSERVICE_HANDLE hSvc,
|
||||||
lpReadBuffer->lpCommand = NULL;
|
lpReadBuffer->lpCommand = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 3- Initialize the new value to set.
|
* 2- Initialize the new value to set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
|
dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
|
||||||
|
@ -5292,6 +5246,7 @@ DWORD RChangeServiceConfig2W(
|
||||||
PSERVICE_HANDLE hSvc;
|
PSERVICE_HANDLE hSvc;
|
||||||
PSERVICE lpService = NULL;
|
PSERVICE lpService = NULL;
|
||||||
HKEY hServiceKey = NULL;
|
HKEY hServiceKey = NULL;
|
||||||
|
ACCESS_MASK RequiredAccess = SERVICE_CHANGE_CONFIG;
|
||||||
|
|
||||||
DPRINT("RChangeServiceConfig2W() called\n");
|
DPRINT("RChangeServiceConfig2W() called\n");
|
||||||
DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
|
DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
|
||||||
|
@ -5302,17 +5257,27 @@ DWORD RChangeServiceConfig2W(
|
||||||
hSvc = ScmGetServiceFromHandle(hService);
|
hSvc = ScmGetServiceFromHandle(hService);
|
||||||
if (hSvc == NULL)
|
if (hSvc == NULL)
|
||||||
{
|
{
|
||||||
DPRINT1("Invalid service handle!\n");
|
DPRINT("Invalid service handle!\n");
|
||||||
return ERROR_INVALID_HANDLE;
|
return ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
|
||||||
|
RequiredAccess |= SERVICE_START;
|
||||||
|
|
||||||
|
/* Check the access rights */
|
||||||
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
|
||||||
SERVICE_CHANGE_CONFIG))
|
RequiredAccess))
|
||||||
{
|
{
|
||||||
DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
|
||||||
return ERROR_ACCESS_DENIED;
|
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;
|
lpService = hSvc->ServiceEntry;
|
||||||
if (lpService == NULL)
|
if (lpService == NULL)
|
||||||
{
|
{
|
||||||
|
@ -5320,6 +5285,13 @@ DWORD RChangeServiceConfig2W(
|
||||||
return ERROR_INVALID_HANDLE;
|
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 */
|
/* Lock the service database exclusively */
|
||||||
ScmLockDatabaseExclusive();
|
ScmLockDatabaseExclusive();
|
||||||
|
|
||||||
|
@ -5372,9 +5344,7 @@ DWORD RChangeServiceConfig2W(
|
||||||
}
|
}
|
||||||
else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
|
else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
|
||||||
{
|
{
|
||||||
dwError = ScmSetFailureActions(hSvc,
|
dwError = ScmSetFailureActions(hServiceKey,
|
||||||
lpService,
|
|
||||||
hServiceKey,
|
|
||||||
(LPSERVICE_FAILURE_ACTIONSW)Info.psfa);
|
(LPSERVICE_FAILURE_ACTIONSW)Info.psfa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue