Getting local AppData folder in Haskell

I am trying to get the local Window Local AppData folder using the agnostic version using Haskell and I am having problems with this. I tried to use the System.Win32.Registry library, and I was able to get the code below (after some trial and error), but I could not figure out how to use regQueryValueExor any other function to get the desired value.

import System.Win32.Types
import System.Win32.Registry

userShellFolders :: IO HKEY
userShellFolders = regOpenKeyEx hKEY_CURRENT_USER "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\" kEY_QUERY_VALUE

I also tried to look at the source code for the function getAppUserDataDirectoryin the System.Directory module, but that didn't help either.

Maybe there is an easier way to do this, which I just miss.

+3
source share
2 answers

, . API : SHGetFolderPath. :

{-# LANGUAGE ForeignFunctionInterface #-}
import System.Win32.Types
import Graphics.Win32.GDI.Types
import Foreign.C.String
import Foreign.Marshal.Array

foreign import stdcall unsafe "SHGetFolderPathW"
    cSHGetFolderPathW :: HWND -> INT -> HANDLE -> DWORD -> CWString -> IO LONG

maxPath = 260
cSIDL_LOCAL_APPDATA = 0x001c -- //see file ShlObj.h in MS Platform SDK for other CSIDL constants

getShellFolder :: INT -> IO String
getShellFolder csidl = allocaArray0 maxPath $ \path -> do
    cSHGetFolderPathW nullHANDLE csidl nullHANDLE 0 path
    peekCWString path

main = getShellFolder cSIDL_LOCAL_APPDATA >>= putStrLn
+11

, Haskell C. , , REG_EXPAND_SZ . , :

{-# LANGUAGE ForeignFunctionInterface #-}

import System.Win32.Types
import System.Win32.Registry
import Foreign.Ptr (castPtr)
import Foreign.Marshal.Alloc (allocaBytes)
import Foreign.C.String (peekCWString, withCWString)
import Control.Exception (bracket, throwIO)

-- // parse a string from a registry value of certain type
parseRegString :: RegValueType -> LPBYTE -> IO String
parseRegString ty mem
   | ty == rEG_SZ        = peekCWString (castPtr mem)
   | ty == rEG_EXPAND_SZ = peekCWString (castPtr mem) >>=
                              expandEnvironmentStrings
   | otherwise           = ioError (userError "Invalid registry value type")

-- // FFI import of the ExpandEnvironmentStrings function needed
-- // to make use of the registry values
expandEnvironmentStrings :: String -> IO String
expandEnvironmentStrings toexpand =
   withCWString toexpand $ \input ->
   allocaBytes 512 $ \output ->
   do c_ExpandEnvironmentStrings input output 256
      peekCWString output
foreign import stdcall unsafe "windows.h ExpandEnvironmentStringsW"
  c_ExpandEnvironmentStrings :: LPCTSTR -> LPTSTR -> DWORD -> IO DWORD

-- // open the registry key
userShellFolders :: IO HKEY
userShellFolders = regOpenKeyEx hKEY_CURRENT_USER
   "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"
   kEY_QUERY_VALUE

-- // read the actual value
localAppData :: IO String
localAppData =
   bracket userShellFolders regCloseKey $ \usfkey ->
   allocaBytes 512 $ \mem ->
   do ty <- regQueryValueEx usfkey "Local AppData" mem 512
      parseRegString ty mem

main = localAppData >>= print

, (, ), Windows, , .

0

Source: https://habr.com/ru/post/1715789/


All Articles