From 7b3fd9218596a2d7a14a92625a4d62c9a7b7b0f6 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Mon, 11 Jul 2016 19:11:23 +0300 Subject: rename modules + fix compiler warnings --- src/EnvUtils.hs | 81 --------------------------------------------- src/Environment.hs | 83 ++++++++++++++++++++++++++++++++++++++++++++++ src/RegUtils.hs | 91 -------------------------------------------------- src/Registry.hs | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 172 deletions(-) delete mode 100644 src/EnvUtils.hs create mode 100644 src/Environment.hs delete mode 100644 src/RegUtils.hs create mode 100644 src/Registry.hs (limited to 'src') diff --git a/src/EnvUtils.hs b/src/EnvUtils.hs deleted file mode 100644 index 7e9bc96..0000000 --- a/src/EnvUtils.hs +++ /dev/null @@ -1,81 +0,0 @@ -{- - - Copyright 2015 Egor Tensin - - This file is licensed under the terms of the MIT License. - - See LICENSE.txt for details. --} - -module EnvUtils ( saveToRegistry - , saveToRegistryWithPrompt - , queryFromRegistry - , wipeFromRegistry - , wipeFromRegistryWithPrompt - , getEnv - , splitPaths - , joinPaths - , RegistryBasedEnvironment ( CurrentUserEnvironment, AllUsersEnvironment ) ) where - -import Control.Monad ( liftM, when ) -import Data.List ( intercalate ) -import Data.List.Split ( splitOn ) -import Data.Maybe ( fromMaybe ) -import qualified System.Environment ( lookupEnv ) -import System.IO.Error ( catchIOError, isDoesNotExistError ) - -import qualified RegUtils -import qualified Utils ( promptToContinue ) - -data RegistryBasedEnvironment = CurrentUserEnvironment - | AllUsersEnvironment - deriving (Eq, Show) - -registrySubKeyPath :: RegistryBasedEnvironment -> String -registrySubKeyPath CurrentUserEnvironment = "Environment" -registrySubKeyPath AllUsersEnvironment = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment" - -registryKey CurrentUserEnvironment = RegUtils.hkcu -registryKey AllUsersEnvironment = RegUtils.hklm - -registryKeyPath :: RegistryBasedEnvironment -> String -registryKeyPath CurrentUserEnvironment = "HKCU\\" ++ registrySubKeyPath CurrentUserEnvironment -registryKeyPath AllUsersEnvironment = "HKLM\\" ++ registrySubKeyPath AllUsersEnvironment - -saveToRegistry :: RegistryBasedEnvironment -> String -> String -> IO () -saveToRegistry env = RegUtils.setString (registryKey env) (registrySubKeyPath env) - -saveToRegistryWithPrompt :: RegistryBasedEnvironment -> String -> String -> IO () -saveToRegistryWithPrompt env name value = do - putStrLn $ "Saving variable '" ++ name ++ "' to '" ++ registryKeyPath env ++ "'..." - oldValue <- queryFromRegistry env name - putStrLn $ "\tOld value: " ++ oldValue - putStrLn $ "\tNew value: " ++ value - agreed <- Utils.promptToContinue - when agreed $ saveToRegistry env name value - -queryFromRegistry :: RegistryBasedEnvironment -> String -> IO String -queryFromRegistry env name = catchIOError (RegUtils.getString (registryKey env) (registrySubKeyPath env) name) emptyIfDoesNotExist - where - emptyIfDoesNotExist :: IOError -> IO String - emptyIfDoesNotExist e = if isDoesNotExistError e then return "" else ioError e - -wipeFromRegistry :: RegistryBasedEnvironment -> String -> IO () -wipeFromRegistry env name = catchIOError (RegUtils.delValue (registryKey env) (registrySubKeyPath env) name) ignoreIfDoesNotExist - where - ignoreIfDoesNotExist :: IOError -> IO () - ignoreIfDoesNotExist e = if isDoesNotExistError e then return () else ioError e - -wipeFromRegistryWithPrompt :: RegistryBasedEnvironment -> String -> IO () -wipeFromRegistryWithPrompt env name = do - putStrLn $ "Deleting variable '" ++ name ++ "' from '" ++ registryKeyPath env ++ "'..." - agreed <- Utils.promptToContinue - when agreed $ wipeFromRegistry env name - -getEnv :: String -> IO String -getEnv = liftM (fromMaybe "") . System.Environment.lookupEnv - -pathSep = ";" - -splitPaths :: String -> [String] -splitPaths = filter (not . null) . splitOn pathSep - -joinPaths :: [String] -> String -joinPaths = intercalate pathSep . filter (not . null) diff --git a/src/Environment.hs b/src/Environment.hs new file mode 100644 index 0000000..0690278 --- /dev/null +++ b/src/Environment.hs @@ -0,0 +1,83 @@ +{- + - Copyright 2015 Egor Tensin + - This file is licensed under the terms of the MIT License. + - See LICENSE.txt for details. +-} + +module Environment ( saveToRegistry + , saveToRegistryWithPrompt + , queryFromRegistry + , wipeFromRegistry + , wipeFromRegistryWithPrompt + , getEnv + , splitPaths + , joinPaths + , RegistryBasedEnvironment(..) ) where + +import Control.Monad ( liftM, when ) +import Data.List ( intercalate ) +import Data.List.Split ( splitOn ) +import Data.Maybe ( fromMaybe ) +import qualified System.Environment ( lookupEnv ) +import System.IO.Error ( catchIOError, isDoesNotExistError ) + +import qualified Registry +import qualified Utils ( promptToContinue ) + +data RegistryBasedEnvironment = CurrentUserEnvironment + | AllUsersEnvironment + deriving (Eq, Show) + +registrySubKeyPath :: RegistryBasedEnvironment -> String +registrySubKeyPath CurrentUserEnvironment = "Environment" +registrySubKeyPath AllUsersEnvironment = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment" + +registryKey :: RegistryBasedEnvironment -> Registry.KeyHandle +registryKey CurrentUserEnvironment = Registry.hkcu +registryKey AllUsersEnvironment = Registry.hklm + +registryKeyPath :: RegistryBasedEnvironment -> String +registryKeyPath CurrentUserEnvironment = "HKCU\\" ++ registrySubKeyPath CurrentUserEnvironment +registryKeyPath AllUsersEnvironment = "HKLM\\" ++ registrySubKeyPath AllUsersEnvironment + +saveToRegistry :: RegistryBasedEnvironment -> String -> String -> IO () +saveToRegistry env = Registry.setString (registryKey env) (registrySubKeyPath env) + +saveToRegistryWithPrompt :: RegistryBasedEnvironment -> String -> String -> IO () +saveToRegistryWithPrompt env name value = do + putStrLn $ "Saving variable '" ++ name ++ "' to '" ++ registryKeyPath env ++ "'..." + oldValue <- queryFromRegistry env name + putStrLn $ "\tOld value: " ++ oldValue + putStrLn $ "\tNew value: " ++ value + agreed <- Utils.promptToContinue + when agreed $ saveToRegistry env name value + +queryFromRegistry :: RegistryBasedEnvironment -> String -> IO String +queryFromRegistry env name = catchIOError (Registry.getString (registryKey env) (registrySubKeyPath env) name) emptyIfDoesNotExist + where + emptyIfDoesNotExist :: IOError -> IO String + emptyIfDoesNotExist e = if isDoesNotExistError e then return "" else ioError e + +wipeFromRegistry :: RegistryBasedEnvironment -> String -> IO () +wipeFromRegistry env name = catchIOError (Registry.delValue (registryKey env) (registrySubKeyPath env) name) ignoreIfDoesNotExist + where + ignoreIfDoesNotExist :: IOError -> IO () + ignoreIfDoesNotExist e = if isDoesNotExistError e then return () else ioError e + +wipeFromRegistryWithPrompt :: RegistryBasedEnvironment -> String -> IO () +wipeFromRegistryWithPrompt env name = do + putStrLn $ "Deleting variable '" ++ name ++ "' from '" ++ registryKeyPath env ++ "'..." + agreed <- Utils.promptToContinue + when agreed $ wipeFromRegistry env name + +getEnv :: String -> IO String +getEnv = liftM (fromMaybe "") . System.Environment.lookupEnv + +pathSep :: String +pathSep = ";" + +splitPaths :: String -> [String] +splitPaths = filter (not . null) . splitOn pathSep + +joinPaths :: [String] -> String +joinPaths = intercalate pathSep . filter (not . null) diff --git a/src/RegUtils.hs b/src/RegUtils.hs deleted file mode 100644 index eccb6ad..0000000 --- a/src/RegUtils.hs +++ /dev/null @@ -1,91 +0,0 @@ -{- - - Copyright 2015 Egor Tensin - - This file is licensed under the terms of the MIT License. - - See LICENSE.txt for details. --} - -module RegUtils ( delValue - , getString - , hkcu - , hklm - , setString ) 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 - -getType :: HKEY -> String -> String -> IO (Maybe RegValueType) -getType key subKeyPath valueName = - bracket (regOpenKey key subKeyPath) regCloseKey $ \key -> - withForeignPtr key $ \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 :: HKEY -> String -> String -> IO String -getString key subKeyPath valueName = - bracket (regOpenKey key subKeyPath) regCloseKey $ \key -> - withForeignPtr key $ \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 :: HKEY -> String -> String -> String -> IO () -setString key subKeyPath valueName valueValue = - bracket (regOpenKey key subKeyPath) regCloseKey $ \subKey -> - withTString valueValue $ \p_valueValue -> do - type_ <- getType key 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 :: HKEY -> String -> String -> IO () -delValue key subKeyPath valueName = - bracket (regOpenKey key 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 = hKEY_CURRENT_USER -hklm = hKEY_LOCAL_MACHINE diff --git a/src/Registry.hs b/src/Registry.hs new file mode 100644 index 0000000..d6c3f26 --- /dev/null +++ b/src/Registry.hs @@ -0,0 +1,97 @@ +{- + - Copyright 2015 Egor Tensin + - 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 -- cgit v1.2.3