module System.Win32.FileMapping.Memory ( createMap, openMap, mapFile, withMapFile, readMapFile ) where import Control.Monad.Catch import Control.Monad.Cont import Control.Monad.Except import Data.ByteString.Char8 import qualified Data.ByteString.Char8 as BS import Foreign.Ptr import System.Win32.File (closeHandle) import System.Win32.FileMapping hiding (mapFile) import System.Win32.Types import System.Win32.Mem createMap :: Maybe HANDLE -> ProtectFlags -> DDWORD -> Maybe String -> ExceptT String (ContT r IO) HANDLE createMap mh pf sz mn = verify (/= iNVALID_HANDLE_VALUE) "Invalid handle" $ ContT $ bracket (createFileMapping mh pf sz mn) closeHandle openMap :: FileMapAccess -> Bool -> Maybe String -> ExceptT String (ContT r IO) HANDLE openMap f i mn = verify (/= iNVALID_HANDLE_VALUE) "Invalid handle" $ ContT $ bracket (openFileMapping f i mn) closeHandle mapFile :: HANDLE -> FileMapAccess -> DDWORD -> SIZE_T -> ExceptT String IO (Ptr a) mapFile h f off sz = verify (/= nullPtr) "null pointer" $ mapViewOfFile h f off sz -- | Write data to named map view of file withMapFile :: String -> ByteString -> IO a -> ExceptT String IO a withMapFile name str act = mapExceptT (`runContT` return) $ do p <- lift $ ContT $ BS.useAsCString str h <- createMap Nothing pAGE_READWRITE (fromIntegral len) (Just name) ptr <- mapExceptT lift $ mapFile h fILE_MAP_ALL_ACCESS 0 0 liftIO $ do copyMemory ptr p (fromIntegral len) unmapViewOfFile ptr act where len = BS.length str + 1 -- | Read data from named map view of file readMapFile :: String -> ExceptT String IO ByteString readMapFile name = mapExceptT (`runContT` return) $ do h <- openMap fILE_MAP_ALL_ACCESS True (Just name) ptr <- mapExceptT lift $ mapFile h fILE_MAP_ALL_ACCESS 0 0 liftIO $ BS.packCString ptr verify :: Monad m => (a -> Bool) -> String -> m a -> ExceptT String m a verify p str act = do x <- lift act if p x then return x else throwError str