module Main where
import Control.Concurrent.MVar
import System.Win32.SystemServices.Services
import System.Win32.Types
main :: IO ()
main = do
gState <- newMVar (1, SERVICE_STATUS WIN32_OWN_PROCESS
START_PENDING [] nO_ERROR 0 0 3000)
mStop <- newEmptyMVar
startServiceCtrlDispatcher "Test" 3000 (svcCtrlHandler mStop gState) $ svcMain mStop gState
svcMain mStop gState _ _ h = do
reportSvcStatus h RUNNING nO_ERROR 0 gState
takeMVar mStop
reportSvcStatus h STOPPED nO_ERROR 0 gState
reportSvcStatus :: HANDLE -> SERVICE_STATE -> DWORD -> DWORD
-> MVar (DWORD, SERVICE_STATUS) -> IO ()
reportSvcStatus hStatus state win32ExitCode waitHint mState = do
modifyMVar_ mState $ \(checkPoint, svcStatus) -> do
let state' = nextState (checkPoint, svcStatus
{ win32ExitCode = win32ExitCode
, waitHint = waitHint
, currentState = state })
setServiceStatus hStatus (snd state')
return state'
nextState :: (DWORD, SERVICE_STATUS) -> (DWORD, SERVICE_STATUS)
nextState (checkPoint, svcStatus) = case (currentState svcStatus) of
START_PENDING -> (checkPoint + 1, svcStatus
{ controlsAccepted = [], checkPoint = checkPoint + 1 })
RUNNING -> (checkPoint, svcStatus
{ controlsAccepted = [ACCEPT_STOP], checkPoint = 0 })
STOPPED -> (checkPoint, svcStatus
{ controlsAccepted = [], checkPoint = 0 })
_ -> (checkPoint + 1, svcStatus
{ controlsAccepted = [], checkPoint = checkPoint + 1 })
svcCtrlHandler :: MVar () -> MVar (DWORD, SERVICE_STATUS)
-> HandlerFunction
svcCtrlHandler mStop mState hStatus STOP = do
reportSvcStatus hStatus STOP_PENDING nO_ERROR 3000 mState
putMVar mStop ()
return True
svcCtrlHandler _ _ _ INTERROGATE = return True
svcCtrlHandler _ _ _ _ = return False