Jump to content
tatane

[SOLVED] Set recovery properties of Windows service

Recommended Posts

tatane
Posted (edited)

Hi,

Sorry this post is a copy of this one but i've got no answer :-(

 

I would like to use ChangeServiceConfig2 function to set recovery properties of a Windows service but it doesn't work.

https://msdn.microsoft.com/en-us/library/windows/desktop/ms681988(v=vs.85).aspx

I'm using _Service_UDF v4 library.

Here is my code :

Func _ChangeServiceConfig2($sServiceName, $sComputerName = "")
    Local $hSC, $hService, $rdll
    $hSC = OpenSCManager($sComputerName, $SC_MANAGER_CONNECT)
    $hService = OpenService($hSC, $sServiceName, $SERVICE_CHANGE_CONFIG)

    ;~ typedef struct _SERVICE_FAILURE_ACTIONS {
    ;~   DWORD     dwResetPeriod;
    ;~   LPTSTR    lpRebootMsg;
    ;~   LPTSTR    lpCommand;
    ;~   DWORD     cActions;
    ;~   SC_ACTION *lpsaActions;
    ;~  } SERVICE_FAILURE_ACTIONS, *LPSERVICE_FAILURE_ACTIONS;

    ;~  typedef struct _SC_ACTION {
    ;~   SC_ACTION_TYPE Type;
    ;~   DWORD          Delay;
    ;~ } SC_ACTION, *LPSC_ACTION;

    Local $SC_ACTION_NONE = 0
    Local $SC_ACTION_REBOOT = 2
    Local $SC_ACTION_RESTART = 1
    Local $SC_ACTION_RUN_COMMAND = 3
    Local $SERVICE_CONFIG_FAILURE_ACTIONS = 2

    Local $sc_action = DllStructCreate("int Type; DWORD Delay")
    DllStructSetData($sc_action, "Type", $SC_ACTION_RESTART)
    DllStructSetData($sc_action, "Delay", 1000)

    Local Const $sTagSC_ACTION = "int;dword"
    Local $iNumberOfArrayElement = 1

    Local $tArraySC_ACTION = DllStructCreate($sTagSC_ACTION)
    DllStructSetData($tArraySC_ACTION, 1, $SC_ACTION_RESTART)
    DllStructSetData($tArraySC_ACTION, 2, 10000)
    Local $PtrSC_ACTION_Array = DllStructGetPtr($tArraySC_ACTION)

    Local $serviceFailureActions = DllStructCreate("DWORD dwResetPeriod;ptr lpRebootMsg;ptr lpCommand;DWORD cActions;ptr lpsaActions")
    DllStructSetData($serviceFailureActions, "dwResetPeriod", "INFINITE")

    Local $lpRebootMsg = DllStructCreate("wstr")
    DllStructSetData($lpRebootMsg, 1, "")

    DllStructSetData($serviceFailureActions, "lpRebootMsg", DllStructGetPtr($lpRebootMsg))
    DllStructSetData($serviceFailureActions, "lpCommand", Null)
    DllStructSetData($serviceFailureActions, "cActions", $iNumberOfArrayElement)
    DllStructSetData($serviceFailureActions, "lpsaActions", $PtrSC_ACTION_Array)

    Local $dwInfoLevel = $SERVICE_CONFIG_FAILURE_ACTIONS
    Local $lpInfo = DllStructGetPtr($serviceFailureActions)
    $rdll = DllCall($hAdvapi32_DLL, "BOOLEAN", "ChangeServiceConfig2", _
                                                    "HANDLE", $hService, _
                                                    "DWORD", $dwInfoLevel, _
                                                    "ptr", $lpInfo) ; pointeur vers la structure SERVICE_FAILURE_ACTIONS


    CloseServiceHandle($hService)
    CloseServiceHandle($hSC)

    If @error Then
        Return 0
    Else
        Return $rdll[0]
    EndIf

EndFunc

I suppose my problem coming from the "lpsaActions" variable. It should be a pointer to array of Service_Failure_Actions structures.

Any idea ?

Thanks and sorry for the double post.

 

