Jump to content

Updated service control funtions


SumTingWong
 Share

Recommended Posts

Grrr.

No old script!

3.3.8.1 = 16-Nov-2012

win 8.1, advapi32.dll, OpenService

OpenService is normal function in Win 8.1 advapi32.dll, no old!

Compile 32bit autoit script with service function with autoit version 3.3.8.1 = no bug! Advapi32.dll + OpenService = no error 6

Compile 64bit autoit script with service function with autoit version 3.3.8.1 = no bug! Advapi32.dll + OpenService = no error 6

Compile 32bit autoit script with service function with autoit version 3.3.10.2 and 3.3.12.0 = no bug! Advapi32.dll + OpenService = no error 6

Compile 64bit autoit script with service function with autoit version 3.3.10.2 and 3.3.12.0 = bug! Advapi32.dll + OpenService = error 6!

 

Autoit (3.3.10.2 and 3.3.12.0) compile 64bit exe with bug!

Edited by Melba23
Resized font
Link to comment
Share on other sites

I hope you're up for learning about DllCall and the Win API. I can almost guarantee that this has to do with improvements and bugfixing in DllCall and DllStruct with respect to parameter sizing and alignment in 64-bit windows.

To fix this UDF you're going to have to go through the function calls and correct the parameters by referencing the functions on MSDN.

Quick example: OpenService

Current implementation (read this as <return: param1, param2, ...> etc)

<long: long, str, long>

Correct implementationhttp://msdn.microsoft.com/en-us/library/windows/desktop/ms684330(v=vs.85).aspx )

<handle: handle, str, dword>

Additionally, for functions that have ANSI and Unicode variants, you should explicitly call one or the other. OpenService really calls either OpenServiceA (ANSI) or OpenServiceW (Unicode). This will change whether your DllCall string parameters are ANSI strings (str) or Unicode strings (wstr).

Link to comment
Share on other sites

wraithdu:

Added "A" as ANSI.

Added handle and dword.

Same always:

32bit and 64bit 3.3.8.1 and 32bit 3.3.10.2 and  32bit 3.3.12.0 OK

64bit 3.3.10.2 and 64bit 3.3.12.0 error 6 OpenService.

64bit 3.3.8.1 OK + 64bit 3.3.10.2 and 64bit 3.3.12.0 error 6 OpenService -> 64bit 3.3.10.2 and 64bit 3.3.12.0 bug.

Func _StartService($sServiceName)
   Local $hAdvapi32
   Local $hKernel32
   Local $arRet
   Local $hSC
   Local $hService
   Local $lError = -1

   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $hKernel32 = DllOpen("kernel32.dll")
   If $hKernel32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "long", "OpenSCManagerA", _
                    "str", "", _
                    "str", "ServicesActive", _
                    "dword", 0x0001)
   If $arRet[0] = 0 Then
      $arRet = DllCall($hKernel32, "long", "GetLastError")
      $lError = $arRet[0]
              MsgBox (0,"error1", $lError)
   Else
      $hSC = $arRet[0]
      MsgBox (0,"$hSC", $hSC)
      $arRet = DllCall($hAdvapi32, "long", "OpenServiceA", _
                       "handle", $hSC, _
                       "str", $sServiceName, _
                       "dword", 0x0010)
      If $arRet[0] = 0 Then
         $arRet = DllCall($hKernel32, "long", "GetLastError")
         $lError = $arRet[0]
                  MsgBox (0,"error2", $lError)
      Else
         $hService = $arRet[0]
         $arRet = DllCall($hAdvapi32, "int", "StartServiceA", _
                          "long", $hService, _
                          "long", 0, _
                          "str", "")
         If $arRet[0] = 0 Then
            $arRet = DllCall($hKernel32, "long", "GetLastError")
            $lError = $arRet[0]
                      MsgBox (0,"error3", $lError)
         EndIf
         DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hService)
      EndIf
      DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hSC)
   EndIf
   DllClose($hAdvapi32)
   DllClose($hKernel32)
   If $lError <> -1 Then
          MsgBox (0,"error", $lError)
      SetError($lError)
      Return 0
   EndIf
   Return 1
EndFunc
Edited by Krakatoa
Link to comment
Share on other sites

What's the return value from the OpenSCManager call? Error 6 means that the handle is invalid and that means that the DLLCall probably failed, because you're not getting a valid handle to pass to StartService.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

OpenSCManager and OpenService... a 'long' is not a 'handle'. Your return value is wrong, which I already pointed out. I'm sure your CloseServiceHandle calls are also wrong. Read the help file for DllCall, and consult MSDN for the correct function prototypes.

Link to comment
Share on other sites

BrewManNH, wraithdu:

Thanks help.

Replace type and 64bit 3.3.12.0 no error 6.

Valid code (_StartService, _StopService, _ServiceRunning)(ControlService not struct but str (str no problem)).

