winerror-1.0: System/Windows/Error.hs
{-# LANGUAGE CPP, DeriveDataTypeable, ForeignFunctionInterface #-}
{- |
Module : System.Windows.Error
Copyright : 2008 Felix Martini
License : BSD-style
Maintainer : fmartini@gmail.com
Stability : Provisional
Portability : Non-portable (extended exceptions)
Error handling for foreign calls to the Windows API.
-}
module System.Windows.Error
( WinError(..),
getWinError,
getWinErrorMessage,
throwWinErrorIf,
throwWinErrorIfFalse,
throwWinErrorIfInvalidHandle,
-- ** Common Windows error codes
-- | If the error code that you need is not listed below you can create your
-- own with the 'WinError' constructor and a numeric error code obtained from
-- the MSDN documentation at
-- <http://msdn2.microsoft.com/en-us/library/ms681381.aspx>.
errorSuccess, errorInvalidFunction, errorFileNotFound,
errorPathNotFound, errorTooManyOpenFiles, errorAccessDenied,
errorInvalidHandle, errorArenaTrashed, errorNotEnoughMemory,
errorInvalidBlock, errorBadEnvironment, errorBadFormat,
errorInvalidAccess, errorInvalidData, errorOutOfMemory,
errorInvalidDrive, errorCurrentDirectory, errorNotReady,
errorHandleEOF,
) where
import Prelude hiding (catch)
import Control.Exception (Exception, throwIO)
import Data.Typeable (Typeable)
import Data.Word (Word32)
import Foreign.Ptr (Ptr)
import Foreign.C.String (CWString, peekCWString)
-- | WinError is an exception that corresponds to a Windows error code.
newtype WinError = WinError Word32
deriving (Eq, Typeable)
instance Exception WinError
instance Show WinError where
showsPrec _ (WinError err) = showString "Windows error " . shows err
-- | Get the current thread's last error code. Each OS thread maintains it's
-- own last error code.
getWinError :: IO WinError
getWinError = do
err <- c_GetLastError
return (WinError err)
-- | Get the error message corresponding to the error code.
getWinErrorMessage :: WinError -- ^ Windows error code
-> IO String
getWinErrorMessage (WinError err) = do
msg <- c_GetErrorMessage err
str <- peekCWString msg
let str' = (unwords . words) str
c_LocalFree msg
return str'
-- | Throw a 'WinError' exception corresponding to the last error code if the
-- result value of the 'IO' action meets the given predicate.
throwWinErrorIf :: (a -> Bool) -- ^ Predicate to apply to the result value
-- of the 'IO' operation
-> IO a -- ^ The 'IO' action to be executed
-> IO a
throwWinErrorIf predicate act = do
res <- act
if predicate res
then do err <- c_GetLastError
throwIO (WinError err)
else return res
-- | Throw a 'WinError' exception corresponding to the last error code if the
-- result value of the 'IO' action is False.
throwWinErrorIfFalse :: IO Bool -- ^ The 'IO' action to be executed
-> IO ()
throwWinErrorIfFalse act = do
res <- act
if not res
then do err <- c_GetLastError
throwIO (WinError err)
else return ()
-- | Throw a 'WinError' exception corresponding to the last error code if
-- the result value of the 'IO' action is an invalid handle.
throwWinErrorIfInvalidHandle :: IO (Ptr a) -- ^ The 'IO' action to be
-- executed
-> IO (Ptr a)
throwWinErrorIfInvalidHandle act = do
res <- act
if res == invalidHandleValue
then do err <- c_GetLastError
throwIO (WinError err)
else return res
-- ---------------------------------------------------------------------
-- Error codes
errorSuccess :: WinError
errorInvalidFunction :: WinError
errorFileNotFound :: WinError
errorPathNotFound :: WinError
errorTooManyOpenFiles :: WinError
errorAccessDenied :: WinError
errorInvalidHandle :: WinError
errorArenaTrashed :: WinError
errorNotEnoughMemory :: WinError
errorInvalidBlock :: WinError
errorBadEnvironment :: WinError
errorBadFormat :: WinError
errorInvalidAccess :: WinError
errorInvalidData :: WinError
errorOutOfMemory :: WinError
errorInvalidDrive :: WinError
errorCurrentDirectory :: WinError
errorNotReady :: WinError
errorHandleEOF :: WinError
errorSuccess = WinError 0
errorInvalidFunction = WinError 1
errorFileNotFound = WinError 2
errorPathNotFound = WinError 3
errorTooManyOpenFiles = WinError 4
errorAccessDenied = WinError 5
errorInvalidHandle = WinError 6
errorArenaTrashed = WinError 7
errorNotEnoughMemory = WinError 8
errorInvalidBlock = WinError 9
errorBadEnvironment = WinError 10
errorBadFormat = WinError 11
errorInvalidAccess = WinError 12
errorInvalidData = WinError 13
errorOutOfMemory = WinError 14
errorInvalidDrive = WinError 15
errorCurrentDirectory = WinError 16
errorNotReady = WinError 21
errorHandleEOF = WinError 38
-- ---------------------------------------------------------------------
-- Foreign functions
foreign import stdcall unsafe "GetLastError"
c_GetLastError :: IO Word32
foreign import ccall unsafe "GetErrorMessageW"
c_GetErrorMessage :: Word32 -> IO CWString
foreign import stdcall unsafe "LocalFree"
c_LocalFree :: Ptr a -> IO (Ptr a)
foreign import ccall unsafe "invalidHandleValue"
invalidHandleValue :: Ptr a