{-# 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.String ( withTString, peekTString ) import System.Win32.Types ( BOOL, BYTE, failIfFalse_ ) import System.Win32.Word ( WORD, DWORD ) #include #include "alignment.h" ##include "windows_cconv.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 _ = #alignment OSVERSIONINFOEX 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 -}