i try to use ChangeServiceConfig2 to change the settings of a service to restart on crash.
Although i run it with higher privilege (on Win7 64bit) and have the permission to change directly in the registry, the function keeps returning 'Access denied'.
Any idea what i'm doing wrong?
Thanks for the help.
Code: Select all
Enumeration ;SC_ACTION_TYPE
#SC_ACTION_NONE ;0 - no action.
#SC_ACTION_RESTART ;1 - restart the service.
#SC_ACTION_REBOOT ;2 - reboot the computer.
#SC_ACTION_RUN_COMMAND ;3 - run a command.
EndEnumeration
Enumeration 1 ;dwInfoLevel = Configuration information to be changed
#SERVICE_CONFIG_DESCRIPTION ;1 - The lpInfo parameter is a pointer To a SERVICE_DESCRIPTION Structure.
#SERVICE_CONFIG_FAILURE_ACTIONS ;2 - The lpInfo parameter is a pointer To a SERVICE_FAILURE_ACTIONS Structure.
#SERVICE_CONFIG_DELAYED_AUTO_START_INFO ;3 - The lpInfo parameter is a pointer To a SERVICE_DELAYED_AUTO_START_INFO Structure. (XP not supported)
#SERVICE_CONFIG_FAILURE_ACTIONS_FLAG ;4 - The lpInfo parameter is a pointer To a SERVICE_FAILURE_ACTIONS_FLAG Structure. (XP not supported)
#SERVICE_CONFIG_SERVICE_SID_INFO ;5 - The lpInfo parameter is a pointer To a SERVICE_SID_INFO Structure.
#SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO ;6 - The lpInfo parameter is a pointer To a SERVICE_REQUIRED_PRIVILEGES_INFO Structure. (XP not supported)
#SERVICE_CONFIG_PRESHUTDOWN_INFO ;7 - The lpInfo parameter is a pointer To a SERVICE_PRESHUTDOWN_INFO Structure. (XP not supported)
#SERVICE_CONFIG_TRIGGER_INFO ;8 - The lpInfo parameter is a pointer To a SERVICE_TRIGGER_INFO Structure. (XP not supported)
#SERVICE_CONFIG_PREFERRED_NODE ;9 - The lpInfo parameter is a pointer To a SERVICE_PREFERRED_NODE_INFO Structure. (XP not supported)
EndEnumeration
Structure SC_ACTION
type.l ;SC_ACTION_TYPE
delay.l ;(in milliseconds)
EndStructure
Structure SERVICE_FAILURE_ACTIONS
dwResetPeriod.l ;The time after which to reset the failure count to zero if there are no failures, in seconds. Specify INFINITE to indicate that this value should never be reset.
lpRebootMsg.l ;The message to be broadcast before rebooting in response to the SC_ACTION_REBOOT service controller action (#NULL = message is unchanged, "" = no message is broadcast)
lpCommand.l ;The command line of the process for the CreateProcess function to execute in response to the SC_ACTION_RUN_COMMAND service controller action
cActions.l ;Number of elements in the lpsaActions array
*lpsaActions ;Pointer to an array of SC_ACTION structures
EndStructure
Prototype.l ProtoChange(hService.l, dwInfoLevel.l, sfa.l)
;===================================
Procedure.s GetLastError()
Msg$ = ""
error.l = GetLastError_()
If error
*Buffer = AllocateMemory(255)
If *Buffer
FormatMessage_ (#FORMAT_MESSAGE_FROM_SYSTEM, #Null, error, 0, *Buffer, 255, #Null)
Msg$ = PeekS(*Buffer)
FreeMemory(*Buffer)
EndIf
EndIf
ProcedureReturn Msg$
EndProcedure
;===================================
Computername$ = ""
Servicename$ = "MozillaMaintenance" ;<-- enter an existing service here
LibNr.i = OpenLibrary(#PB_Any,"advapi32.dll")
If LibNr
CompilerIf #PB_Compiler_Unicode
ChangeServiceConfig2.ProtoChange = GetFunction(LibNr, "ChangeServiceConfig2W")
CompilerElse
ChangeServiceConfig2.ProtoChange = GetFunction(LibNr, "ChangeServiceConfig2A")
CompilerEndIf
;
hSCObject.i = OpenSCManager_(Computername$, 0, #SC_MANAGER_ALL_ACCESS)
If hSCObject
hService.i = OpenService_(hSCObject, Servicename$, #SERVICE_ALL_ACCESS)
If hService
;
Dim sca.SC_ACTION(3)
sca(0)\type = #SC_ACTION_RESTART
sca(0)\delay = 2000
sca(1)\type = #SC_ACTION_NONE
sca(1)\delay = 0
sca(2)\type = #SC_ACTION_NONE
sca(2)\delay = 0
;
sfa.SERVICE_FAILURE_ACTIONS
sfa\dwResetPeriod = #INFINITE
sfa\lpRebootMsg = #Null
sfa\lpCommand = 0
sfa\cActions = 3
sfa\lpsaActions = sca()
;
If ChangeServiceConfig2(hService, #SERVICE_CONFIG_FAILURE_ACTIONS, sfa)
Debug "OK"
Else
Debug "Unable to change the configuration (" + GetLastError() + ")"
EndIf
;
CloseServiceHandle_(hService)
Else
Debug "Unable to open the service (" + GetLastError() + ")"
EndIf
CloseServiceHandle_(hSCObject)
Else
Debug "Unable to call the service manager (" + GetLastError() + ")"
EndIf
CloseLibrary(LibNr)
EndIf