module System.Win32.Utils
( try, tryWithoutNull, try'
, maybePtr, ptrToMaybe, maybeNum, numToMaybe
, peekMaybe, withMaybe
) where
import Control.Monad ( unless )
import Foreign.Marshal.Array ( allocaArray, peekArray )
import Foreign.Marshal.Utils ( with )
import Foreign.Ptr ( Ptr, nullPtr )
import Foreign.Storable ( Storable(..) )
import System.Win32.Types ( failIfZero
, failWith, getLastError, eRROR_INSUFFICIENT_BUFFER )
import qualified System.Win32.Types ( try )
import System.Win32.String ( LPTSTR, peekTString )
import System.Win32.Types ( BOOL, UINT, maybePtr, ptrToMaybe, maybeNum, numToMaybe )
import System.Win32.Word ( DWORD, PDWORD )
try :: String -> (LPTSTR -> UINT -> IO UINT) -> UINT -> IO String
try = System.Win32.Types.try
{-# INLINE try #-}
tryWithoutNull :: String -> (LPTSTR -> UINT -> IO UINT) -> UINT -> IO String
tryWithoutNull loc f n = do
e <- allocaArray (fromIntegral n) $ \lptstr -> do
r <- failIfZero loc $ f lptstr n
if (r > n) then return (Left r) else do
str <- peekTString lptstr
return (Right str)
case e of
Left r' -> tryWithoutNull loc f r'
Right str -> return str
try' :: Storable a => String -> (Ptr a -> PDWORD -> IO BOOL) -> DWORD -> IO [a]
try' loc f n =
with n $ \n' -> do
e <- allocaArray (fromIntegral n) $ \lptstr -> do
flg <- f lptstr n'
unless flg $ do
err_code <- getLastError
unless (err_code == eRROR_INSUFFICIENT_BUFFER)
$ failWith loc err_code
r <- peek n'
if (r > n) then return (Left r) else do
str <- peekArray (fromIntegral r) lptstr
return (Right str)
case e of
Left r' -> try' loc f r'
Right str -> return str
peekMaybe :: Storable a => Ptr a -> IO (Maybe a)
peekMaybe p =
if p == nullPtr
then return Nothing
else Just `fmap` peek p
withMaybe :: Storable a => Maybe a -> (Ptr a -> IO b) -> IO b
withMaybe Nothing action = action nullPtr
withMaybe (Just x) action = with x action