    {-# LINE 1 "libraries\\Win32\\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 "libraries\\Win32\\System\\Win32\\Event.hsc" #-}

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

    {-# LINE 76 "libraries\\Win32\\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 "libraries\\Win32\\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