    module Network.HostName (
        HostName, getHostName
      ) where

    import Foreign.C.Error
    import Foreign.C.String
    import Foreign.C.Types
    import Foreign.Marshal.Array

    #ifdef WINDOWS

    import Foreign.Marshal.Utils
    import Foreign.Ptr
    import Foreign.Storable

    import System.Win32.Types

    foreign import stdcall unsafe "windows.h GetComputerNameExW" getComputerNameEx :: COMPUTER_NAME_FORMAT -> LPTSTR -> LPDWORD -> IO BOOL

    type COMPUTER_NAME_FORMAT = CInt

    computerNamePhysicalDnsHostname :: COMPUTER_NAME_FORMAT
    computerNamePhysicalDnsHostname = 5

    getHostName :: IO HostName
    getHostName = with 0 $ \p_charcount -> do
        -- On the first run, determine the character count and ignore any error we get
        _ <- getComputerNameEx computerNamePhysicalDnsHostname nullPtr p_charcount
        charcount <- peek p_charcount

        -- The second time around, use the correct character count to retrieve the data
        withTString (replicate (fromIntegral charcount) ' ') $ \name -> do
            failIfFalse_ "GetComputerNameExW" $ getComputerNameEx computerNamePhysicalDnsHostname name p_charcount
            peekTString name

    #else

    foreign import ccall unsafe "gethostname" gethostname :: CString -> CSize -> IO CInt

    getHostName :: IO HostName
    getHostName :: IO HostName
    getHostName = Int -> (Ptr CChar -> IO HostName) -> IO HostName
    forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
    allocaArray0 Int
    size ((Ptr CChar -> IO HostName) -> IO HostName)
    -> (Ptr CChar -> IO HostName) -> IO HostName
    forall a b. (a -> b) -> a -> b
    $ \Ptr CChar
    cstr -> do
            HostName -> IO CInt -> IO ()
    forall a. (Eq a, Num a) => HostName -> IO a -> IO ()
    throwErrnoIfMinus1_ HostName
    "getHostName" (IO CInt -> IO ()) -> IO CInt -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Ptr CChar -> CSize -> IO CInt
    gethostname Ptr CChar
    cstr (Int -> CSize
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    size)
            Ptr CChar -> IO HostName
    peekCString Ptr CChar
    cstr
        where size :: Int
    size = Int
    256

    #endif

    type HostName = String