'=================================================
'
' Stop a windows service - build as single file.
'
'=================================================

'NOTE
'Compile and run the exe as Admin. 

$Include "Windows.inc"

typedef SC_STATUS_TYPE int
const SC_STATUS_PROCESS_INFO = 0

typedef SC_ENUM_TYPE int
const SC_ENUM_PROCESS_INFO	= 0

type SERVICE_STATUS
	int	dwServiceType
	int	dwCurrentState
	INT	dwControlsAccepted
	INT	dwWin32ExitCode
	INT	dwServiceSpecificExitCode
	INT	dwCheckPoint
	INT	dwWaitHint
endtype

type SERVICE_STATUS_PROCESS
	INT	dwServiceType
	INT	dwCurrentState
	INT	dwControlsAccepted
	INT	dwWin32ExitCode
	INT	dwServiceSpecificExitCode
	INT	dwCheckPoint
	INT	dwWaitHint
	INT	dwProcessId
	INT	dwServiceFlags
endtype

def Xbuffer as pointer
Xbuffer = new SERVICE_STATUS_PROCESS

type ENUM_SERVICE_STATUS
	pointer	lpServiceName
	pointer	lpDisplayName
	SERVICE_STATUS	ServiceStatus
endtype

declare import, DeleteService(hService AS UINT),int
DECLARE IMPORT, OpenSCManager ALIAS OpenSCManagerA(lpMachineName AS POINTER,lpDatabaseName AS POINTER,dwDesiredAccess AS INT),INT
declare import, OpenService alias OpenServiceA(hSCManager AS UINT,lpServiceName AS POINTER,dwDesiredAccess AS int),int
DECLARE IMPORT, QueryServiceStatus(hService AS INT,lpServiceStatus AS SERVICE_STATUS),INT
declare import, QueryServiceStatusEx(hService as int,InfoLevel as SC_STATUS_TYPE,pointer lpBuffer,int cbBufSize,pointer pcbBytesNeeded),int
declare import, ControlService(hService as int,dwControl as int,lpServiceStatus as SERVICE_STATUS),int


' Service State -- for CurrentState
const SERVICE_STOPPED =	0x1
const SERVICE_START_PENDING =	0x2
const SERVICE_STOP_PENDING = 0x3
const SERVICE_RUNNING =	0x4
const SERVICE_CONTINUE_PENDING =	0x5
const SERVICE_PAUSE_PENDING =	0x6
const SERVICE_PAUSED = 0x7

CONST SERVICE_ERROR_NORMAL = 0x1
CONST SERVICE_DEMAND_START = 0x3
CONST SERVICE_WIN32_OWN_PROCESS = 0x10
const SC_MANAGER_CREATE_SERVICE = 0x2
const SC_MANAGER_ALL_ACCESS =	0xF003F
 
' Service flags for QueryServiceStatusEx
const SERVICE_RUNS_IN_SYSTEM_PROCESS = 0x1

DEF SERVICES_ACTIVE_DATABASE,MyService,ErMes,Display AS String
DEF Error,nSize,Arguments AS Uint
def Bneeded as int

nSize = 255
MyService ="IWBrules"     ' A name for the service.
Display ="IWBDisplayName" ' A display name for the service.
SERVICES_ACTIVE_DATABASE = "ServicesActive"


OPENCONSOLE 'So we can see if there are any errors.
print
print


'==========================================================
'Step 1 - open a connection to the service control manager.
'==========================================================

hSCManager = OpenSCManager(0,0,SC_MANAGER_ALL_ACCESS)
IF hSCManager = 0 THEN
   Error = _GetLastError ()
   _FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,Error,0,ErMes,nSize,Arguments)
   Print "  Error by OSCM: ",ErMes
   GOTO Exit
else
	print
	print "  Service manager opened..."
	print
ENDIF


'==========================
'Step 2 - open the service.
'==========================

hService = OpenService(hSCManager,MyService,SC_MANAGER_ALL_ACCESS)
IF hService = 0 THEN
   Error = _GetLastError ()
   _FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,Error,0,ErMes,nSize,Arguments)
   Print "  Error by Open Service: ",ErMes
   GOTO Exit
else
	print
	print "  Service was found..."
	print
ENDIF


'============================
'Step 3 - Query the service.
'============================

int qs

'Designed to fail to get bytes needed.
qs = QueryServiceStatusEx(hService,SC_STATUS_PROCESS_INFO,NULL,0,&Bneeded)

if not qs then 'Error detected.
	if _GetLastError() = ERROR_INSUFFICIENT_BUFFER then
		Xbuffer = new(char, Bneeded)

      'Now try again with correct bytes required.
		qs = QueryServiceStatusEx(hService,SC_STATUS_PROCESS_INFO,Xbuffer,Bneeded,&Bneeded)

      'If second fail, print error and exit. 
		IF qs = 0 THEN 'Error detected.
			Error = _GetLastError ()
			_FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,Error,0,ErMes,nSize,Arguments)
			Print "  Error by Query Service: ",ErMes
			GOTO Exit
		endif

	endif

	' Now get and display the results using type cast
   print "  Service Name ",MyService
   PRINT	"  Type         ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwServiceType
	PRINT	"  State        ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwCurrentState
	PRINT	"  Accepted     ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwControlsAccepted
	PRINT	"  ExitCode     ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwWin32ExitCode
	PRINT	"  SExitCode    ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwServiceSpecificExitCode
	PRINT	"  CheckPoint   ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwCheckPoint
	PRINT	"  WaitHint     ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwWaitHint
   print "  Proc ID      ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwProcessId
   print "  Bytes needed ",Bneeded
	print
	print
	print "  No errors... ",qs

else

	' Now get and display the results using type cast
   print "  Service Name ",MyService
   PRINT	"  Type         ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwServiceType
	PRINT	"  State        ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwCurrentState
	PRINT	"  Accepted     ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwControlsAccepted
	PRINT	"  ExitCode     ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwWin32ExitCode
	PRINT	"  SExitCode    ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwServiceSpecificExitCode
	PRINT	"  CheckPoint   ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwCheckPoint
	PRINT	"  WaitHint     ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwWaitHint
   print "  Proc ID      ",#<SERVICE_STATUS_PROCESS>Xbuffer.dwProcessId
   print "  Bytes needed ",Bneeded
	print
	print
	print "  No errors... ",qs

endif

if #<SERVICE_STATUS_PROCESS>Xbuffer.dwCurrentState = SERVICE_STOPPED
	print "  Service is Stopped."
endif 

if #<SERVICE_STATUS_PROCESS>Xbuffer.dwCurrentState = SERVICE_RUNNING
	print "  Service is Running."
	def lpServiceStatus AS SERVICE_STATUS

	'==========================
	'Step 4 - Stop the service.
	'==========================

	cs = ControlService(hService,SERVICE_CONTROL_STOP,lpServiceStatus)
	IF cs = 0 THEN
		Error = _GetLastError ()
		_FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,Error,0,ErMes,nSize,Arguments)
		Print "  Error by Control Service: ",ErMes
		GOTO Exit
	else 
		print
		print "  Service was stopped..."
		print
	ENDIF

endif 

'=========================================================
'Step 4 - Close the handle to the service control manager.
'=========================================================

LABEL Exit
'Close handles
_CloseServiceHandle(hService)
_CloseServiceHandle(hSCManager)

'Free the buffer from memory
delete Xbuffer

print
print
print "  Press any key to close..."
print
DO:UNTIL INKEY$<>""
