    {-# INCLUDE <windows.h> #-}
    {-# LINE 1 "System\Win32\Registry.hsc" #-}
    -----------------------------------------------------------------------------
    {-# LINE 2 "System\Win32\Registry.hsc" #-}
    -- |
    -- Module      :  System.Win32.Registry
    -- Copyright   :  (c) Alastair Reid, 1997-2003
    -- License     :  BSD-style (see the file libraries/base/LICENSE)
    --
    -- Maintainer  :  Esa Ilari Vuokko <ei@vuokko.info>
    -- Stability   :  provisional
    -- Portability :  portable
    --
    -- A collection of FFI declarations for accessing the Win32 registry.
    --
    -----------------------------------------------------------------------------

    module System.Win32.Registry
    		( module System.Win32.Registry
    		) where
    {- What's really on offer:
    	(
    	  regCloseKey        -- :: HKEY -> IO ()
    	, regConnectRegistry -- :: Maybe String -> HKEY -> IO HKEY
    	, regCreateKey       -- :: HKEY -> String -> IO HKEY
    	, regCreateKeyEx     -- :: HKEY -> String -> String
    	                     -- -> RegCreateOptions -> REGSAM
    			     -- -> Maybe LPSECURITY_ATTRIBUTES
    			     -- -> IO (HKEY, Bool)
            , regDeleteKey       -- :: HKEY -> String -> IO ()
    	, regDeleteValue     -- :: HKEY -> String -> IO ()
    	, regEnumKeys	     -- :: HKEY -> IO [String]
    	, regEnumKey 	     -- :: HKEY -> DWORD -> Addr -> DWORD -> IO String
    	, regEnumKeyValue    -- :: HKEY -> DWORD -> Addr -> DWORD -> Addr -> DWORD -> IO String
    	, regFlushKey        -- :: HKEY -> IO ()
    	, regLoadKey         -- :: HKEY -> String -> String -> IO ()
    	, regNotifyChangeKeyValue -- :: HKEY -> Bool -> RegNotifyOptions
    				  -- -> HANDLE -> Bool -> IO ()
    	, regOpenKey         -- :: HKEY -> String -> IO HKEY
    	, regOpenKeyEx 	     -- :: HKEY -> String -> REGSAM -> IO HKEY
    	, regQueryInfoKey    -- :: HKEY -> IO RegInfoKey
    	, regQueryValue      -- :: HKEY -> Maybe String -> IO String
    	, regQueryValueKey   -- :: HKEY -> Maybe String -> IO String
    	, regQueryValueEx    -- :: HKEY -> String -> Addr -> Int -> IO RegValueType
    	, regReplaceKey      -- :: HKEY -> String -> String -> String -> IO ()
    	, regRestoreKey      -- :: HKEY -> String -> RegRestoreFlags -> IO ()
    	, regSaveKey         -- :: HKEY -> String -> Maybe LPSECURITY_ATTRIBUTES -> IO ()
    	, regSetValue        -- :: HKEY -> String -> String -> IO ()
    	, regSetValueEx      -- :: HKEY -> String -> RegValueType -> LPTSTR -> Int -> IO ()
    	, regSetStringValue  -- :: HKEY -> String -> String -> IO ()
    	, regUnloadKey       -- :: HKEY -> String -> IO ()
    	) where
    -}

    {-
     Registry API omissions:

       RegQueryMultipleValues()
       RegEnumKeyEx()

    -}

    import System.Win32.Time
    import System.Win32.Types
    import System.Win32.File

    import Foreign

    {-# LINE 67 "System\Win32\Registry.hsc" #-}

    hKEY_CLASSES_ROOT     :: HKEY
    hKEY_CLASSES_ROOT     = (unsafePerformIO . newForeignHANDLE . castUINTToPtr) 2147483648
    hKEY_CURRENT_CONFIG   :: HKEY
    hKEY_CURRENT_CONFIG   = (unsafePerformIO . newForeignHANDLE . castUINTToPtr) 2147483653
    hKEY_CURRENT_USER     :: HKEY
    hKEY_CURRENT_USER     = (unsafePerformIO . newForeignHANDLE . castUINTToPtr) 2147483649
    hKEY_LOCAL_MACHINE    :: HKEY
    hKEY_LOCAL_MACHINE    = (unsafePerformIO . newForeignHANDLE . castUINTToPtr) 2147483650
    hKEY_USERS            :: HKEY
    hKEY_USERS            = (unsafePerformIO . newForeignHANDLE . castUINTToPtr) 2147483651

    {-# LINE 75 "System\Win32\Registry.hsc" #-}
    -- , PKEYERFORMANCE_DATA  NT only
    -- , HKEY_DYN_DATA     95/98 only

    regCloseKey :: HKEY -> IO ()
    regCloseKey key =
      withForeignPtr key $ \ p_key ->
      failUnlessSuccess "RegCloseKey" $ c_RegCloseKey p_key
    foreign import stdcall unsafe "windows.h RegCloseKey"
      c_RegCloseKey :: PKEY -> IO ErrCode

    -- Connects to a predefined registry handle on another computer.

    regConnectRegistry :: Maybe String -> HKEY -> IO HKEY
    regConnectRegistry mb_machine key =
      withForeignPtr key $ \ p_key ->
      maybeWith withTString mb_machine $ \ c_machine ->
      alloca $ \ p_out_key -> do
      failUnlessSuccess "RegConnectRegistry" $
        c_RegConnectRegistry c_machine p_key p_out_key
      p_new_key <- peek p_out_key
      newForeignHANDLE p_new_key
    foreign import stdcall unsafe "windows.h RegConnectRegistryW"
      c_RegConnectRegistry :: LPCTSTR -> PKEY -> Ptr PKEY -> IO ErrCode

    regCreateKey :: HKEY -> String -> IO HKEY
    regCreateKey key subkey =
      withForeignPtr key $ \ p_key ->
      withTString subkey $ \ c_subkey ->
      alloca $ \ p_out_key -> do
      failUnlessSuccess "RegCreateKey" $
        c_RegCreateKey p_key c_subkey p_out_key
      p_new_key <- peek p_out_key
      newForeignHANDLE p_new_key
    foreign import stdcall unsafe "windows.h RegCreateKeyW"
      c_RegCreateKey :: PKEY -> LPCTSTR -> Ptr PKEY -> IO ErrCode

    type RegCreateOptions = DWORD

    rEG_OPTION_NON_VOLATILE       :: RegCreateOptions
    rEG_OPTION_NON_VOLATILE       =  0
    rEG_OPTION_VOLATILE           :: RegCreateOptions
    rEG_OPTION_VOLATILE           =  1

    {-# LINE 117 "System\Win32\Registry.hsc" #-}

    type REGSAM = Word32
    {-# LINE 119 "System\Win32\Registry.hsc" #-}

    kEY_ALL_ACCESS        :: REGSAM
    kEY_ALL_ACCESS        =  983103
    kEY_CREATE_LINK       :: REGSAM
    kEY_CREATE_LINK       =  32
    kEY_CREATE_SUB_KEY    :: REGSAM
    kEY_CREATE_SUB_KEY    =  4
    kEY_ENUMERATE_SUB_KEYS  :: REGSAM
    kEY_ENUMERATE_SUB_KEYS  =  8
    kEY_EXECUTE           :: REGSAM
    kEY_EXECUTE           =  131097
    kEY_NOTIFY            :: REGSAM
    kEY_NOTIFY            =  16
    kEY_QUERY_VALUE       :: REGSAM
    kEY_QUERY_VALUE       =  1
    kEY_READ              :: REGSAM
    kEY_READ              =  131097
    kEY_SET_VALUE         :: REGSAM
    kEY_SET_VALUE         =  2
    kEY_WRITE             :: REGSAM
    kEY_WRITE             =  131078

    {-# LINE 132 "System\Win32\Registry.hsc" #-}

    regCreateKeyEx :: HKEY -> String -> String -> RegCreateOptions -> REGSAM -> Maybe LPSECURITY_ATTRIBUTES -> IO (HKEY, Bool)
    regCreateKeyEx key subkey cls opts sam mb_attr =
      withForeignPtr key $ \ p_key ->
      withTString subkey $ \ c_subkey ->
      withTString cls $ \ c_cls ->
      alloca $ \ p_res ->
      alloca $ \ p_disp -> do
      failUnlessSuccess "RegCreateKeyEx" $
        c_RegCreateKeyEx p_key c_subkey 0 c_cls opts sam (maybePtr mb_attr) p_res p_disp
      p_out_key <- peek p_res
      out_key <- newForeignHANDLE p_out_key
      disp <- peek p_disp
      return (out_key, disp == 1)
    {-# LINE 146 "System\Win32\Registry.hsc" #-}
    foreign import stdcall unsafe "windows.h RegCreateKeyExW"
      c_RegCreateKeyEx :: PKEY -> LPCTSTR -> DWORD -> LPCTSTR -> RegCreateOptions -> REGSAM -> LPSECURITY_ATTRIBUTES -> Ptr PKEY -> Ptr DWORD -> IO ErrCode

    regDeleteKey :: HKEY -> String -> IO ()
    regDeleteKey key subkey =
      withForeignPtr key $ \ p_key ->
      withTString subkey $ \ c_subkey ->
      failUnlessSuccess "RegDeleteKey" $ c_RegDeleteKey p_key c_subkey
    foreign import stdcall unsafe "windows.h RegDeleteKeyW"
      c_RegDeleteKey :: PKEY -> LPCTSTR -> IO ErrCode

    regDeleteValue :: HKEY -> String -> IO ()
    regDeleteValue key name =
      withForeignPtr key $ \ p_key ->
      withTString name $ \ c_name ->
      failUnlessSuccess "RegDeleteValue" $ c_RegDeleteValue p_key c_name
    foreign import stdcall unsafe "windows.h RegDeleteValueW"
      c_RegDeleteValue :: PKEY -> LPCTSTR -> IO ErrCode

    -- XXX Not 100% sure this is right, but I think it is.
    -- Surely this function already exists somewhere?
    mallocWideChars :: Int -> IO (Ptr a)
    mallocWideChars i = mallocBytes (4 * i)

    regEnumKeys :: HKEY -> IO [String]
    regEnumKeys hkey = do
       hinfo <- regQueryInfoKey hkey
       let buflen = 1+max_subkey_len hinfo
       buf   <- mallocWideChars (fromIntegral buflen)
       ls    <- go 0 buf buflen
       free buf
       return ls
     where
       go n buf buflen = do
          (v,flg)  <- regEnumKey hkey n buf buflen
          if flg /= 0
           then return []
           else do
             vs <- go (n+1) buf buflen
             return (v:vs)

    regEnumKeyVals :: HKEY -> IO [(String,String,RegValueType)]
    regEnumKeyVals hkey = do
       hinfo <- regQueryInfoKey hkey
       let nmlen  = 1+max_value_name_len hinfo  -- add spc for terminating NUL.
       let vallen = 1+max_value_len hinfo
       nmbuf  <- mallocWideChars (fromIntegral nmlen)
       valbuf <- mallocWideChars (fromIntegral vallen)
       ls     <- go 0 nmbuf nmlen valbuf vallen
       free nmbuf
       free valbuf
       return ls
     where
       go n nmbuf nmlen valbuf vallen = do
          (ty,nm,flg) <- regEnumValue hkey n nmbuf nmlen valbuf vallen
          if flg /= 0
           then return []
           else do

            val <-
    	   case ty of
    	     x | x == rEG_SZ    -> peekTString (castPtr valbuf)
    	       | x == rEG_DWORD -> peekElemOff (castPtr valbuf) 0 >>= \ v -> return (show (v :: DWORD))
    	       | otherwise      -> return "<<unknown>>"

            vs <- go (n+1) nmbuf nmlen valbuf vallen
            return ((nm,val,ty):vs)

    -- It's up to the programmer to ensure that a large enough
    -- buffer is passed in here.

    regEnumKey :: HKEY -> DWORD -> LPTSTR -> DWORD -> IO (String, Int)
    regEnumKey key index c_name len =
      withForeignPtr key $ \ p_key -> do
      no_more <- failUnlessSuccessOr eRROR_NO_MORE_ITEMS "RegEnumKey" $
        c_RegEnumKey p_key index c_name len
      str <- peekTString c_name
      return (str, fromEnum no_more)
    foreign import stdcall unsafe "windows.h RegEnumKeyW"
      c_RegEnumKey :: PKEY -> DWORD -> LPTSTR -> DWORD -> IO ErrCode

    regEnumValue :: HKEY -> DWORD -> LPTSTR -> DWORD -> LPBYTE -> DWORD -> IO (RegValueType, String, Int)
    regEnumValue key index name name_len value value_len =
      withForeignPtr key $ \ p_key ->
      with name_len $ \ p_name_len ->
      with value_len $ \ p_value_len ->
      alloca $ \ p_reg_ty -> do
      no_more <- failUnlessSuccessOr eRROR_NO_MORE_ITEMS "RegEnumValue" $
        c_RegEnumValue p_key index name p_name_len nullPtr p_reg_ty value p_value_len
      reg_ty <- peek p_reg_ty
      str <- peekTString name
      return (reg_ty, str, fromEnum no_more)
    foreign import stdcall unsafe "windows.h RegEnumValueW"
      c_RegEnumValue :: PKEY -> DWORD -> LPTSTR -> Ptr DWORD -> Ptr DWORD -> Ptr DWORD -> LPBYTE -> Ptr DWORD -> IO ErrCode

    eRROR_NO_MORE_ITEMS :: ErrCode
    eRROR_NO_MORE_ITEMS = 259
    {-# LINE 243 "System\Win32\Registry.hsc" #-}

    regFlushKey :: HKEY -> IO ()
    regFlushKey key =
      withForeignPtr key $ \ p_key ->
      failUnlessSuccess "RegFlushKey" $ c_RegFlushKey p_key
    foreign import stdcall unsafe "windows.h RegFlushKey"
      c_RegFlushKey :: PKEY -> IO ErrCode

    -- ifdef FOR_WINDOWS_NT
    -- RegGetKeySecurity :: HKEY -> SECURITY_INFORMATION -> IO SECURITY_DESCRIPTION

    -- endif

    regLoadKey :: HKEY -> String -> String -> IO ()
    regLoadKey key subkey file =
      withForeignPtr key $ \ p_key ->
      withTString subkey $ \ c_subkey ->
      withTString file $ \ c_file ->
      failUnlessSuccess "RegLoadKey" $ c_RegLoadKey p_key c_subkey c_file
    foreign import stdcall unsafe "windows.h RegLoadKeyW"
      c_RegLoadKey :: PKEY -> LPCTSTR -> LPCTSTR -> IO ErrCode

    -- ifdef FOR_WINDOWS_NT

    type RegNotifyOptions = DWORD

    rEG_NOTIFY_CHANGE_NAME        :: RegNotifyOptions
    rEG_NOTIFY_CHANGE_NAME        =  1
    rEG_NOTIFY_CHANGE_ATTRIBUTES  :: RegNotifyOptions
    rEG_NOTIFY_CHANGE_ATTRIBUTES  =  2
    rEG_NOTIFY_CHANGE_LAST_SET    :: RegNotifyOptions
    rEG_NOTIFY_CHANGE_LAST_SET    =  4
    rEG_NOTIFY_CHANGE_SECURITY    :: RegNotifyOptions
    rEG_NOTIFY_CHANGE_SECURITY    =  8

    {-# LINE 275 "System\Win32\Registry.hsc" #-}

    regNotifyChangeKeyValue :: HKEY -> Bool -> RegNotifyOptions -> HANDLE -> Bool -> IO ()
    regNotifyChangeKeyValue key watch notifyFilter event async =
      withForeignPtr key $ \ p_key ->
      failUnlessSuccess "RegNotifyChangeKeyValue" $
        c_RegNotifyChangeKeyValue p_key watch notifyFilter event async
    foreign import stdcall unsafe "windows.h RegNotifyChangeKeyValue"
      c_RegNotifyChangeKeyValue :: PKEY -> Bool -> RegNotifyOptions -> HANDLE -> Bool -> IO ErrCode

    -- endif

    -- for Win 3.x compatibility, use RegOpenKeyEx instead.

    regOpenKey :: HKEY -> String -> IO HKEY
    regOpenKey key subkey =
      withForeignPtr key $ \ p_key ->
      withTString subkey $ \ c_subkey ->
      alloca $ \ p_res -> do
      failUnlessSuccess "RegOpenKey" $ c_RegOpenKey p_key c_subkey p_res
      p_res_key <- peek p_res
      newForeignHANDLE p_res_key
    foreign import stdcall unsafe "windows.h RegOpenKeyW"
      c_RegOpenKey :: PKEY -> LPCTSTR -> Ptr PKEY -> IO ErrCode

    regOpenKeyEx :: HKEY -> String -> REGSAM -> IO HKEY
    regOpenKeyEx key subkey sam =
      withForeignPtr key $ \ p_key ->
      withTString subkey $ \ c_subkey ->
      alloca $ \ p_res -> do
      failUnlessSuccess "RegOpenKeyEx" $ c_RegOpenKeyEx p_key c_subkey 0 sam p_res
      p_res_key <- peek p_res
      newForeignHANDLE p_res_key
    foreign import stdcall unsafe "windows.h RegOpenKeyExW"
      c_RegOpenKeyEx :: PKEY -> LPCTSTR -> DWORD -> REGSAM -> Ptr PKEY -> IO ErrCode

    data RegInfoKey =
      RegInfoKey {
        class_string       :: String,
        class_id           :: Int,
        subkeys            :: Word32,
        max_subkey_len     :: Word32,
        max_class_len      :: Word32,
        values             :: Word32,
        max_value_name_len :: Word32,
        max_value_len      :: Word32,
        sec_len            :: Int,
        lastWrite_lo       :: Word32,
        lastWrite_hi       :: Word32
      }

    regQueryInfoKey :: HKEY -> IO RegInfoKey
    regQueryInfoKey key =
      withForeignPtr key $ \ p_key ->
      allocaBytes 100 $ \ c_class_string ->
      alloca $ \ p_class_id ->
      alloca $ \ p_subkeys ->
      alloca $ \ p_max_subkey_len ->
      alloca $ \ p_max_class_len ->
      alloca $ \ p_values ->
      alloca $ \ p_max_value_name_len ->
      alloca $ \ p_max_value_len ->
      alloca $ \ p_sec_len ->
      allocaBytes ((8)) $ \ p_lastWrite -> do
    {-# LINE 338 "System\Win32\Registry.hsc" #-}
      failUnlessSuccess "RegQueryInfoKey" $
        c_RegQueryInfoKey p_key c_class_string p_class_id nullPtr p_subkeys
            p_max_subkey_len p_max_class_len p_values p_max_value_name_len
            p_max_value_len p_sec_len p_lastWrite
      class_string <- peekTString c_class_string
      class_id <- peek p_class_id
      subkeys <- peek p_subkeys
      max_subkey_len <- peek p_max_subkey_len
      max_class_len <- peek p_max_class_len
      values <- peek p_values
      max_value_name_len <- peek p_max_value_name_len
      max_value_len <- peek p_max_value_len
      sec_len <- peek p_sec_len
      lastWrite_lo <- (\hsc_ptr -> peekByteOff hsc_ptr 0) p_lastWrite
    {-# LINE 352 "System\Win32\Registry.hsc" #-}
      lastWrite_hi <- (\hsc_ptr -> peekByteOff hsc_ptr 4) p_lastWrite
    {-# LINE 353 "System\Win32\Registry.hsc" #-}
      return $ RegInfoKey
        { class_string = class_string
        , class_id = fromIntegral class_id
        , subkeys = subkeys
        , max_subkey_len = max_subkey_len
        , max_class_len = max_class_len
        , values = values
        , max_value_name_len = max_value_name_len
        , max_value_len = max_value_len
        , sec_len = fromIntegral sec_len
        , lastWrite_lo = lastWrite_lo
        , lastWrite_hi = lastWrite_hi
        }
    foreign import stdcall unsafe "windows.h RegQueryInfoKeyW"
      c_RegQueryInfoKey :: PKEY -> LPTSTR -> Ptr DWORD -> Ptr DWORD -> Ptr DWORD -> Ptr DWORD -> Ptr DWORD -> Ptr DWORD -> Ptr DWORD -> Ptr DWORD -> Ptr DWORD -> Ptr FILETIME -> IO ErrCode

    -- RegQueryMultipleValues :: HKEY -> IO ([VALENT],String)

    -- RegQueryValue() isn't really that, it just allows you to
    -- get at the default values of keys, so we provide our own
    -- (and better!) version of it. If you want RegQueryValue()s
    -- behaviour, use regQueryValueKey.

    regQueryValueKey :: HKEY -> Maybe String -> IO String
    regQueryValueKey key mb_subkey =
      withForeignPtr key $ \ p_key ->
      maybeWith withTString mb_subkey $ \ c_subkey ->
      alloca $ \ p_value_len -> do
      failUnlessSuccess "RegQueryValue" $
        c_RegQueryValue p_key c_subkey nullPtr p_value_len
      value_len <- peek p_value_len
      allocaArray0 (fromIntegral value_len) $ \ c_value -> do
        failUnlessSuccess "RegQueryValue" $
          c_RegQueryValue p_key c_subkey c_value p_value_len
        peekTString c_value
    foreign import stdcall unsafe "windows.h RegQueryValueW"
      c_RegQueryValue :: PKEY -> LPCTSTR -> LPTSTR -> Ptr LONG -> IO ErrCode

    regQueryValue :: HKEY -> Maybe String -> IO String
    regQueryValue key mb_subkey =
      withForeignPtr key $ \ p_key ->
      maybeWith withTString mb_subkey $ \ c_subkey ->
      alloca $ \ p_ty ->
      alloca $ \ p_value_len -> do
      failUnlessSuccess "RegQueryValue" $
        c_RegQueryValueEx p_key c_subkey nullPtr p_ty nullPtr p_value_len
      ty <- peek p_ty
      failUnlessSuccess "RegQueryValue" $ return (if ty == rEG_SZ then 0 else 1)
      value_len <- peek p_value_len
      allocaArray0 (fromIntegral value_len) $ \ c_value -> do
        failUnlessSuccess "RegQueryValue" $
          c_RegQueryValueEx p_key c_subkey nullPtr p_ty c_value p_value_len
        peekTString (castPtr c_value)

    regQueryValueEx :: HKEY -> String -> LPBYTE -> Int -> IO RegValueType
    regQueryValueEx key name value value_len =
      withForeignPtr key $ \ p_key ->
      withTString name $ \ c_name ->
      alloca $ \ p_ty ->
      with (fromIntegral value_len) $ \ p_value_len -> do
      failUnlessSuccess "RegQueryValueEx" $
        c_RegQueryValueEx p_key c_name nullPtr p_ty value p_value_len
      peek p_ty
    foreign import stdcall unsafe "windows.h RegQueryValueExW"
      c_RegQueryValueEx :: PKEY -> LPCTSTR -> Ptr DWORD -> Ptr DWORD -> LPBYTE -> Ptr DWORD -> IO ErrCode

    regReplaceKey :: HKEY -> String -> String -> String -> IO ()
    regReplaceKey key subkey newfile oldfile =
      withForeignPtr key $ \ p_key ->
      withTString subkey $ \ c_subkey ->
      withTString newfile $ \ c_newfile ->
      withTString oldfile $ \ c_oldfile ->
      failUnlessSuccess "RegReplaceKey" $
        c_RegReplaceKey p_key c_subkey c_newfile c_oldfile
    foreign import stdcall unsafe "windows.h RegReplaceKeyW"
      c_RegReplaceKey :: PKEY -> LPCTSTR -> LPCTSTR -> LPCTSTR -> IO ErrCode

    type RegRestoreFlags = DWORD

    rEG_WHOLE_HIVE_VOLATILE  :: RegRestoreFlags
    rEG_WHOLE_HIVE_VOLATILE  =  1
    rEG_REFRESH_HIVE      :: RegRestoreFlags
    rEG_REFRESH_HIVE      =  2
    rEG_NO_LAZY_FLUSH     :: RegRestoreFlags
    rEG_NO_LAZY_FLUSH     =  4

    {-# LINE 437 "System\Win32\Registry.hsc" #-}

    regRestoreKey :: HKEY -> String -> RegRestoreFlags -> IO ()
    regRestoreKey key file flags =
      withForeignPtr key $ \ p_key ->
      withTString file $ \ c_file ->
      failUnlessSuccess "RegRestoreKey" $ c_RegRestoreKey p_key c_file flags
    foreign import stdcall unsafe "windows.h RegRestoreKeyW"
      c_RegRestoreKey :: PKEY -> LPCTSTR -> RegRestoreFlags -> IO ErrCode

    regSaveKey :: HKEY -> String -> Maybe LPSECURITY_ATTRIBUTES -> IO ()
    regSaveKey key file mb_attr =
      withForeignPtr key $ \ p_key ->
      withTString file $ \ c_file ->
      failUnlessSuccess "RegSaveKey" $ c_RegSaveKey p_key c_file (maybePtr mb_attr)
    foreign import stdcall unsafe "windows.h RegSaveKeyW"
      c_RegSaveKey :: PKEY -> LPCTSTR -> LPSECURITY_ATTRIBUTES -> IO ErrCode

    -- ifdef FOR_WINDOWS_NT

    -- RegSetKeySecurity :: HKEY -> SECURITY_INFORMATION -> SECURITY_DESCRIPTOR -> IO ()

    -- endif

    -- 3.1 compat. - only allows storage of REG_SZ values.

    regSetValue :: HKEY -> String -> String -> IO ()
    regSetValue key subkey value =
      withForeignPtr key $ \ p_key ->
      withTString subkey $ \ c_subkey ->
      withTStringLen value $ \ (c_value, value_len) ->
      failUnlessSuccess "RegSetValue" $
        c_RegSetValue p_key c_subkey rEG_SZ c_value value_len
    foreign import stdcall unsafe "windows.h RegSetValueW"
      c_RegSetValue :: PKEY -> LPCTSTR -> DWORD -> LPCTSTR -> Int -> IO ErrCode

    type RegValueType = DWORD

    rEG_BINARY            :: RegValueType
    rEG_BINARY            =  3
    rEG_DWORD             :: RegValueType
    rEG_DWORD             =  4
    rEG_DWORD_LITTLE_ENDIAN  :: RegValueType
    rEG_DWORD_LITTLE_ENDIAN  =  4
    rEG_DWORD_BIG_ENDIAN  :: RegValueType
    rEG_DWORD_BIG_ENDIAN  =  5
    rEG_EXPAND_SZ         :: RegValueType
    rEG_EXPAND_SZ         =  2
    rEG_LINK              :: RegValueType
    rEG_LINK              =  6
    rEG_MULTI_SZ          :: RegValueType
    rEG_MULTI_SZ          =  7
    rEG_NONE              :: RegValueType
    rEG_NONE              =  0
    rEG_RESOURCE_LIST     :: RegValueType
    rEG_RESOURCE_LIST     =  8
    rEG_SZ                :: RegValueType
    rEG_SZ                =  1

    {-# LINE 487 "System\Win32\Registry.hsc" #-}

    -- regSetValueEx has a somewhat wieldly interface if all you want to do is
    -- add a string value (a Common Thing to want to do), so we support this
    -- specially:
    regSetStringValue :: HKEY -> String -> String -> IO ()
    regSetStringValue hk key val =
      withTString val $ \ v ->
      regSetValueEx hk key rEG_SZ v (length val)

    regSetValueEx :: HKEY -> String -> RegValueType -> LPTSTR -> Int -> IO ()
    regSetValueEx key subkey ty value value_len =
      withForeignPtr key $ \ p_key ->
      withTString subkey $ \ c_subkey ->
      failUnlessSuccess "RegSetValueEx" $
        c_RegSetValueEx p_key c_subkey 0 ty value value_len
    foreign import stdcall unsafe "windows.h RegSetValueExW"
      c_RegSetValueEx :: PKEY -> LPCTSTR -> DWORD -> RegValueType -> LPTSTR -> Int -> IO ErrCode

    regUnLoadKey :: HKEY -> String -> IO ()
    regUnLoadKey key subkey =
      withForeignPtr key $ \ p_key ->
      withTString subkey $ \ c_subkey ->
      failUnlessSuccess "RegUnLoadKey" $ c_RegUnLoadKey p_key c_subkey
    foreign import stdcall unsafe "windows.h RegUnLoadKeyW"
      c_RegUnLoadKey :: PKEY -> LPCTSTR -> IO ErrCode