packages feed

dpapi-0.1.0.0: src/System/Win32/Dpapi/Internal.hs

{-
 - This Source Code Form is subject to the terms of the Mozilla Public
 - License, v. 2.0. If a copy of the MPL was not distributed with this
 - file, You can obtain one at https://mozilla.org/MPL/2.0/.
 -}

-- | You probably do not need these, they are only exposed for the benefit of testing.
module System.Win32.Dpapi.Internal (DataBlob (..), withBlobFromByteString, byteStringFromBlob) where

import Data.ByteString
import Foreign.Ptr (Ptr, alignPtr, castPtr, minusPtr, nullPtr, plusPtr)
import Foreign.Storable (Storable (..))
import System.Win32.Types (BYTE, DWORD)

-- | The struct that is passed to the C functions, a length and a pointer to bytes.
data DataBlob = DataBlob
  { cbData :: DWORD,
    pbData :: Ptr BYTE
  }

instance Storable DataBlob where
  sizeOf _ = offsetOfPbData + sizeOf (undefined :: Ptr BYTE)
  alignment _ = max (alignment (undefined :: Ptr BYTE)) (alignment (undefined :: DWORD))
  peek ptr = do
    size <- peekByteOff ptr 0
    bytes <- peekByteOff ptr offsetOfPbData
    pure $ DataBlob size bytes
  poke ptr (DataBlob size bytes) = do
    pokeByteOff ptr 0 size
    pokeByteOff ptr offsetOfPbData bytes

offsetOfPbData :: Int
offsetOfPbData = (nullPtr `plusPtr` (sizeOf (undefined :: DWORD) + 1)) `alignPtr` alignment (undefined :: Ptr BYTE) `minusPtr` nullPtr

withBlobFromByteString :: ByteString -> (DataBlob -> IO a) -> IO a
withBlobFromByteString bs with =
  useAsCStringLen bs (\(ptr, len) -> with $ DataBlob (fromIntegral len) (castPtr ptr))

byteStringFromBlob :: DataBlob -> IO ByteString
byteStringFromBlob (DataBlob len ptr) = packCStringLen (castPtr ptr, fromIntegral len)