;===============================================================================
; Description:   Starts a service
; Parameters:    $sServiceName - name of the service to start
; Requirements:  None
; Return Values: On Success - 1
;                On Failure - 0 and @error is set to extended Windows error code
; Note:          This function does not check to see if the service has started successfully
;===============================================================================
Func _StartService($sServiceName)
   Local $hAdvapi32
   Local $hKernel32
   Local $arRet
   Local $hSC
   Local $hService
   Local $lError = -1

   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $hKernel32 = DllOpen("kernel32.dll")
   If $hKernel32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "handle", "OpenSCManagerA", _
                    "str", "", _
                    "str", "ServicesActive", _
                    "dword", 0x0001)
   If $arRet[0] = 0 Then
      $arRet = DllCall($hKernel32, "dword", "GetLastError")
      $lError = $arRet[0]
   Else
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "handle", "OpenServiceA", _
                       "handle", $hSC, _
                       "str", $sServiceName, _
                       "dword", 0x0010)
      If $arRet[0] = 0 Then
         $arRet = DllCall($hKernel32, "dword", "GetLastError")
         $lError = $arRet[0]
      Else
         $hService = $arRet[0]
         $arRet = DllCall($hAdvapi32, "bool", "StartServiceA", _
                          "handle", $hService, _
                          "dword", 0x0000, _
                          "str", "")
         If $arRet[0] = 0 Then
            $arRet = DllCall($hKernel32, "dword", "GetLastError")
            $lError = $arRet[0]
         EndIf
         DllCall($hAdvapi32, "bool", "CloseServiceHandle", "handle", $hService)
      EndIf
      DllCall($hAdvapi32, "bool", "CloseServiceHandle", "handle", $hSC)
   EndIf
   DllClose($hAdvapi32)
   DllClose($hKernel32)
   If $lError <> -1 Then
      SetError($lError)
      Return 0
   EndIf
   Return 1
EndFunc

;===============================================================================
; Description:   Stops a service
; Parameters:    $sServiceName - name of the service to stop
; Requirements:  None
; Return Values: On Success - 1
;                On Failure - 0 and @error is set to extended Windows error code
; Note:          This function does not check to see if the service has stopped successfully
;===============================================================================
Func _StopService($sServiceName)
   Local $hAdvapi32
   Local $hKernel32
   Local $arRet
   Local $hSC
   Local $hService
   Local $lError = -1

   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $hKernel32 = DllOpen("kernel32.dll")
   If $hKernel32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "handle", "OpenSCManagerA", _
                    "str", "", _
                    "str", "ServicesActive", _
                    "dword", 0x0001)
   If $arRet[0] = 0 Then
      $arRet = DllCall($hKernel32, "dword", "GetLastError")
      $lError = $arRet[0]
   Else
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "handle", "OpenServiceA", _
                       "handle", $hSC, _
                       "str", $sServiceName, _
                       "dword", 0x0020)
      If $arRet[0] = 0 Then
         $arRet = DllCall($hKernel32, "dword", "GetLastError")
         $lError = $arRet[0]
      Else
         $hService = $arRet[0]
         $arRet = DllCall($hAdvapi32, "bool", "ControlService", _
                          "handle", $hService, _
                          "dword", 0x00000001, _
                          "str", "")
         If $arRet[0] = 0 Then
            $arRet = DllCall($hKernel32, "dword", "GetLastError")
            $lError = $arRet[0]
         EndIf
         DllCall($hAdvapi32, "bool", "CloseServiceHandle", "handle", $hService)
      EndIf
      DllCall($hAdvapi32, "bool", "CloseServiceHandle", "handle", $hSC)
   EndIf
   DllClose($hAdvapi32)
   DllClose($hKernel32)
   If $lError <> -1 Then
      SetError($lError)
      Return 0
   EndIf
   Return 1
EndFunc

;===============================================================================
; Description:   Checks if a service is running
; Parameters:    $sServiceName - name of the service to check
; Requirements:  None
; Return Values: On Success - 1
;                On Failure - 0
; Note:          This function relies on the fact that only a running service responds
;                to a SERVICE_CONTROL_INTERROGATE control code. Check the ControlService
;                page on MSDN for limitations with using this method.
;===============================================================================
Func _ServiceRunning($sServiceName)
   Local $hAdvapi32
   Local $arRet
   Local $hSC
   Local $hService
   Local $bRunning = 0

   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "handle", "OpenSCManagerA", _
                    "str", "", _
                    "str", "ServicesActive", _
                    "dword", 0x0001)
   If $arRet[0] <> 0 Then
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "handle", "OpenServiceA", _
                       "handle", $hSC, _
                       "str", $sServiceName, _
                       "dword", 0x0080)
      If $arRet[0] <> 0 Then
         $hService = $arRet[0]
         $arRet = DllCall($hAdvapi32, "bool", "ControlService", _
                          "handle", $hService, _
                          "dword", 0x00000004, _
                          "str", "")
         $bRunning = $arRet[0]
         DllCall($hAdvapi32, "bool", "CloseServiceHandle", "handle", $hService)
      EndIf
      DllCall($hAdvapi32, "bool", "CloseServiceHandle", "handle", $hSC)
   EndIf
   DllClose($hAdvapi32)
   Return $bRunning
EndFunc
Edited by Krakatoa
Link to comment
Share on other sites

Nicely done.

The ControlService function's last parameter is a pointer to a SERVICE_STATUS structure, which it fills in upon error. The correct way to do that would be to create the structure, then pass the pointer to it. The easiest way would be to create an array of 7 dwords, but the best way is to create the actual structure with element names, so you can easily access them later if needed.

$tagSERVICE_STATUS = "dword dwServiceType;dword dwCurrentState;dword dwControlsAccepted;dword dwWin32ExitCode; _
    dword dwServiceSpecificExitCode;dword dwCheckPoint;dword dwWaitHint"
$SERVICE_STATUS = DllStructCreate($tagSERVICE_STATUS)
;; easy way
;$SERVICE_STATUS = DllStructCreate("dword[7]")
$ret = DllCall("AdvApi32.dll", "bool", "ControlService", "handle", $hService, "dword", 1, "struct*", $SERVICE_STATUS)
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...