{-# 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