HardRock
HardRock

Reputation: 23

Haskell: Importing a DWORD value into the Windows Registry

I want to write a small program that reads data from a text file and then imports it into the Windows Registry. I've found the bindings to the Windows functions in the System.Win32.Registry package, but ran into an issue with the regSetValueEx function. When I want to import a number as a DWORD (Word32) I can't figure out how to pass it to regSetValueEx to get the desired result.

Right now I'm storing the number as a TCHAR and using alloca and poke to get a pointer. Here's the code I'm using for testing:

module Main where

import           Foreign.Marshal.Alloc
import           Foreign.Storable
import           System.Win32.Registry
import           System.Win32.Types

number :: TCHAR
number = 42

getKey :: IO HKEY
getKey = regOpenKey hKEY_CURRENT_USER "test"

importFromTCHAR :: IO ()
importFromTCHAR = alloca $ \ptr -> do
                  poke ptr number
                  key <- getKey
                  regSetValueEx key "tchar" rEG_DWORD ptr (sizeOf (undefined::DWORD))

main :: IO ()
main = importFromTCHAR

The result: 0x0184002a

It kinda works, but since the size of a TCHAR value is only 2 bytes the other two bytes is taken up by junk. How can I prevent this? Any help would be greatly appreciated. I'm fairly new to Haskell (only recently finished LYAH), so please go easy on me. :)

Also, I'd really like to know what libraries more experienced Haskellers use to interface with the Windows Registry. Is there any libraries that makes working with it easier?

EDIT: Alright, as it turns out while looking through the packages on Hackage I somehow missed the castPtr function in the Foreign.Ptr package. I feel like an idiot, because with it the solution is really easy. As per Ilya's answer I just need to store the number as a Word32 (or DWORD), poke it into the pointer alloca gives me and then call castPtr on it before I pass it to regSetValueEx. Here's the modified code:

module Main where

import           Foreign.Marshal.Alloc
import           Foreign.Ptr
import           Foreign.Storable
import           System.Win32.Registry
import           System.Win32.Types

number :: DWORD
number = 42

getKey :: IO HKEY
getKey = regOpenKey hKEY_CURRENT_USER "test"

importFromDWORD :: IO ()
importFromDWORD = alloca $ \ptr -> do
                  poke ptr number
                  key <- getKey
                  regSetValueEx key "dword" rEG_DWORD (castPtr ptr) (sizeOf number)

main :: IO ()
main = importFromDWORD

Upvotes: 1

Views: 877

Answers (1)

Ilya Rezvov
Ilya Rezvov

Reputation: 944

Just define number as Word32 from Data.Word:

number :: Word32
number = 42

Also you can use sizeOf on normal value like: sizeOf number

Upvotes: 1

Related Questions