{-# LINE 1 "System\\Win32\\Event.hsc" #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  System.Win32.Event
-- Copyright   :  (c) Esa Ilari Vuokko, 2006
-- License     :  BSD-style (see the file LICENSE)
--
-- Maintainer  :  Esa Ilari Vuokko <ei@vuokko.info>
-- Stability   :  provisional
-- Portability :  portable
--
-- A collection of FFI declarations for interfacing with Win32 event system between
-- processes.
--
-----------------------------------------------------------------------------
module System.Win32.Event
    ( -- * Duplicate options
      DuplicateOption
    , dUPLICATE_CLOSE_SOURCE
    , dUPLICATE_SAME_ACCESS
      -- * Access modes
    , AccessMode
    , eVENT_ALL_ACCESS
    , eVENT_MODIFY_STATE
      -- * Wait results
    , WaitResult
    , wAIT_ABANDONED
    , wAIT_IO_COMPLETION
    , wAIT_OBJECT_0
    , wAIT_TIMEOUT
    , wAIT_FAILED
      -- * Managing events
    , openEvent
    , createEvent
    , duplicateHandle
    , setEvent
    , resetEvent
    , pulseEvent
      -- * Signalling objects
    , signalObjectAndWait
      -- * Waiting on objects
    , waitForSingleObject
    , waitForSingleObjectEx
    , waitForMultipleObjects
    , waitForMultipleObjectsEx
    ) where

import Foreign.Marshal.Alloc     ( alloca )
import Foreign.Marshal.Array     ( withArrayLen )
import Foreign.Marshal.Utils     ( maybeWith, with )
import Foreign.Ptr               ( Ptr, nullPtr )
import Foreign.Storable          ( Storable(..) )
import Graphics.Win32.Misc       ( MilliSeconds )
import System.Win32.File         ( AccessMode, LPSECURITY_ATTRIBUTES, SECURITY_ATTRIBUTES )
import System.Win32.Types        ( LPCTSTR, HANDLE, BOOL, withTString, failIf, failIfFalse_  )
import System.Win32.Word         ( DWORD )

#include "windows_cconv.h"





---------------------------------------------------------------------------
-- Enums
---------------------------------------------------------------------------
type DuplicateOption = DWORD
dUPLICATE_CLOSE_SOURCE  :: DuplicateOption
dUPLICATE_CLOSE_SOURCE  =  1
dUPLICATE_SAME_ACCESS   :: DuplicateOption
dUPLICATE_SAME_ACCESS   =  2

{-# LINE 71 "System\\Win32\\Event.hsc" #-}

eVENT_ALL_ACCESS    :: AccessMode
eVENT_ALL_ACCESS    =  2031619
eVENT_MODIFY_STATE  :: AccessMode
eVENT_MODIFY_STATE  =  2

{-# LINE 76 "System\\Win32\\Event.hsc" #-}

type WaitResult = DWORD
wAIT_ABANDONED      :: WaitResult
wAIT_ABANDONED      =  128
wAIT_IO_COMPLETION  :: WaitResult
wAIT_IO_COMPLETION  =  192
wAIT_OBJECT_0       :: WaitResult
wAIT_OBJECT_0       =  0
wAIT_TIMEOUT        :: WaitResult
wAIT_TIMEOUT        =  258
wAIT_FAILED         :: WaitResult
wAIT_FAILED         =  4294967295

{-# LINE 85 "System\\Win32\\Event.hsc" #-}

---------------------------------------------------------------------------
-- API in Haskell
---------------------------------------------------------------------------
openEvent :: AccessMode -> Bool -> String -> IO HANDLE
openEvent amode inherit name = withTString name $ \c_name ->
    failIf (==nullPtr) "openEvent: OpenEvent" $ c_OpenEvent (fromIntegral amode) inherit c_name

createEvent :: Maybe SECURITY_ATTRIBUTES -> Bool -> Bool -> String -> IO HANDLE
createEvent msecurity manual initial name = withTString name $ \c_name ->
    maybeWith with msecurity $ \c_sec ->
        failIf (==nullPtr) "createEvent: CreateEvent" $ c_CreateEvent c_sec manual initial c_name

duplicateHandle :: HANDLE -> HANDLE -> HANDLE -> AccessMode -> Bool -> DuplicateOption -> IO HANDLE
duplicateHandle srcProccess srcHandler targetProcess access inherit opts = alloca $ \res -> do
    failIfFalse_ "duplicateHandle: DuplicateHandle" $ c_DuplicateHandle srcProccess srcHandler targetProcess res (fromIntegral access) inherit opts
    peek res

setEvent :: HANDLE -> IO ()
setEvent event = failIfFalse_ "setEvent: SetEvent" $ c_SetEvent event

resetEvent :: HANDLE -> IO ()
resetEvent event = failIfFalse_ "resetEvent: ResetEvent" $ c_ResetEvent event

pulseEvent :: HANDLE -> IO ()
pulseEvent event = failIfFalse_ "pulseEvent: PulseEvent" $ c_PulseEvent event

signalObjectAndWait :: HANDLE -> HANDLE -> MilliSeconds -> Bool -> IO WaitResult
signalObjectAndWait toSignal toWaitOn millis alterable = c_SignalObjectAndWait toSignal toWaitOn millis alterable

waitForSingleObject :: HANDLE -> MilliSeconds -> IO WaitResult
waitForSingleObject toWaitOn millis = c_WaitForSingleObject toWaitOn millis

waitForSingleObjectEx :: HANDLE -> MilliSeconds -> Bool -> IO WaitResult
waitForSingleObjectEx toWaitOn millis alterable = c_WaitForSingleObjectEx toWaitOn millis alterable

waitForMultipleObjects :: [HANDLE] -> Bool -> MilliSeconds -> IO WaitResult
waitForMultipleObjects hs waitAll millis = withArrayLen hs $ \n hsp ->
  c_WaitForMultipleObjects (fromIntegral n) hsp waitAll millis

waitForMultipleObjectsEx :: [HANDLE] -> Bool -> MilliSeconds -> Bool -> IO WaitResult
waitForMultipleObjectsEx hs waitAll millis alterable = withArrayLen hs $ \n hsp ->
  c_WaitForMultipleObjectsEx (fromIntegral n) hsp waitAll millis alterable

---------------------------------------------------------------------------
-- Imports
---------------------------------------------------------------------------
foreign import WINDOWS_CCONV "windows.h OpenEventW"
    c_OpenEvent :: DWORD -> BOOL -> LPCTSTR -> IO HANDLE

foreign import WINDOWS_CCONV "windows.h CreateEventW"
    c_CreateEvent :: LPSECURITY_ATTRIBUTES -> BOOL -> BOOL -> LPCTSTR -> IO HANDLE

foreign import WINDOWS_CCONV "windows.h DuplicateHandle"
    c_DuplicateHandle :: HANDLE -> HANDLE -> HANDLE -> Ptr HANDLE -> DWORD -> BOOL -> DWORD -> IO BOOL

foreign import WINDOWS_CCONV "windows.h SetEvent"
    c_SetEvent :: HANDLE -> IO Bool

foreign import WINDOWS_CCONV "windows.h ResetEvent"
    c_ResetEvent :: HANDLE -> IO Bool

foreign import WINDOWS_CCONV "windows.h PulseEvent"
    c_PulseEvent :: HANDLE -> IO Bool

foreign import WINDOWS_CCONV "windows.h SignalObjectAndWait"
    c_SignalObjectAndWait :: HANDLE -> HANDLE -> DWORD -> BOOL -> IO DWORD

foreign import WINDOWS_CCONV "windows.h WaitForSingleObject"
    c_WaitForSingleObject :: HANDLE -> DWORD -> IO DWORD

foreign import WINDOWS_CCONV "windows.h WaitForSingleObjectEx"
    c_WaitForSingleObjectEx :: HANDLE -> DWORD -> BOOL -> IO DWORD

foreign import WINDOWS_CCONV "windows.h WaitForMultipleObjects"
    c_WaitForMultipleObjects :: DWORD -> Ptr HANDLE -> BOOL -> DWORD -> IO DWORD

foreign import WINDOWS_CCONV "windows.h WaitForMultipleObjectsEx"
    c_WaitForMultipleObjectsEx :: DWORD -> Ptr HANDLE -> BOOL -> DWORD -> BOOL -> IO DWORD