aboutsummaryrefslogblamecommitdiffstatshomepage
path: root/src/Registry.hs
blob: d6c3f267375374e7c676001fe923ecf3169e23d8 (plain) (tree)
1
2
3
4
5
6
7
8
9
10





                                                            
                          


                           

                                   


                                    



                                                    
                                            



                                                           

                                  

                                                              

                                                            


                                                                             

               

                            


                                           



                                                                
                                         

                             
                                                                                  







                                                                               
                                                                                   
                                       


                                                                                                                         


                                                               
                                              
                                              
                                                                                                                                

                           

                                



                                                         
                                                        

             
                               
 


                                                               
                                       

                                                 
                           




                                                                                                                         




                                   
{-
 - Copyright 2015 Egor Tensin <Egor.Tensin@gmail.com>
 - This file is licensed under the terms of the MIT License.
 - See LICENSE.txt for details.
-}

module Registry ( delValue
                , getString
                , hkcu
                , hklm
                , setString
                , KeyHandle ) where

import Control.Exception ( bracket )
import Data.Maybe ( fromMaybe )
import Foreign.ForeignPtr ( withForeignPtr )
import Foreign.Marshal.Alloc ( alloca, allocaBytes )
import Foreign.Ptr ( castPtr, plusPtr )
import Foreign.Storable ( peek, poke, sizeOf )
import Graphics.Win32.Window ( sendMessage )
import System.IO.Error ( mkIOError, doesNotExistErrorType )
import System.Win32.Types
import System.Win32.Registry

newtype KeyHandle = KeyHandle HKEY

getType :: HKEY -> String -> String -> IO (Maybe RegValueType)
getType key subKeyPath valueName =
  bracket (regOpenKey key subKeyPath) regCloseKey $ \hKey ->
  withForeignPtr hKey $ \p_key ->
  withTString valueName $ \p_valueName ->
  alloca $ \p_type -> do
    ret <- c_RegQueryValueEx p_key p_valueName nullPtr p_type nullPtr nullPtr
    case ret of
      0x0 -> do
        type_ <- peek p_type
        return $ Just type_
      0x2 -> return Nothing
      _   -> failWith "RegQueryValueEx" ret

getString :: KeyHandle -> String -> String -> IO String
getString (KeyHandle hKey) subKeyPath valueName =
  bracket (regOpenKey hKey subKeyPath) regCloseKey $ \hSubKey ->
  withForeignPtr hSubKey $ \p_key ->
  withTString valueName $ \p_valueName ->
  alloca $ \dataSizePtr -> do
    poke dataSizePtr 0
    ret <- c_RegQueryValueEx p_key p_valueName nullPtr nullPtr nullPtr dataSizePtr
    case ret of
      0x0 -> do
        dataSize <- peek dataSizePtr
        let newDataSize = dataSize + fromIntegral (sizeOf (undefined :: TCHAR))
        poke dataSizePtr newDataSize
        allocaBytes (fromIntegral newDataSize) $ \dataPtr -> do
          poke (castPtr $ plusPtr dataPtr $ fromIntegral dataSize) '\0'
          failUnlessSuccess "RegQueryValueEx" $
            c_RegQueryValueEx p_key p_valueName nullPtr nullPtr dataPtr dataSizePtr
          peekTString $ castPtr dataPtr
      0x2 -> ioError $ mkIOError doesNotExistErrorType "RegQueryValueEx" Nothing $ Just (subKeyPath ++ "\\" ++ valueName)
      _   -> failWith "RegQueryValueEx" ret

setString :: KeyHandle -> String -> String -> String -> IO ()
setString (KeyHandle hKey) subKeyPath valueName valueValue =
  bracket (regOpenKey hKey subKeyPath) regCloseKey $ \subKey ->
  withTString valueValue $ \p_valueValue -> do
    type_ <- getType hKey subKeyPath valueName
    regSetValueEx subKey valueName (fromMaybe rEG_SZ type_) p_valueValue $ (length valueValue + 1) * sizeOf (undefined :: TCHAR)
    notifyEnvironmentUpdate

notifyEnvironmentUpdate :: IO ()
notifyEnvironmentUpdate =
  withTString "Environment" $ \p_lparam -> do
    let wparam = 0
    let lparam = fromIntegral $ castPtrToUINTPtr p_lparam
    let hwnd = castUINTPtrToPtr 0xffff
    _ <- sendMessage hwnd wM_SETTINGCHANGE wparam lparam
    return ()
      where
        wM_SETTINGCHANGE = 0x1A

delValue :: KeyHandle -> String -> String -> IO ()
delValue (KeyHandle hKey) subKeyPath valueName =
  bracket (regOpenKey hKey subKeyPath) regCloseKey $ \subKey ->
  withForeignPtr subKey $ \subKeyPtr ->
  withTString valueName $ \p_valueName -> do
    ret <- c_RegDeleteValue subKeyPtr p_valueName
    notifyEnvironmentUpdate
    case ret of
      0x0 -> return ()
      0x2 -> ioError $ mkIOError doesNotExistErrorType "RegQueryValueEx" Nothing $ Just (subKeyPath ++ "\\" ++ valueName)
      _   -> failWith "RegDeleteValue" ret

hkcu :: KeyHandle
hkcu = KeyHandle hKEY_CURRENT_USER

hklm :: KeyHandle
hklm = KeyHandle hKEY_LOCAL_MACHINE