Win32-extras 0.1.0.0 → 0.2.0.0
raw patch · 24 files changed
+913/−216 lines, 24 filesdep ~Win32dep ~base
Dependency ranges changed: Win32, base
Files
- Graphics/Win32/GDI/AlphaBlend.hsc +18/−6
- Graphics/Win32/LayeredWindow.hsc +2/−2
- Graphics/Win32/Window/HotKey.hsc +19/−13
- Media/Win32.hs +1/−1
- System/Win32/Console/CtrlHandler.hs +50/−0
- System/Win32/Console/HWND.hs +34/−0
- System/Win32/Console/Title.hsc +42/−0
- System/Win32/DLL/LoadFunction.hs +82/−16
- System/Win32/Encoding.hs +6/−4
- System/Win32/Error.hs +0/−31
- System/Win32/Error.hsc +49/−0
- System/Win32/Error/MultiByte.hsc +2/−2
- System/Win32/Exception/Unsupported.hs +26/−12
- System/Win32/HardLink.hs +95/−0
- System/Win32/Info/Computer.hsc +114/−103
- System/Win32/Info/Version.hsc +164/−0
- System/Win32/Process/Current.hs +20/−0
- System/Win32/String.hs +3/−4
- System/Win32/SymbolicLink.hs +31/−19
- System/Win32/Utils.hs +77/−0
- System/Win32/Word.hs +23/−0
- Win32-extras.cabal +16/−3
- cbits/alphablend.c +15/−0
- changelog +24/−0
Graphics/Win32/GDI/AlphaBlend.hsc view
@@ -18,8 +18,20 @@ #include <windows.h> +foreign import ccall unsafe "alphablend.h" + c_AlphaBlend :: HDC -> Int -> Int -> Int -> Int -> HDC -> Int -> Int -> Int -> Int -> PBLENDFUNCTION -> IO BOOL {- -foreign import WINDOWS_CCONV unsafe "windows.h AlphaBlend" +We use C wrapper function to call this API. +Because foreign stacall/ccall/capi doesn't work with non-pointer user defined type. + +We think that capi should support that when user defined type has Storable class instance +and using CTYPE pragma in the scope. + +{-# LANGUAGE CApiFFI #-} + +data {-# CTYPE "windows.h" "BLENDFUNCTION" #-} BLENDFUNCTION = + +foreign import capi unsafe "windows.h AlphaBlend" c_AlphaBlend :: HDC -> Int -> Int -> Int -> Int -> HDC -> Int -> Int -> Int -> Int -> BLENDFUNCTION -> IO BOOL -} @@ -52,9 +64,9 @@ (#poke BLENDFUNCTION, AlphaFormat) buf (alphaFormat func) peek buf = do - blendOp <- (#peek BLENDFUNCTION, BlendOp) buf - blendFlags <- (#peek BLENDFUNCTION, BlendFlags) buf - sourceConstantAlpha <- + blendOp' <- (#peek BLENDFUNCTION, BlendOp) buf + blendFlags' <- (#peek BLENDFUNCTION, BlendFlags) buf + sourceConstantAlpha' <- (#peek BLENDFUNCTION, SourceConstantAlpha) buf - alphaFormat <- (#peek BLENDFUNCTION, AlphaFormat) buf - return $ BLENDFUNCTION blendOp blendFlags sourceConstantAlpha alphaFormat + alphaFormat' <- (#peek BLENDFUNCTION, AlphaFormat) buf + return $ BLENDFUNCTION blendOp' blendFlags' sourceConstantAlpha' alphaFormat'
Graphics/Win32/LayeredWindow.hsc view
@@ -21,8 +21,8 @@ #define _WIN32_WINNT 0x0500 #include <windows.h> -toLayerdWindow :: HWND -> IO () -toLayerdWindow w = do +toLayeredWindow :: HWND -> IO () +toLayeredWindow w = do flg <- c_GetWindowLongPtr w gWL_EXSTYLE void $ c_SetWindowLongPtr w gWL_EXSTYLE (flg .|. (fromIntegral wS_EX_LAYERED))
Graphics/Win32/Window/HotKey.hsc view
@@ -11,12 +11,14 @@ An FFI binding to the hot key part of the Win32 API. -} module Graphics.Win32.Window.HotKey where -import Data.Bits ( (.|.) ) -import Graphics.Win32.GDI.Types ( HWND, MbHWND ) -import Graphics.Win32.Key ( VKey ) -import Graphics.Win32.Message ( WindowMessage ) -import System.Win32.Types ( UINT, BOOL, maybePtr ) -import System.Win32.Error ( failIfFalse_ ) +import Data.Bits ( (.|.) ) +import Graphics.Win32.GDI.Types ( HWND, MbHWND ) +import Graphics.Win32.Key ( VKey ) +import Graphics.Win32.Message ( WindowMessage ) +import System.Win32.Types ( UINT, BOOL, maybePtr ) +import System.Win32.Error ( failIfFalse_ ) +import System.Win32.Exception.Unsupported ( unsupportedVal, upgradeWindowsOS ) +import System.Win32.Info.Version ( is7OrLater ) #include <windows.h> @@ -30,8 +32,12 @@ , mOD_WIN = MOD_WIN } +-- | This parameter requires to use Windows 7 or later. +mOD_NOREPEAT :: FsModifier +mOD_NOREPEAT + = unsupportedVal "MOD_NOREPEAT" + is7OrLater (upgradeWindowsOS "Windows 7") 0x4000 {- - -- This parameter requires to use Windows 7 or later. , mOD_NOREPEAT = MOD_NOREPEAT -} @@ -42,17 +48,17 @@ joinModifiers = foldr (.|.) 0 registerHotKey :: MbHWND -> Int -> FsModifier -> VKey -> IO () -registerHotKey mb_wnd id md vkey = - failIfFalse_ (unwords ["RegisterHotKey", show mb_wnd, show id, show md, show vkey]) - $ c_RegisterHotKey (maybePtr mb_wnd) id md vkey +registerHotKey mb_wnd kid md vkey = + failIfFalse_ (unwords ["RegisterHotKey", show mb_wnd, show kid, show md, show vkey]) + $ c_RegisterHotKey (maybePtr mb_wnd) kid md vkey foreign import WINDOWS_CCONV "windows.h RegisterHotKey" c_RegisterHotKey :: HWND -> Int -> UINT -> VKey -> IO BOOL unregisterHotKey :: MbHWND -> Int -> IO () -unregisterHotKey mb_wnd id = - failIfFalse_ (unwords ["UnregisterHotKey", show mb_wnd, show id]) - $ c_UnregisterHotKey (maybePtr mb_wnd) id +unregisterHotKey mb_wnd kid = + failIfFalse_ (unwords ["UnregisterHotKey", show mb_wnd, show kid]) + $ c_UnregisterHotKey (maybePtr mb_wnd) kid foreign import WINDOWS_CCONV "windows.h UnregisterHotKey" c_UnregisterHotKey :: HWND -> Int -> IO BOOL
Media/Win32.hs view
@@ -37,7 +37,7 @@ mciGetErrorString :: MCIERROR -> IO () mciGetErrorString err = withTStringBufferLen 256 $ \(cstr, len) -> do - failIfFalse_ "mciGetErrorString" $ + failIfFalse_ (unwords ["mciGetErrorString", show err]) $ c_mciGetErrorString err cstr $ fromIntegral len msg <- peekTString cstr cp <- getCurrentCodePage
+ System/Win32/Console/CtrlHandler.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE CPP #-} +{- | + Module : System.Win32.Console.CtrlHandler + Copyright : 2008-2013 Judah Jacobson, 2013 shelarcy + License : BSD-style + + Maintainer : shelarcy@gmail.com + Stability : Provisional + Portability : Non-portable (Win32 API) + + Set handlers of console Ctrl events. +-} +module System.Win32.Console.CtrlHandler + ( CtrlEvent, Handler, PHANDLER_ROUTINE + , withConsoleCtrlHandler + , setConsoleCtrlHandler, c_SetConsoleCtrlHandler + , mkHandler + , cTRL_C_EVENT, cTRL_BREAK_EVENT + ) where +import Control.Exception ( bracket ) +import Control.Monad ( void ) +import Foreign.Ptr ( FunPtr ) +import System.Win32.Console ( CtrlEvent, cTRL_C_EVENT, cTRL_BREAK_EVENT ) +import System.Win32.Error ( failIfFalse_ ) +import System.Win32.Types ( BOOL ) + +type Handler = CtrlEvent -> IO BOOL +-- type HandlerRoutine = Handler +type PHANDLER_ROUTINE = FunPtr Handler + +withConsoleCtrlHandler :: Handler -> IO a -> IO a +withConsoleCtrlHandler handler io + = bracket (do hd <- mkHandler handler + -- don't fail if we can't set the Ctrl-C handler + -- for example, we might not be attached to a console? + void $ c_SetConsoleCtrlHandler hd True + return hd) + (\hd -> void $ c_SetConsoleCtrlHandler hd False) + $ const io + +-- | This function isn't suitable when we want to set the cTRL_C_EVENT handler. +-- If you want to set the cTRL_C_EVENT handler, use 'c_SetConsoleCtrlHandler' instead. +setConsoleCtrlHandler :: PHANDLER_ROUTINE -> BOOL -> IO () +setConsoleCtrlHandler handler flag + = failIfFalse_ "SetConsoleCtrlHandler" + $ c_SetConsoleCtrlHandler handler flag + +foreign import WINDOWS_CCONV "wrapper" mkHandler :: Handler -> IO PHANDLER_ROUTINE +foreign import WINDOWS_CCONV "windows.h SetConsoleCtrlHandler" + c_SetConsoleCtrlHandler :: PHANDLER_ROUTINE -> BOOL -> IO BOOL
+ System/Win32/Console/HWND.hs view
@@ -0,0 +1,34 @@+{- | + Module : System.Win32.Console.HWND + Copyright : 2009 Balazs Komuves, 2013 shelarcy + License : BSD-style + + Maintainer : shelarcy@gmail.com + Stability : Provisional + Portability : Non-portable (Win32 API) + + Get the handle of the current console window. +-} +module System.Win32.Console.HWND where +import Control.Concurrent ( threadDelay ) +import Control.Exception ( bracket ) +import Foreign.Ptr ( nullPtr ) +import Graphics.Win32.Window ( c_FindWindow ) +import Graphics.Win32.GDI.Types ( HWND ) +import System.Win32.Console.Title ( getConsoleTitle, setConsoleTitle ) +import System.Win32.Process.Current ( getCurrentProcessId ) +import System.Win32.String ( withTString ) +import System.Win32.Time ( getTickCount ) + +-- | Get the handle of the current console window by using window's title. +-- See: <http://support.microsoft.com/kb/124103> +getConsoleHWND :: IO HWND +getConsoleHWND + = bracket getConsoleTitle setConsoleTitle $ \_ -> do + time <- getTickCount + pid <- getCurrentProcessId + let unique = show time ++ show pid + setConsoleTitle unique + threadDelay (42*1000) + withTString unique $ \punique -> + c_FindWindow nullPtr punique
+ System/Win32/Console/Title.hsc view
@@ -0,0 +1,42 @@+{-# LANGUAGE CPP #-} +{- | + Module : System.Win32.Console.Title + Copyright : 2013 shelarcy + License : BSD-style + + Maintainer : shelarcy@gmail.com + Stability : Provisional + Portability : Non-portable (Win32 API) + + Get/Set the title for the current console window. +-} +module System.Win32.Console.Title where +import System.Win32.Error ( failIfFalse_, failIfZero ) +import System.Win32.String ( LPTSTR, LPCTSTR + , withTStringBufferLen, withTString, peekTStringLen ) +import System.Win32.Types ( BOOL ) +import System.Win32.Word ( DWORD ) + +#include <windows.h> + +getConsoleTitle :: IO String +getConsoleTitle = + withTStringBufferLen maxLength $ \(buf, len) -> do + len' <- failIfZero "GetConsoleTitle" + $ c_GetConsoleTitle buf (fromIntegral len) + peekTStringLen (buf, (fromIntegral len')) + where + maxLength = #const MAX_PATH + +setConsoleTitle :: String -> IO () +setConsoleTitle title = + withTString title $ \buf -> + failIfFalse_ (unwords ["SetConsoleTitle", title]) + $ c_SetConsoleTitle buf + +foreign import WINDOWS_CCONV "windows.h GetConsoleTitleW" + c_GetConsoleTitle :: LPTSTR -> DWORD -> IO DWORD + +foreign import WINDOWS_CCONV "windows.h SetConsoleTitleW" + c_SetConsoleTitle :: LPCTSTR -> IO BOOL +
System/Win32/DLL/LoadFunction.hs view
@@ -23,32 +23,55 @@ ---------------------------------------------------------------- -- LoadFunctions ---------------------------------------------------------------- -loadFunction :: HMODULE -> String -> (FunPtr a -> IO b) -> IO b -loadFunction dll name conv +-- | This function is not stable yet. +-- If you worry about compatibility, use 'loadFunction'' instead. +loadFunction :: HMODULE + -> String -- ^ Function name + -> String -- ^ Advice to use function when user can't load function. + -> (FunPtr a -> IO b) -- ^ Process with using loaded function. + -> IO b +loadFunction dll name reason conv = withCAString name $ \c_name -> do - proc <- unsupportedIfNull (missingFunction name) + proc <- unsupportedIfNull (MissingFunction name reason) $ c_GetProcAddress dll c_name conv $ castPtrToFunPtr proc -loadSystemFunction :: HMODULE -> String -> (FunPtr a -> IO b) -> IO b -loadSystemFunction dll name conv +loadFunction' :: HMODULE + -> String -- ^ Function name + -> (FunPtr a -> IO b) -- ^ Process with using loaded function. + -> IO b +loadFunction' dll name conv = loadFunction dll name "" conv + +-- | This function is not stable yet. +-- If you worry about compatibility, use 'loadSystemFunction'' instead. +loadSystemFunction :: HMODULE -> String -> String -> (FunPtr a -> IO b) -> IO b +loadSystemFunction dll name reason conv = withCAString name $ \c_name -> do -- Is failIfNull suitable or not? - proc <- unsupportedIfNull (missingWin32Function name) + proc <- unsupportedIfNull (missingWin32Function name reason) $ c_GetProcAddress dll c_name conv $ castPtrToFunPtr proc +loadSystemFunction' :: HMODULE -> String -> (FunPtr a -> IO b) -> IO b +loadSystemFunction' dll name conv = loadSystemFunction dll name "" conv + loadLibrary' :: FilePath -> IO HINSTANCE loadLibrary' name = withTString name $ \ c_name -> unsupportedIfNull (missingLibrary name) $ c_LoadLibrary c_name -withLoadFunction :: FilePath -> String -> (FunPtr a -> IO b) -> IO b -withLoadFunction dllname name conv = +-- | This function is not stable yet. +-- If you worry about compatibility, use 'withLoadFunction'' instead. +withLoadFunction :: FilePath -- ^ DLL path + -> String -- ^ Function name + -> String -- ^ Advice to use function when user can't load function. + -> (FunPtr a -> IO b) -- ^ Process with using loaded function. + -> IO b +withLoadFunction dllname name reason conv = mask $ \restore -> do -- loadLibrry is better than c_getModuleHandle when load non-system library. dll <- loadLibrary' dllname - restore $ finally (loadFunction dll name conv) (freeLibrary dll) + restore $ finally (loadFunction dll name reason conv) (freeLibrary dll) {- result <- restore $ catch (loadFunction dllname dll name conv) @@ -59,17 +82,60 @@ _ <- freeLibrary a return result -} +withLoadFunction' :: FilePath -- ^ DLL path + -> String -- ^ Function name + -> (FunPtr a -> IO b) -- ^ Process with using loaded function. + -> IO b +withLoadFunction' dllname name conv = withLoadFunction dllname name "" conv -withLoadSystemFunction :: String -> String -> (FunPtr a -> IO b) -> IO b -withLoadSystemFunction dllname name conv +-- | This function is not stable yet. +-- If you worry about compatibility, use 'withLoadSystemFunction'' instead. +withLoadSystemFunction :: String -- ^ System's DLL name + -> String -- ^ Function name + -> String -- ^ Advice to use function when user can't load function. + -> (FunPtr a -> IO b) -- ^ Process with using loaded function. + -> IO b +withLoadSystemFunction dllname name reason conv = bracket (getModuleHandle (Just dllname)) (\_ -> return ()) - $ \dll -> loadSystemFunction dll name conv + $ \dll -> loadSystemFunction dll name reason conv +withLoadSystemFunction' :: String -- ^ System's DLL name + -> String -- ^ Function name + -> (FunPtr a -> IO b) -- ^ Process with using loaded function. + -> IO b +withLoadSystemFunction' dllname name conv = withLoadSystemFunction dllname name "" conv + +{- +-- Should we provide Maybe version's function to provide fallback functionality? + +getModuleHandle :: String -> IO (Maybe HMODULE) +getModuleHandle moduleName = do + ptr <- withTString moduleName c_GetModuleHandle + if ptr == nullPtr + then do + err <- getLastError + if err == eRROR_MOD_NOT_FOUND + then return Nothing + else failWith "GetModuleHandle" err + else return $ Just ptr + +getProcAddress :: HMODULE -> String -> IO (Maybe (FunPtr a)) +getProcAddress hModule procName = do + ptr <- withCAString procName $ c_GetProcAddress hModule + if ptr == nullPtr + then do + err <- getLastError + if err == eRROR_PROC_NOT_FOUND + then return Nothing + else failWith "GetProcAddress" err + else return $ Just $ castPtrToFunPtr ptr +-} + -- portable version setSearchPathMode :: SearchPathModeFlags -> IO () setSearchPathMode flag = - withLoadSystemFunction "Kernel32.dll" "SetSearchPathMode" $ \c_SetSearchPathMode -> - failIfFalse_ "SetDllDirectory" $ convSetSearchPathMode c_SetSearchPathMode flag + withLoadSystemFunction "Kernel32.dll" "SetSearchPathMode" "" $ \c_SetSearchPathMode -> + failIfFalse_ "SetDllDirectory" $ mkSetSearchPathMode c_SetSearchPathMode flag type SearchPathModeFlags = DWORD bASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE, bASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE, bASE_SEARCH_PATH_PERMANENT :: SearchPathModeFlags @@ -77,7 +143,7 @@ bASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE = 0x00010000 bASE_SEARCH_PATH_PERMANENT = 0x00008000 -foreign import WINDOWS_CCONV unsafe "dynamic" convSetSearchPathMode :: +foreign import WINDOWS_CCONV unsafe "dynamic" mkSetSearchPathMode :: FunPtr (SearchPathModeFlags -> IO BOOL) -> (SearchPathModeFlags -> IO BOOL) {- -- non portable version. @@ -98,7 +164,7 @@ setDllDirectory :: String -> IO () setDllDirectory name = withTString name $ \ c_name -> - failIfFalse_ "SetDllDirectory" $ c_SetDllDirectory c_name + failIfFalse_ (unwords ["SetDllDirectory", name]) $ c_SetDllDirectory c_name foreign import WINDOWS_CCONV unsafe "windows.h SetDllDirectoryW" c_SetDllDirectory :: LPTSTR -> IO BOOL
System/Win32/Encoding.hs view
@@ -17,6 +17,8 @@ , encodeMultiByteIO , decodeMultiByte , decodeMultiByteIO + , wideCharToMultiByte + , multiByteToWideChar ) where import Foreign.C.Types (CInt(..)) @@ -50,21 +52,21 @@ -- WideCharToMultiByte doesn't handle empty strings encodeMultiByteIO cp wstr = withCWStringLen wstr $ \(cwstr,len) -> do - mbchars <- failIfZero "WideCharToMultiByte" $ wideCharToMultiByte + mbchars' <- failIfZero "WideCharToMultiByte" $ wideCharToMultiByte cp 0 cwstr (fromIntegral len) nullPtr 0 nullPtr nullPtr - -- mbchars is the length of buffer required - allocaArray (fromIntegral mbchars) $ \mbstr -> do + -- mbchar' is the length of buffer required + allocaArray (fromIntegral mbchars') $ \mbstr -> do mbchars <- failIfZero "WideCharToMultiByte" $ wideCharToMultiByte cp 0 cwstr (fromIntegral len) - mbstr mbchars + mbstr mbchars' nullPtr nullPtr peekCAStringLen (mbstr,fromIntegral mbchars) -- converts [Char] to UTF-16
− System/Win32/Error.hs
@@ -1,31 +0,0 @@-{-# LANGUAGE CPP #-} -{- | - Module : System.Win32.Error - Copyright : 2013 shelarcy - License : BSD-style - - Maintainer : shelarcy@gmail.com - Stability : Provisional - Portability : Non-portable (Win32 API) - - Error handling for foreign calls to the Win32 API. - - This module - - * reorganize Win32 package's error handling functions. - - * supports to show non-UTF MutiByte error message without using GHC 7.8.1. --} -module System.Win32.Error - ( failIf, failIf_, failIfNull - , failIfZero, failIfFalse_ - , failUnlessSuccess, failUnlessSuccessOr - , errorWin, failWith - , failIfWithRetry, failIfWithRetry_, failIfFalseWithRetry_ - ) where -#if __GLASGOW_HASKELL__ >= 707 -import System.Win32.File ( failIfWithRetry, failIfWithRetry_, failIfFalseWithRetry_ ) -import System.Win32.Types -#else -import System.Win32.Error.MultiByte -#endif
+ System/Win32/Error.hsc view
@@ -0,0 +1,49 @@+{-# LANGUAGE CPP #-} +{- | + Module : System.Win32.Error + Copyright : 2013 shelarcy + License : BSD-style + + Maintainer : shelarcy@gmail.com + Stability : Provisional + Portability : Non-portable (Win32 API) + + Error handling for foreign calls to the Win32 API. + + This module + + * reorganize Win32 package's error handling functions. + + * supports to show non-UTF MutiByte error message without using GHC 7.8.1. +-} +module System.Win32.Error + ( failIf, failIf_, failIfNull + , failIfZero, failIfZero_, failIfFalse_ + , failUnlessSuccess, failUnlessSuccessOr + , failIfWithRetry, failIfWithRetry_, failIfFalseWithRetry_ + , errorWin, getLastError, failWith + , eRROR_INSUFFICIENT_BUFFER + , eRROR_MOD_NOT_FOUND + , eRROR_PROC_NOT_FOUND + ) where +#if __GLASGOW_HASKELL__ >= 707 +import System.Win32.File ( failIfWithRetry, failIfWithRetry_, failIfFalseWithRetry_ ) +import System.Win32.Types +#else +import System.Win32.Error.MultiByte +import System.Win32.Types ( getLastError, ErrCode ) +#endif + +#include <windows.h> + +failIfZero_ :: (Eq a, Num a) => String -> IO a -> IO () +failIfZero_ = failIf_ (== 0) + +eRROR_INSUFFICIENT_BUFFER :: ErrCode +eRROR_INSUFFICIENT_BUFFER = #const ERROR_INSUFFICIENT_BUFFER + +eRROR_MOD_NOT_FOUND :: ErrCode +eRROR_MOD_NOT_FOUND = #const ERROR_MOD_NOT_FOUND + +eRROR_PROC_NOT_FOUND :: ErrCode +eRROR_PROC_NOT_FOUND = #const ERROR_PROC_NOT_FOUND
System/Win32/Error/MultiByte.hsc view
@@ -72,8 +72,8 @@ failWithInternal getErrorMessage (encodeMultiByteIO cp) fn_name err_code failWithInternal :: (ErrCode -> IO LPWSTR) -> (String -> IO String) -> String -> ErrCode -> IO a -failWithInternal msg conv fn_name err_code = do - c_msg <- msg err_code +failWithInternal msg_fun conv fn_name err_code = do + c_msg <- msg_fun err_code msg <- if c_msg == nullPtr then return $ "Error 0x" ++ Numeric.showHex err_code "" else do msg <- peekTString c_msg
System/Win32/Exception/Unsupported.hs view
@@ -15,9 +15,10 @@ ( module System.Win32.Exception.Unsupported ) where -import Control.Exception ( Exception(..), throwIO ) -import Data.Typeable ( Typeable ) -import Foreign.Ptr ( Ptr, nullPtr ) +import Control.Exception ( Exception(..), throwIO ) +import Data.Typeable ( Typeable ) +import Foreign.Ptr ( Ptr, nullPtr ) +import Foreign.Marshal.Unsafe ( unsafeLocalState ) ---------------------------------------------------------------- -- Exception type of Unsupported @@ -32,25 +33,38 @@ = "Can't load library \"" ++ name ++ "\". " ++ reason show (MissingFunction name reason) = "Can't find \"" ++ name ++ "\" function. " ++ reason - show (MissingValue name reason) - = "Can't find \"" ++ name ++ "\" value. " ++ reason + show (MissingValue name reason) + = "Can't use \"" ++ name ++ "\" value. " ++ reason instance Exception Unsupported -missingLibrary, missingValue, missingWin32Value :: String -> Unsupported -missingFunction, missingWin32Function :: FilePath -> Unsupported +missingLibrary :: FilePath -> Unsupported +missingFunction, missingValue :: String -> Unsupported missingLibrary name = MissingLibrary name "" missingFunction name = MissingFunction name "" missingValue name = MissingValue name "" -missingWin32Function name = MissingFunction name $ doesn'tSupport ++ '\n':upgradeVista -missingWin32Value name = MissingValue name $ doesn'tSupport ++ '\n':upgradeVista +missingWin32Function, missingWin32Value :: String -> String -> Unsupported +missingWin32Function name reason = MissingFunction name $ doesn'tSupport ++ '\n':reason +missingWin32Value name reason = MissingValue name $ doesn'tSupport ++ '\n':reason + doesn'tSupport, upgradeVista, removed :: String doesn'tSupport = "Because it's not supported on this OS." -upgradeVista = "If you want to use this function, please upgrade your OS to Windows Vista or higher." -removed = "This function is removed. " +upgradeVista = upgradeWindowsOS "Windows Vista" +removed = "It's removed. " +upgradeWindowsOS :: String -> String +upgradeWindowsOS ver + = "If you want to use it, please upgrade your OS to " + ++ ver ++ " or higher." + unsupportedIfNull :: Unsupported -> IO (Ptr a) -> IO (Ptr a) unsupportedIfNull wh act = do v <- act - if v == nullPtr then throwIO wh else return v + if v /= nullPtr then return v else throwIO wh + +unsupportedVal :: String -> IO Bool -> String -> a -> a +unsupportedVal name checkVer reason val = unsafeLocalState $ do + cv <- checkVer + if cv then return val else throwIO $ MissingValue name reason +
+ System/Win32/HardLink.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE CPP #-} +{- | + Module : System.Win32.HardLink + Copyright : 2013 shelarcy + License : BSD-style + + Maintainer : shelarcy@gmail.com + Stability : Provisional + Portability : Non-portable (Win32 API) + + Handling hard link using Win32 API. [NTFS only] + + Note: You should worry about file system type when use this module's function in your application: + + * NTFS only supprts this functionality. + + * ReFS doesn't support hard link currently. +-} +module System.Win32.HardLink + ( module System.Win32.HardLink + ) where +import System.Win32.Error ( failIfFalseWithRetry_ ) +import System.Win32.File ( LPSECURITY_ATTRIBUTES ) +import System.Win32.String ( LPCTSTR, withTString ) +import System.Win32.Types ( BOOL, nullPtr ) + +-- | NOTE: createHardLink is /flipped arguments/ to provide compatiblity for Unix. +-- +-- If you want to create hard link by Windows way, use 'createHardLink'' instead. +createHardLink :: FilePath -- ^ Target file path + -> FilePath -- ^ Hard link name + -> IO () +createHardLink = flip createHardLink' + +createHardLink' :: FilePath -- ^ Hard link name + -> FilePath -- ^ Target file path + -> IO () +createHardLink' link target = + withTString target $ \c_target -> + withTString link $ \c_link -> + failIfFalseWithRetry_ (unwords ["CreateHardLinkW",show link,show target]) $ + c_CreateHardLink c_link c_target nullPtr + +foreign import WINDOWS_CCONV unsafe "windows.h CreateHardLinkW" + c_CreateHardLink :: LPCTSTR -- ^ Hard link name + -> LPCTSTR -- ^ Target file path + -> LPSECURITY_ATTRIBUTES -- ^ This parameter is reserved. You should pass just /nullPtr/. + -> IO BOOL + +{- +-- We plan to check file system type internally. + +-- We are thinking about API design, currently... +data VolumeInformation = VolumeInformation + { volumeName :: String + , volumeSerialNumber :: DWORD + , maximumComponentLength :: DWORD + , fileSystemFlags :: DWORD + , fileSystemName :: String + } deriving Show + +getVolumeInformation :: String -> IO VolumeInformation +getVolumeInformation drive = + withTString drive $ \c_drive -> + withTStringBufferLen 256 $ \(vnBuf, vnLen) -> + alloca $ \serialNum -> + alloca $ \maxLen -> + alloca $ \fsFlags -> + withTStringBufferLen 256 $ \(fsBuf, fsLen) -> do + failIfFalse_ (unwords ["GetVolumeInformationW", drive]) $ + c_GetVolumeInformation c_drive vnBuf (fromIntegral vnLen) + serialNum maxLen fsFlags + fsBuf (fromIntegral fsLen) + return VolumeInformation + <*> peekTString vnBuf + <*> peek serialNum + <*> peek maxLen + <*> peek fsFlags + <*> peekTString fsBuf + +-- Which is better? +getVolumeFileType :: String -> IO String +getVolumeFileType drive = fileSystemName <$> getVolumeInformation drive + +getVolumeFileType :: String -> IO String +getVolumeFileType drive = + withTString drive $ \c_drive -> + withTStringBufferLen 256 $ \(buf, len) -> do + failIfFalse_ (unwords ["GetVolumeInformationW", drive]) $ + c_GetVolumeInformation c_drive nullPtr 0 nullPtr nullPtr nullPtr buf (fromIntegral len) + peekTString buf + +foreign import WINDOWS_CCONV unsafe "windows.h GetVolumeInformationW" + c_GetVolumeInformation :: LPCTSTR -> LPTSTR -> DWORD -> LPDWORD -> LPDWORD -> LPDWORD -> LPTSTR -> DWORD -> IO BOOL +-}
System/Win32/Info/Computer.hsc view
@@ -1,7 +1,7 @@ {-# LANGUAGE CPP #-} {- | Module : System.Win32.Info.Computer - Copyright : 2012 shelarcy + Copyright : 2012-2013 shelarcy License : BSD-style Maintainer : shelarcy@gmail.com @@ -10,22 +10,80 @@ Information about your computer. -} -module System.Win32.Info.Computer where -import Data.Word ( Word64 ) -import Foreign.Ptr ( Ptr ) -import Foreign.Marshal.Alloc ( alloca ) +module System.Win32.Info.Computer + ( -- * Environment Strings + expandEnvironmentStrings, c_ExpandEnvironmentStrings + + -- * Computer Name + , getComputerName, setComputerName + , c_GetComputerName, c_SetComputerName + + -- * System metrics + , getSystemMetrics + , sM_CMONITORS + , sM_IMMENABLED + , sM_MOUSEWHEELPRESENT + , sM_REMOTESESSION + , sM_SAMEDISPLAYFORMAT + , sM_XVIRTUALSCREEN + , sM_YVIRTUALSCREEN + , sM_SERVERR2 + , sM_MEDIACENTER + , sM_STARTER + , sM_TABLETPC + + -- * User name + , getUserName, c_GetUserName + + -- * Version Info + , OSVERSIONINFOEX(..), POSVERSIONINFOEX, LPOSVERSIONINFOEX + , ProductType(..) + , getVersionEx, c_GetVersionEx + + -- * Processor features + , ProcessorFeature + , isProcessorFeaturePresent + , pF_3DNOW_INSTRUCTIONS_AVAILABLE + , pF_COMPARE_EXCHANGE_DOUBLE + , pF_FLOATING_POINT_EMULATED + , pF_FLOATING_POINT_PRECISION_ERRATA + , pF_MMX_INSTRUCTIONS_AVAILABLE + , pF_PAE_ENABLED + , pF_RDTSC_INSTRUCTION_AVAILABLE + , pF_XMMI_INSTRUCTIONS_AVAILABLE + , pF_XMMI64_INSTRUCTIONS_AVAILABLE + ) where import Foreign.Marshal.Utils ( with ) import Foreign.Storable ( Storable(..) ) import System.Win32.Error ( failIfFalse_ ) import System.Win32.Info ( SMSetting ) -import System.Win32.String ( LPTSTR, withTString, withTStringBuffer +import System.Win32.Info.Version +import System.Win32.String ( LPCTSTR, LPTSTR, withTString, withTStringBuffer , peekTString, peekTStringLen ) -import System.Win32.Types ( BOOL, WORD, DWORD, LPDWORD, BYTE ) +import System.Win32.Types ( BOOL ) +import System.Win32.Utils ( tryWithoutNull ) +import System.Win32.Word ( DWORD, LPDWORD ) #define _WIN32_WINNT 0x0500 #include <windows.h> #include <Lmcons.h> +---------------------------------------------------------------- +-- Environment Strings +---------------------------------------------------------------- +expandEnvironmentStrings :: String -> IO String +expandEnvironmentStrings name = + withTString name $ \ c_name -> + tryWithoutNull (unwords ["ExpandEnvironmentStrings", name]) + (\buf len -> c_ExpandEnvironmentStrings c_name buf len) 512 + +foreign import WINDOWS_CCONV unsafe "windows.h ExpandEnvironmentStringsW" + c_ExpandEnvironmentStrings :: LPCTSTR -> LPTSTR -> DWORD -> IO DWORD + +---------------------------------------------------------------- +-- Computer Name +---------------------------------------------------------------- + getComputerName :: IO String getComputerName = withTStringBuffer maxLength $ \buf -> @@ -43,7 +101,7 @@ setComputerName :: String -> IO () setComputerName name = withTString name $ \buf -> - failIfFalse_ "SetComputerName" + failIfFalse_ (unwords ["SetComputerName", name]) $ c_SetComputerName buf foreign import WINDOWS_CCONV unsafe "SetComputerNameW" @@ -63,7 +121,52 @@ } -} -foreign import WINDOWS_CCONV unsafe "GetSystemMetrics" +---------------------------------------------------------------- +-- Hardware Profiles +---------------------------------------------------------------- +{- +-- TODO: Deside HW_PROFILE_INFO type design + +type LPHW_PROFILE_INFO = Ptr HW_PROFILE_INFO + +data HW_PROFILE_INFO = HW_PROFILE_INFO + { dwDockInfo :: DWORD + , szHwProfileGuid :: String -- Should we use GUID type instead of String? + , szHwProfileName :: String + } deriving Show + +instance Storable HW_PROFILE_INFO where + sizeOf = const #{size HW_PROFILE_INFOW} + alignment = sizeOf + poke buf info = do + (#poke HW_PROFILE_INFOW, dwDockInfo) buf (dwDockInfo info) + withTString (szHwProfileGuid info) $ \szHwProfileGuid' -> + (#poke HW_PROFILE_INFOW, szHwProfileGuid) buf szHwProfileGuid' + withTString (szHwProfileName info) $ \szHwProfileName' -> + (#poke HW_PROFILE_INFOW, szHwProfileName) buf szHwProfileName' + + peek buf = do + dockInfo <- (#peek HW_PROFILE_INFOW, dwDockInfo) buf + hwProfileGuid <- peekTString $ (#ptr HW_PROFILE_INFOW, szHwProfileGuid) buf + hwProfileName <- peekTString $ (#ptr HW_PROFILE_INFOW, szHwProfileName) buf + return $ HW_PROFILE_INFO dockInfo hwProfileGuid hwProfileName + +getCurrentHwProfile :: IO HW_PROFILE_INFO +getCurrentHwProfile = + alloca $ \buf -> do + failIfFalse_ "GetCurrentHwProfile" + $ c_GetCurrentHwProfile buf + peek buf + +foreign import WINDOWS_CCONV unsafe "windows.h GetCurrentHwProfileW" + c_GetCurrentHwProfile :: LPHW_PROFILE_INFO -> IO Bool +-} + +---------------------------------------------------------------- +-- System metrics +---------------------------------------------------------------- + +foreign import WINDOWS_CCONV unsafe "windows.h GetSystemMetrics" getSystemMetrics :: SMSetting -> IO Int #{enum SMSetting, @@ -97,106 +200,14 @@ -- This requires Lmcons.h maxLength = #const UNLEN -foreign import WINDOWS_CCONV unsafe "GetUserNameW" +foreign import WINDOWS_CCONV unsafe "windows.h GetUserNameW" c_GetUserName :: LPTSTR -> LPDWORD -> IO Bool ---------------------------------------------------------------- --- Version Info ----------------------------------------------------------------- -getVersionEx :: IO OSVERSIONINFOEX -getVersionEx = - alloca $ \buf -> do - (#poke OSVERSIONINFOEXW, dwOSVersionInfoSize) buf - (#{size OSVERSIONINFOEXW}::DWORD) - failIfFalse_ "GetVersionEx" - $ c_GetVersionEx buf - peek buf - -foreign import WINDOWS_CCONV unsafe "GetVersionExW" - c_GetVersionEx :: LPOSVERSIONINFOEX -> IO BOOL - -{- -foreign import WINDOWS_CCONV unsafe "VerifyVersionInfoW" - verifyVersionInfo :: LPOSVERSIONINFOEX -> DWORD -> DWORDLONG -> IO BOOL --} - -type DWORDLONG = Word64 - -data ProductType = VerUnknow BYTE | VerNTWorkStation | VerNTDomainControler | VerNTServer - deriving (Show,Eq) - -instance Storable ProductType where - sizeOf _ = sizeOf (undefined::BYTE) - alignment _ = alignment (undefined::BYTE) - poke buf v = pokeByteOff buf 0 $ case v of - VerUnknow w -> w - VerNTWorkStation -> #const VER_NT_WORKSTATION - VerNTDomainControler -> #const VER_NT_DOMAIN_CONTROLLER - VerNTServer -> #const VER_NT_SERVER - peek buf = do - v <- peekByteOff buf 0 - return $ case v of - (#const VER_NT_WORKSTATION) -> VerNTWorkStation - (#const VER_NT_DOMAIN_CONTROLLER) -> VerNTDomainControler - (#const VER_NT_SERVER) -> VerNTServer - w -> VerUnknow w - -type POSVERSIONINFOEX = Ptr OSVERSIONINFOEX -type LPOSVERSIONINFOEX = Ptr OSVERSIONINFOEX - -data OSVERSIONINFOEX = OSVERSIONINFOEX - { dwMajorVersion :: DWORD - , dwMinorVersion :: DWORD - , dwBuildNumber :: DWORD - , dwPlatformId :: DWORD - , szCSDVersion :: String - , wServicePackMajor :: WORD - , wServicePackMinor :: WORD - , wSuiteMask :: WORD - , wProductType :: ProductType - , wReserved :: BYTE - } deriving Show - -instance Storable OSVERSIONINFOEX where - sizeOf = const #{size struct _OSVERSIONINFOEXW} - alignment = sizeOf - poke buf info = do - (#poke OSVERSIONINFOEXW, dwOSVersionInfoSize) buf - $ sizeOf (undefined::OSVERSIONINFOEX) - (#poke OSVERSIONINFOEXW, dwMajorVersion) buf (dwMajorVersion info) - (#poke OSVERSIONINFOEXW, dwMinorVersion) buf (dwMinorVersion info) - (#poke OSVERSIONINFOEXW, dwBuildNumber) buf (dwBuildNumber info) - (#poke OSVERSIONINFOEXW, dwPlatformId) buf (dwPlatformId info) - withTString (szCSDVersion info) $ \szCSDVersion' -> - (#poke OSVERSIONINFOEXW, szCSDVersion) buf szCSDVersion' - (#poke OSVERSIONINFOEXW, wServicePackMajor) buf (wServicePackMajor info) - (#poke OSVERSIONINFOEXW, wServicePackMinor) buf (wServicePackMinor info) - (#poke OSVERSIONINFOEXW, wSuiteMask) buf (wSuiteMask info) - (#poke OSVERSIONINFOEXW, wProductType) buf (wProductType info) - (#poke OSVERSIONINFOEXW, wReserved) buf (wReserved info) - - peek buf = do - dwMajorVersion <- (#peek OSVERSIONINFOEXW, dwMajorVersion) buf - dwMinorVersion <- (#peek OSVERSIONINFOEXW, dwMinorVersion) buf - dwBuildNumber <- (#peek OSVERSIONINFOEXW, dwBuildNumber) buf - dwPlatformId <- (#peek OSVERSIONINFOEXW, dwPlatformId) buf - szCSDVersion' <- (#peek OSVERSIONINFOEXW, szCSDVersion) buf - szCSDVersion <- peekTString szCSDVersion' - wServicePackMajor <- (#peek OSVERSIONINFOEXW, wServicePackMajor) buf - wServicePackMinor <- (#peek OSVERSIONINFOEXW, wServicePackMinor) buf - wSuiteMask <- (#peek OSVERSIONINFOEXW, wSuiteMask) buf - wProductType <- (#peek OSVERSIONINFOEXW, wProductType) buf - wReserved <- (#peek OSVERSIONINFOEXW, wReserved) buf - return $ OSVERSIONINFOEX dwMajorVersion dwMinorVersion - dwBuildNumber dwPlatformId szCSDVersion - wServicePackMajor wServicePackMinor - wSuiteMask wProductType wReserved - ----------------------------------------------------------------- -- Processor features ---------------------------------------------------------------- -foreign import WINDOWS_CCONV unsafe "IsProcessorFeaturePresent" +foreign import WINDOWS_CCONV unsafe "windows.h IsProcessorFeaturePresent" isProcessorFeaturePresent :: ProcessorFeature -> IO BOOL type ProcessorFeature = DWORD
+ System/Win32/Info/Version.hsc view
@@ -0,0 +1,164 @@+{-# LANGUAGE CPP #-} +{- | + Module : System.Win32.Info.Version + Copyright : 2013 shelarcy + License : BSD-style + + Maintainer : shelarcy@gmail.com + Stability : Provisional + Portability : Non-portable (Win32 API) + + Version information about your computer. +-} +module System.Win32.Info.Version + ( -- * Version Info + OSVERSIONINFOEX(..), POSVERSIONINFOEX, LPOSVERSIONINFOEX + , ProductType(..) + , getVersionEx, c_GetVersionEx + + -- * Verify OS version + , isVistaOrLater, is7OrLater + ) where +import Foreign.Ptr ( Ptr, plusPtr ) +import Foreign.Marshal.Alloc ( alloca ) +import Foreign.Storable ( Storable(..) ) +import System.Win32.Error ( failIfFalse_ ) +import System.Win32.String ( withTString, peekTString ) +import System.Win32.Types ( BOOL, BYTE ) +import System.Win32.Word ( WORD, DWORD ) + +#define _WIN32_WINNT 0x0500 +#include <windows.h> + +---------------------------------------------------------------- +-- Version Info +---------------------------------------------------------------- +getVersionEx :: IO OSVERSIONINFOEX +getVersionEx = + alloca $ \buf -> do + (#poke OSVERSIONINFOEXW, dwOSVersionInfoSize) buf + $ sizeOf (undefined::OSVERSIONINFOEX) + failIfFalse_ "GetVersionEx" + $ c_GetVersionEx buf + peek buf + +data ProductType = VerUnknow BYTE | VerNTWorkStation | VerNTDomainControler | VerNTServer + deriving (Show,Eq) + +instance Storable ProductType where + sizeOf _ = sizeOf (undefined::BYTE) + alignment _ = alignment (undefined::BYTE) + poke buf v = pokeByteOff buf 0 $ case v of + VerUnknow w -> w + VerNTWorkStation -> #const VER_NT_WORKSTATION + VerNTDomainControler -> #const VER_NT_DOMAIN_CONTROLLER + VerNTServer -> #const VER_NT_SERVER + peek buf = do + v <- peekByteOff buf 0 + return $ case v of + (#const VER_NT_WORKSTATION) -> VerNTWorkStation + (#const VER_NT_DOMAIN_CONTROLLER) -> VerNTDomainControler + (#const VER_NT_SERVER) -> VerNTServer + w -> VerUnknow w + +type POSVERSIONINFOEX = Ptr OSVERSIONINFOEX +type LPOSVERSIONINFOEX = Ptr OSVERSIONINFOEX + +data OSVERSIONINFOEX = OSVERSIONINFOEX + { dwMajorVersion :: DWORD + , dwMinorVersion :: DWORD + , dwBuildNumber :: DWORD + , dwPlatformId :: DWORD + , szCSDVersion :: String + , wServicePackMajor :: WORD + , wServicePackMinor :: WORD + , wSuiteMask :: WORD + , wProductType :: ProductType + } deriving Show + +instance Storable OSVERSIONINFOEX where + sizeOf = const #{size struct _OSVERSIONINFOEXW} + alignment = sizeOf + poke buf info = do + (#poke OSVERSIONINFOEXW, dwOSVersionInfoSize) buf (sizeOf info) + (#poke OSVERSIONINFOEXW, dwMajorVersion) buf (dwMajorVersion info) + (#poke OSVERSIONINFOEXW, dwMinorVersion) buf (dwMinorVersion info) + (#poke OSVERSIONINFOEXW, dwBuildNumber) buf (dwBuildNumber info) + (#poke OSVERSIONINFOEXW, dwPlatformId) buf (dwPlatformId info) + withTString (szCSDVersion info) $ \szCSDVersion' -> + (#poke OSVERSIONINFOEXW, szCSDVersion) buf szCSDVersion' + (#poke OSVERSIONINFOEXW, wServicePackMajor) buf (wServicePackMajor info) + (#poke OSVERSIONINFOEXW, wServicePackMinor) buf (wServicePackMinor info) + (#poke OSVERSIONINFOEXW, wSuiteMask) buf (wSuiteMask info) + (#poke OSVERSIONINFOEXW, wProductType) buf (wProductType info) + (#poke OSVERSIONINFOEXW, wReserved) buf (0::BYTE) + + peek buf = do + majorVersion <- (#peek OSVERSIONINFOEXW, dwMajorVersion) buf + minorVersion <- (#peek OSVERSIONINFOEXW, dwMinorVersion) buf + buildNumber <- (#peek OSVERSIONINFOEXW, dwBuildNumber) buf + platformId <- (#peek OSVERSIONINFOEXW, dwPlatformId) buf + cSDVersion <- peekTString $ (#ptr OSVERSIONINFOEXW, szCSDVersion) buf + servicePackMajor <- (#peek OSVERSIONINFOEXW, wServicePackMajor) buf + servicePackMinor <- (#peek OSVERSIONINFOEXW, wServicePackMinor) buf + suiteMask <- (#peek OSVERSIONINFOEXW, wSuiteMask) buf + productType <- (#peek OSVERSIONINFOEXW, wProductType) buf + return $ OSVERSIONINFOEX majorVersion minorVersion + buildNumber platformId cSDVersion + servicePackMajor servicePackMinor + suiteMask productType + +foreign import WINDOWS_CCONV unsafe "windows.h GetVersionExW" + c_GetVersionEx :: LPOSVERSIONINFOEX -> IO BOOL + +---------------------------------------------------------------- +-- Verify OS version +---------------------------------------------------------------- +-- See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx + +isVistaOrLater, is7OrLater :: IO Bool +isVistaOrLater = do + ver <- getVersionEx + return $ 6 <= dwMajorVersion ver + +is7OrLater = do + ver <- getVersionEx + return $ 6 <= dwMajorVersion ver + && 1 <= dwMinorVersion ver + +{- +We don't use VerifyVersionInfo function to above functions. + +Because VerifyVersionInfo is more difficult than GetVersionEx and accessing field in Haskell. + +-- | See: http://support.microsoft.com/kb/225013/ +-- http://msdn.microsoft.com/en-us/library/windows/desktop/ms725491(v=vs.85).aspx + +bIsWindowsVersionOK :: DWORD -> DWORD -> WORD -> IO BOOL +bIsWindowsVersionOK dwMajor dwMinor dwSPMajor = + alloca $ \buf -> do + zeroMemory buf + (#{size OSVERSIONINFOEXW}::DWORD) + (#poke OSVERSIONINFOEXW, dwOSVersionInfoSize) buf + (#{size OSVERSIONINFOEXW}::DWORD) + (#poke OSVERSIONINFOEXW, dwMajorVersion) buf dwMajor + (#poke OSVERSIONINFOEXW, dwMinorVersion) buf dwMinor + (#poke OSVERSIONINFOEXW, wServicePackMajor) buf dwSPMajor + -- Set up the condition mask. + let dwlConditionMask = 0 + flag = #const VER_MAJORVERSION + .|. #const VER_MINORVERSION + .|. #const VER_SERVICEPACKMAJOR + dwlConditionMask' <- vER_SET_CONDITION dwlConditionMask #{const VER_MAJORVERSION} #{const VER_GREATER_EQUAL} + dwlConditionMask'' <- vER_SET_CONDITION dwlConditionMask' #{const VER_MINORVERSION} #{const VER_MINORVERSION} + dwlConditionMask''' <- vER_SET_CONDITION dwlConditionMask'' #{const VER_SERVICEPACKMAJOR} #{const VER_SERVICEPACKMAJOR} + verifyVersionInfo buf flag dwlConditionMask''' + +type ULONGLONG = DWORDLONG + +foreign import capi unsafe "windows.h VER_SET_CONDITION" + vER_SET_CONDITION :: ULONGLONG -> DWORD -> BYTE -> IO ULONGLONG + +foreign import WINDOWS_CCONV unsafe "windows.h VerifyVersionInfoW" + verifyVersionInfo :: LPOSVERSIONINFOEX -> DWORD -> DWORDLONG -> IO BOOL +-}
+ System/Win32/Process/Current.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE CPP #-} +{- | + Module : System.Win32.Process.Current + Copyright : 2013 shelarcy + License : BSD-style + + Maintainer : shelarcy@gmail.com + Stability : Provisional + Portability : Non-portable (Win32 API) + + Get current process handle or id. +-} +module System.Win32.Process.Current where +import System.Win32.Process ( ProcessHandle, ProcessId ) + +foreign import WINDOWS_CCONV unsafe "windows.h GetCurrentProcess" + getCurrentProcess :: IO ProcessHandle + +foreign import WINDOWS_CCONV unsafe "windows.h GetCurrentProcessId" + getCurrentProcessId :: IO ProcessId
System/Win32/String.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {- | Module : System.Win32.String Copyright : 2013 shelarcy @@ -10,7 +9,7 @@ Utilities for primitive marshalling of Windows' C strings. -} -module System.Win32.String +module System.Win32.String ( LPSTR, LPCSTR, LPWSTR, LPCWSTR , TCHAR, LPTSTR, LPCTSTR, LPCTSTR_ , withTString, withTStringLen, peekTString, peekTStringLen @@ -23,7 +22,7 @@ -- using temporary storage. -- -- * the Haskell string is created by length parameter. And the Haskell --- string contains contains /only/ NUL characters. +-- string contains /only/ NUL characters. -- -- * the memory is freed when the subcomputation terminates (either -- normally or via an exception), so the pointer to the temporary @@ -39,7 +38,7 @@ -- information. -- -- * the Haskell string is created by length parameter. And the Haskell --- string contains contains /only/ NUL characters. +-- string contains /only/ NUL characters. -- -- * the memory is freed when the subcomputation terminates (either -- normally or via an exception), so the pointer to the temporary
System/Win32/SymbolicLink.hs view
@@ -10,7 +10,7 @@ Handling symbolic link using Win32 API. [Vista of later and desktop app only] - Note: You should worry about UAC (User Account Control) when use this module function in your application: + Note: You should worry about UAC (User Account Control) when use this module's function in your application: * require to use 'Run As Administrator' to run your application. @@ -23,18 +23,26 @@ import Foreign.Ptr ( FunPtr ) import System.Win32.DLL.LoadFunction import System.Win32.Error ( failIfFalseWithRetry_ ) +import System.Win32.Exception.Unsupported ( upgradeVista ) import System.Win32.Types --- | createSymbolicLink* doesn't check that file is exist or not. -createSymbolicLink :: FilePath -> FilePath -> SymbolicLinkFlags -> IO () +-- | createSymbolicLink* functions don't check that file is exist or not. +-- +-- NOTE: createSymbolicLink* functions are /flipped arguments/ to provide compatiblity for Unix, +-- except 'createSymbolicLink''. +-- +-- If you want to create symbolic link by Windows way, use 'createSymbolicLink'' instead. +createSymbolicLink :: FilePath -- ^ Target file path + -> FilePath -- ^ Symbolic link name + -> SymbolicLinkFlags -> IO () createSymbolicLink = flip createSymbolicLink' createSymbolicLinkFile :: FilePath -> FilePath -> IO () -createSymbolicLinkFile src target = createSymbolicLink' target src sYMBOLIC_LINK_FLAG_FILE +createSymbolicLinkFile target link = createSymbolicLink' link target sYMBOLIC_LINK_FLAG_FILE createSymbolicLinkDirectory :: FilePath -> FilePath -> IO () -createSymbolicLinkDirectory src target = createSymbolicLink' target src sYMBOLIC_LINK_FLAG_DIRECTORY +createSymbolicLinkDirectory target link = createSymbolicLink' link target sYMBOLIC_LINK_FLAG_DIRECTORY -- portable version type SymbolicLinkFlags = DWORD @@ -43,25 +51,29 @@ sYMBOLIC_LINK_FLAG_DIRECTORY = 0x1 -- portable version -createSymbolicLink' :: String -> String -> SymbolicLinkFlags -> IO () -createSymbolicLink' target src flag = - withLoadSystemFunction "Kernel32.dll" "CreateSymbolicLinkW" $ \c_CreateSymbolicLink -> - withTString target $ \c_target -> - withTString src $ \c_src -> - failIfFalseWithRetry_ (unwords ["CreateSymbolicLink",show target,show src]) $ - convCreateSymbolicLink c_CreateSymbolicLink c_target c_src flag +createSymbolicLink' :: FilePath -- ^ Symbolic link name + -> FilePath -- ^ Target file path + -> SymbolicLinkFlags -> IO () +createSymbolicLink' link target flag = + withLoadSystemFunction "Kernel32.dll" "CreateSymbolicLinkW" upgradeVista $ \c_CreateSymbolicLink -> + withTString link $ \c_link -> + withTString target $ \c_target -> + failIfFalseWithRetry_ (unwords ["CreateSymbolicLink",show link,show target]) $ + mkCreateSymbolicLink c_CreateSymbolicLink c_link c_target flag -foreign import WINDOWS_CCONV unsafe "dynamic" convCreateSymbolicLink :: +foreign import WINDOWS_CCONV unsafe "dynamic" mkCreateSymbolicLink :: FunPtr (LPTSTR -> LPTSTR -> SymbolicLinkFlags -> IO BOOL) -> (LPTSTR -> LPTSTR -> SymbolicLinkFlags -> IO BOOL) {- -- non portable version. -createSymbolicLink' :: String -> String -> SymbolicLinkFlags -> IO () -createSymbolicLink' target src flag = do - withTString target $ \c_target -> - withTString src $ \c_src -> - failIfFalseWithRetry_ (unwords ["CreateSymbolicLink",show target,show src]) $ - c_CreateSymbolicLink c_target c_src flag +createSymbolicLink' :: FilePath -- ^ Symbolic link name + -> FilePath -- ^ Target file path + -> SymbolicLinkFlags -> IO () +createSymbolicLink' link target flag = do + withTString link $ \c_link -> + withTString target $ \c_target -> + failIfFalseWithRetry_ (unwords ["CreateSymbolicLink",show link,show target]) $ + c_CreateSymbolicLink c_link c_target flag {enum SymbolicLinkFlags, , sYMBOLIC_LINK_FLAG_FILE = SYMBOLIC_LINK_FLAG_FILE
+ System/Win32/Utils.hs view
@@ -0,0 +1,77 @@+{- | + Module : System.Win32.Utils + Copyright : 2009 Balazs Komuves, 2013 shelarcy + License : BSD-style + + Maintainer : shelarcy@gmail.com + Stability : Provisional + Portability : Non-portable (Win32 API) + + Utilities for calling Win32 API +-} +module System.Win32.Utils + ( try, tryWithoutNull, try' + -- * Maybe values + , maybePtr, ptrToMaybe, maybeNum, numToMaybe + , peekMaybe, withMaybe + ) where +import Control.Monad ( unless ) +import Data.Functor ( (<$>) ) +import Foreign.Marshal.Array ( allocaArray, peekArray ) +import Foreign.Marshal.Utils ( with ) +import Foreign.Ptr ( Ptr, nullPtr ) +import Foreign.Storable ( Storable(..) ) +import System.Win32.Error ( failIfZero + , failWith, getLastError, eRROR_INSUFFICIENT_BUFFER ) +import qualified System.Win32.Info ( try ) +import System.Win32.String ( LPTSTR, peekTString ) +import System.Win32.Types ( BOOL, UINT, maybePtr, ptrToMaybe, maybeNum, numToMaybe ) +import System.Win32.Word ( DWORD, PDWORD ) + + +-- | Support for API calls that are passed a fixed-size buffer and tell +-- you via the return value if the buffer was too small. In that +-- case, we extend the buffer size and try again. +try :: String -> (LPTSTR -> UINT -> IO UINT) -> UINT -> IO String +try = System.Win32.Info.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 + +-- | See also: 'Foreign.Marshal.Utils.maybePeek' function. +peekMaybe :: Storable a => Ptr a -> IO (Maybe a) +peekMaybe p = + if p == nullPtr + then return Nothing + else Just <$> peek p + +-- | See also: 'Foreign.Marshal.Utils.maybeWith' function. +withMaybe :: Storable a => Maybe a -> (Ptr a -> IO b) -> IO b +withMaybe Nothing action = action nullPtr +withMaybe (Just x) action = with x action
+ System/Win32/Word.hs view
@@ -0,0 +1,23 @@+{- | + Module : System.Win32.Word + Copyright : 2013 shelarcy + License : BSD-style + + Maintainer : shelarcy@gmail.com + Stability : Provisional + Portability : Non-portable (Win32 API) + + Windows' unsigned integer types and pointer type. +-} +module System.Win32.Word + ( WORD, DWORD, PDWORD, LPDWORD + , DWORDLONG, DDWORD + , DWORD32, DWORD64, DWORD_PTR + ) where +import Data.Word ( Word64 ) +import Foreign.Ptr ( Ptr ) +import System.Win32.Types ( WORD, DWORD, LPDWORD, DDWORD ) +import System.Win32.Types.Compat ( DWORD32, DWORD64, DWORD_PTR ) + +type PDWORD = Ptr DWORD +type DWORDLONG = Word64
Win32-extras.cabal view
@@ -1,10 +1,10 @@ name: Win32-extras -version: 0.1.0.0 +version: 0.2.0.0 synopsis: Provides missing Win32 API description: This package provides missing features of Win32 package. . This should be part of Win32 package. But it seems that Win32 package is not active development now. - So, I made an separated package for solving today problem. + So, I made a separated package for solving today problem. license: BSD3 license-file: LICENSE author: shelarcy @@ -13,7 +13,9 @@ category: System, Graphics build-type: Simple cabal-version: >=1.10 +homepage: http://hub.darcs.net/shelarcy/Win32-extras/ bug-reports: http://hub.darcs.net/shelarcy/Win32-extras/issues +extra-source-files: changelog source-repository head type: darcs @@ -31,14 +33,22 @@ Media.Win32 + System.Win32.Console.CtrlHandler + System.Win32.Console.HWND + System.Win32.Console.Title System.Win32.DLL.LoadFunction System.Win32.Encoding System.Win32.Error System.Win32.Exception.Unsupported + System.Win32.HardLink System.Win32.Info.Computer + System.Win32.Info.Version + System.Win32.Process.Current System.Win32.String System.Win32.SymbolicLink System.Win32.Types.Compat + System.Win32.Utils + System.Win32.Word other-modules: System.Win32.Error.MultiByte build-depends: base < 5, Win32 @@ -48,4 +58,7 @@ else cpp-options: "-DWINDOWS_CCONV=ccall" extra-libraries: msimg32, imm32 - ghc-options : -Wall -fno-warn-name-shadowing + ghc-options : -Wall + include-dirs: include + includes: alphablend.h + c-sources: cbits/alphablend.c
+ cbits/alphablend.c view
@@ -0,0 +1,15 @@+#include <alphablend.h>++BOOL c_AlphaBlend ( HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int hHeightDest+ , HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc+ , PBLENDFUNCTION pblendFunction)+{+ BLENDFUNCTION blendFunction;+ blendFunction.BlendOp = pblendFunction->BlendOp;+ blendFunction.BlendFlags = pblendFunction->BlendFlags;+ blendFunction.SourceConstantAlpha = pblendFunction->SourceConstantAlpha;+ blendFunction.AlphaFormat = pblendFunction->AlphaFormat;+ AlphaBlend ( hdcDest, nXOriginDest, nYOriginDest, nWidthDest, hHeightDest+ , hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc+ , blendFunction);+}
+ changelog view
@@ -0,0 +1,24 @@+0.2.0.0 Nov 13 2013+ * Add mOD_NOREPEAT value to Graphics.Win32.Window.HotKey+ * Fix typo of toLayeredWindow function name in Graphics.Win32.LayeredWindow+ * Add System.Win32.Console.CtrlHandler module+ * Add System.Win32.Console.Title module+ * Add System.Win32.Console.HWND module+ * Export wideCharToMultiByte function from System.Win32.Encoding+ * Re-export multiByteToWideChar function from System.Win32.Encoding+ * Add failIfZero_, eRROR_INSUFFICIENT_BUFFER, eRROR_MOD_NOT_FOUND and eRROR_PROC_NOT_FOUND to System.Win32.Error+ * Re-export getLastError function from System.Win32.Error+ * Add upgradeWindowsOS function to System.Win32.Exception.Unsupported+ * Add upgradeWindowsOS and unsupportedVal function to System.Win32.Exception.Unsupported+ * Change missingWin32Function and missingWin32Value's types+ * Add System.Win32.HardLink module+ * Add expandEnvironmentStrings function to System.Win32.Info.Computer+ * Add System.Win32.Info.Version module+ * Change and fix OSVERSIONINFOEX type's definition+ * Change loadFunction, loadSystemFunction, withLoadFunction and withLoadSystemFunction types+ * Add System.Win32.Process.Current module+ * Add System.Win32.Utils module+ * Add System.Win32.Word module to re-export WORD types++0.1.0.0 Sep 29 2013+ * First release