P.S : I know I can use some SC command but I would prefer Windows internal function.

Edited by tatane

Share this post


Link to post
Share on other sites
tatane

Ok I found what was the problem... We have to Run the script with admin privilege. (#RequireAdmin)

Here is the function to set the service failure parameters :

Func _ChangeServiceConfig2($sServiceName, $sComputerName = "")
    Local $hSC, $hService, $rdll
    $hSC = OpenSCManager($sComputerName, $SC_MANAGER_ALL_ACCESS)
    $hService = OpenService($hSC, $sServiceName, $SERVICE_ALL_ACCESS)

    ;~ typedef struct _SERVICE_FAILURE_ACTIONS {
    ;~   DWORD     dwResetPeriod;
    ;~   LPTSTR    lpRebootMsg;
    ;~   LPTSTR    lpCommand;
    ;~   DWORD     cActions;
    ;~   SC_ACTION *lpsaActions;
    ;~  } SERVICE_FAILURE_ACTIONS, *LPSERVICE_FAILURE_ACTIONS;

    ;~  typedef struct _SC_ACTION {
    ;~   SC_ACTION_TYPE Type; see below
    ;~   DWORD          Delay; in ms
    ;~ } SC_ACTION, *LPSC_ACTION;

    Local $SC_ACTION_NONE = 0
    Local $SC_ACTION_REBOOT = 2
    Local $SC_ACTION_RESTART = 1
    Local $SC_ACTION_RUN_COMMAND = 3
    Local $SERVICE_CONFIG_FAILURE_ACTIONS = 2

    Local $sc_action = DllStructCreate("int Type; DWORD Delay")
    DllStructSetData($sc_action, "Type", $SC_ACTION_RESTART)
    DllStructSetData($sc_action, "Delay", 1000)

    Local Const $sTagSC_ACTION = "int;dword;int;dword;int;dword"
    Local $iNumberOfArrayElement = 3

    Local $tArraySC_ACTION = DllStructCreate($sTagSC_ACTION)
    DllStructSetData($tArraySC_ACTION, 1, $SC_ACTION_RESTART)
    DllStructSetData($tArraySC_ACTION, 2, 60000)
    DllStructSetData($tArraySC_ACTION, 3, $SC_ACTION_RESTART)
    DllStructSetData($tArraySC_ACTION, 4, 60000)
    DllStructSetData($tArraySC_ACTION, 5, $SC_ACTION_RESTART)
    DllStructSetData($tArraySC_ACTION, 6, 60000)
    Local $PtrSC_ACTION_Array = DllStructGetPtr($tArraySC_ACTION)

    Local $serviceFailureActions = DllStructCreate("DWORD dwResetPeriod;uint_ptr lpRebootMsg;uint_ptr lpCommand;DWORD cActions;uint_ptr lpsaActions")
    DllStructSetData($serviceFailureActions, "dwResetPeriod", 86400)

    Local $lpRebootMsg = DllStructCreate("wstr")
    DllStructSetData($lpRebootMsg, 1, "")

    DllStructSetData($serviceFailureActions, "lpRebootMsg", DllStructGetPtr($lpRebootMsg))
    DllStructSetData($serviceFailureActions, "lpCommand", Null)
    DllStructSetData($serviceFailureActions, "cActions", $iNumberOfArrayElement)
    DllStructSetData($serviceFailureActions, "lpsaActions", $PtrSC_ACTION_Array)

    Local $dwInfoLevel = $SERVICE_CONFIG_FAILURE_ACTIONS
    Local $lpInfo = DllStructGetPtr($serviceFailureActions)
    $rdll = DllCall($hAdvapi32_DLL, "int", "ChangeServiceConfig2", _
                                                    "HANDLE", $hService, _
                                                    "DWORD", $dwInfoLevel, _
                                                    "ptr", $lpInfo) ; pointeur vers la structure SERVICE_FAILURE_ACTIONS


    CloseServiceHandle($hService)
    CloseServiceHandle($hSC)

    If @error Then
        Return 0
    Else
        Return $rdll[0]
    EndIf

EndFunc

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×