{-# LINE 1 "System\\Win32\\Info\\Version.hsc" #-}

{-# 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 "windows_cconv.h"



----------------------------------------------------------------

-- Version Info

----------------------------------------------------------------

getVersionEx :: IO OSVERSIONINFOEX

getVersionEx =

  alloca $ \buf -> do

    ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf

{-# LINE 40 "System\\Win32\\Info\\Version.hsc" #-}

      $ 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     -> 1

{-# LINE 54 "System\\Win32\\Info\\Version.hsc" #-}

        VerNTDomainControler -> 2

{-# LINE 55 "System\\Win32\\Info\\Version.hsc" #-}

        VerNTServer          -> 3

{-# LINE 56 "System\\Win32\\Info\\Version.hsc" #-}

    peek buf = do

        v <- peekByteOff buf 0

        return $ case v of

            (1)       -> VerNTWorkStation

{-# LINE 60 "System\\Win32\\Info\\Version.hsc" #-}

            (2) -> VerNTDomainControler

{-# LINE 61 "System\\Win32\\Info\\Version.hsc" #-}

            (3)            -> VerNTServer

{-# LINE 62 "System\\Win32\\Info\\Version.hsc" #-}

            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 (284)

{-# LINE 81 "System\\Win32\\Info\\Version.hsc" #-}

    alignment _ = 4

{-# LINE 82 "System\\Win32\\Info\\Version.hsc" #-}

    poke buf info = do

        ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf (sizeOf info)

{-# LINE 84 "System\\Win32\\Info\\Version.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 4)) buf (dwMajorVersion info)

{-# LINE 85 "System\\Win32\\Info\\Version.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) buf (dwMinorVersion info)

{-# LINE 86 "System\\Win32\\Info\\Version.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 12))  buf (dwBuildNumber info)

{-# LINE 87 "System\\Win32\\Info\\Version.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 16)) buf (dwPlatformId info)

{-# LINE 88 "System\\Win32\\Info\\Version.hsc" #-}

        withTString (szCSDVersion info) $ \szCSDVersion' ->

          ((\hsc_ptr -> pokeByteOff hsc_ptr 20)) buf szCSDVersion'

{-# LINE 90 "System\\Win32\\Info\\Version.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 276)) buf (wServicePackMajor info)

{-# LINE 91 "System\\Win32\\Info\\Version.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 278)) buf (wServicePackMinor info)

{-# LINE 92 "System\\Win32\\Info\\Version.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 280))   buf (wSuiteMask info)

{-# LINE 93 "System\\Win32\\Info\\Version.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 282)) buf (wProductType info)

{-# LINE 94 "System\\Win32\\Info\\Version.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 283))    buf (0::BYTE)

{-# LINE 95 "System\\Win32\\Info\\Version.hsc" #-}



    peek buf = do

        majorVersion     <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) buf

{-# LINE 98 "System\\Win32\\Info\\Version.hsc" #-}

        minorVersion     <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) buf

{-# LINE 99 "System\\Win32\\Info\\Version.hsc" #-}

        buildNumber      <- ((\hsc_ptr -> peekByteOff hsc_ptr 12)) buf

{-# LINE 100 "System\\Win32\\Info\\Version.hsc" #-}

        platformId       <- ((\hsc_ptr -> peekByteOff hsc_ptr 16)) buf

{-# LINE 101 "System\\Win32\\Info\\Version.hsc" #-}

        cSDVersion       <- peekTString $ ((\hsc_ptr -> hsc_ptr `plusPtr` 20)) buf

{-# LINE 102 "System\\Win32\\Info\\Version.hsc" #-}

        servicePackMajor <- ((\hsc_ptr -> peekByteOff hsc_ptr 276)) buf

{-# LINE 103 "System\\Win32\\Info\\Version.hsc" #-}

        servicePackMinor <- ((\hsc_ptr -> peekByteOff hsc_ptr 278)) buf

{-# LINE 104 "System\\Win32\\Info\\Version.hsc" #-}

        suiteMask        <- ((\hsc_ptr -> peekByteOff hsc_ptr 280)) buf

{-# LINE 105 "System\\Win32\\Info\\Version.hsc" #-}

        productType      <- ((\hsc_ptr -> peekByteOff hsc_ptr 282)) buf

{-# LINE 106 "System\\Win32\\Info\\Version.hsc" #-}

        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

-}