diff --git a/Codec/Compression/Zlib/Stream.hsc b/Codec/Compression/Zlib/Stream.hsc
--- a/Codec/Compression/Zlib/Stream.hsc
+++ b/Codec/Compression/Zlib/Stream.hsc
@@ -1,6 +1,7 @@
+{-# OPTIONS_GHC -fno-warn-missing-methods #-}
 -----------------------------------------------------------------------------
 -- |
--- Copyright   :  (c) 2006 Duncan Coutts
+-- Copyright   :  (c) 2006-2008 Duncan Coutts
 -- License     :  BSD-style
 --
 -- Maintainer  :  duncan.coutts@worc.ox.ac.uk
@@ -251,6 +252,7 @@
 run :: Stream a -> a
 run (Z m) = unsafePerformIO $ do
   ptr <- mallocBytes (#{const sizeof(z_stream)})
+  #{poke z_stream, msg}       ptr nullPtr
   #{poke z_stream, zalloc}    ptr nullPtr
   #{poke z_stream, zfree}     ptr nullPtr
   #{poke z_stream, opaque}    ptr nullPtr
@@ -375,16 +377,24 @@
   toEnum (#{const Z_BUF_ERROR})  = BufferError
   toEnum other = error ("unexpected zlib status: " ++ show other)
 
-isFatalError :: CInt -> Bool
-isFatalError n | n >= 0             = False
-isFatalError (#{const Z_BUF_ERROR}) = False
-isFatalError _                      = True
+failIfError :: CInt -> Stream ()
+failIfError errno
+  | errno >= 0
+ || errno == #{const Z_BUF_ERROR} = return ()
+  | otherwise                     = fail =<< getErrorMessage errno
 
-throwError :: Stream a
-throwError = do
-  msg <- withStreamPtr (#{peek z_stream, msg})
-  msg' <- unsafeLiftIO (peekCString msg)
-  fail msg'
+getErrorMessage :: CInt -> Stream String
+getErrorMessage errno = do
+  msgPtr <- withStreamPtr (#{peek z_stream, msg})
+  if msgPtr /= nullPtr
+    then unsafeLiftIO (peekCString msgPtr)
+    else return $ case errno of
+      #{const Z_ERRNO}         -> "file error"
+      #{const Z_STREAM_ERROR}  -> "stream error"
+      #{const Z_DATA_ERROR}    -> "data error"
+      #{const Z_MEM_ERROR}     -> "insufficient memory"
+      #{const Z_VERSION_ERROR} -> "incompatible version"
+      _                        -> "unknown error"
 
 data Flush =
     NoFlush
@@ -507,6 +517,11 @@
   stream <- getStreamState
   unsafeLiftIO (withForeignPtr stream f)
 
+withStreamState :: (StreamState -> IO a) -> Stream a
+withStreamState f = do
+  stream <- getStreamState
+  unsafeLiftIO (withForeignPtr stream (f . StreamState))
+
 setInAvail :: Int -> Stream ()
 setInAvail val = withStreamPtr $ \ptr ->
   #{poke z_stream, avail_in} ptr (fromIntegral val :: CUInt)
@@ -537,12 +552,10 @@
 
 inflateInit :: Format -> WindowBits -> Stream ()
 inflateInit format bits = do
-  err <- withStreamPtr $ \ptr ->
-    c_inflateInit2 ptr (fromIntegral (windowBits format bits))
-  if isFatalError err
-    then throwError
-    else do stream <- getStreamState
-            unsafeLiftIO $ addForeignPtrFinalizer c_inflateEnd stream
+  err <- withStreamState $ \zstream ->
+    c_inflateInit2 zstream (fromIntegral (windowBits format bits))
+  failIfError err
+  getStreamState >>= unsafeLiftIO . addForeignPtrFinalizer c_inflateEnd
 
 deflateInit :: Format
             -> CompressionLevel
@@ -552,31 +565,29 @@
             -> CompressionStrategy
             -> Stream ()
 deflateInit format compLevel method bits memLevel strategy = do
-  err <- withStreamPtr $ \ptr ->
-    c_deflateInit2 ptr
+  err <- withStreamState $ \zstream ->
+    c_deflateInit2 zstream
                   (fromIntegral (fromEnum compLevel))
                   (fromIntegral (fromEnum method))
                   (fromIntegral (windowBits format bits))
                   (fromIntegral (fromEnum memLevel))
                   (fromIntegral (fromEnum strategy))
-  if isFatalError err
-    then throwError
-    else do stream <- getStreamState
-            unsafeLiftIO $ addForeignPtrFinalizer c_deflateEnd stream
+  failIfError err
+  getStreamState >>= unsafeLiftIO . addForeignPtrFinalizer c_deflateEnd
 
 inflate_ :: Flush -> Stream Status
 inflate_ flush = do
-  err <- withStreamPtr (\ptr -> c_inflate ptr (fromIntegral (fromEnum flush)))
-  if isFatalError err
-    then throwError
-    else return (toEnum (fromIntegral err))
+  err <- withStreamState $ \zstream ->
+    c_inflate zstream (fromIntegral (fromEnum flush))
+  failIfError err
+  return (toEnum (fromIntegral err))
 
 deflate_ :: Flush -> Stream Status
 deflate_ flush = do
-  err <- withStreamPtr (\ptr -> c_deflate ptr (fromIntegral (fromEnum flush)))
-  if isFatalError err
-    then throwError
-    else return (toEnum (fromIntegral err))
+  err <- withStreamState $ \zstream ->
+    c_deflate zstream (fromIntegral (fromEnum flush))
+  failIfError err
+  return (toEnum (fromIntegral err))
 
 -- | This never needs to be used as the stream's resources will be released
 -- automatically when no longer needed, however this can be used to release
@@ -589,24 +600,24 @@
 ----------------------
 -- The foreign imports
 
-data StreamState = StreamState ()
+newtype StreamState = StreamState (Ptr StreamState)
 
 foreign import ccall unsafe "zlib.h inflateInit2"
-  c_inflateInit2 :: Ptr StreamState -> CInt -> IO CInt
+  c_inflateInit2 :: StreamState -> CInt -> IO CInt
 
 foreign import ccall unsafe "zlib.h inflate"
-  c_inflate :: Ptr StreamState -> CInt -> IO CInt
+  c_inflate :: StreamState -> CInt -> IO CInt
 
 foreign import ccall unsafe "zlib.h &inflateEnd"
   c_inflateEnd :: FinalizerPtr StreamState
 
 
 foreign import ccall unsafe "zlib.h deflateInit2"
-  c_deflateInit2 :: Ptr StreamState
+  c_deflateInit2 :: StreamState
                  -> CInt -> CInt -> CInt -> CInt -> CInt -> IO CInt
 
 foreign import ccall unsafe "zlib.h deflate"
-  c_deflate :: Ptr StreamState -> CInt -> IO CInt
+  c_deflate :: StreamState -> CInt -> IO CInt
 
 foreign import ccall unsafe "zlib.h &deflateEnd"
   c_deflateEnd :: FinalizerPtr StreamState
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2006-2007, Duncan Coutts
+Copyright (c) 2006-2008, Duncan Coutts
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/gunzip.hs b/gunzip.hs
new file mode 100644
--- /dev/null
+++ b/gunzip.hs
@@ -0,0 +1,6 @@
+module Main where
+
+import qualified Data.ByteString.Lazy as B
+import qualified Codec.Compression.GZip as GZip
+
+main = B.interact GZip.decompress
diff --git a/gzip.hs b/gzip.hs
new file mode 100644
--- /dev/null
+++ b/gzip.hs
@@ -0,0 +1,6 @@
+module Main where
+
+import qualified Data.ByteString.Lazy as B
+import qualified Codec.Compression.GZip as GZip
+
+main = B.interact GZip.compress
diff --git a/zlib.cabal b/zlib.cabal
--- a/zlib.cabal
+++ b/zlib.cabal
@@ -1,17 +1,29 @@
 name:            zlib
-version:         0.4.0.2
-copyright:       (c) 2006-2007 Duncan Coutts
+version:         0.4.0.3
+copyright:       (c) 2006-2008 Duncan Coutts
 license:         BSD3
 license-file:    LICENSE
 author:          Duncan Coutts <duncan@haskell.org>
 maintainer:      Duncan Coutts <duncan@haskell.org>
+category:        Codec
 synopsis:        Compression and decompression in the gzip and zlib formats
+description:     This package provides a pure interface for compressing and 
+                 decompressing streams of data represented as lazy 
+                 'ByteString's. It uses the zlib C library so it has high
+                 performance. It supports the \"zlib\", \"gzip\" and \"raw\"
+                 compression formats.
+                 .
+                 It provides a convenient high level api suitable for most
+                 tasks and for the few cases where more control is needed it
+                 provides access to the full zlib feature set.
 stability:       provisional
 build-type:      Simple
 cabal-version:   >= 1.2.1
 extra-source-files: cbits/crc32.h cbits/inffast.h cbits/inflate.h
                     cbits/trees.h cbits/deflate.h cbits/inffixed.h
                     cbits/inftrees.h cbits/zutil.h
+                    -- demo programs:
+                    gzip.hs gunzip.hs
 
 flag bytestring-in-base
   description: In the ghc-6.6 era the bytestring modules were
@@ -27,11 +39,11 @@
   if flag(bytestring-in-base)
     -- bytestring was in base-2.0 and 2.1.1
     build-depends: base >= 2.0 && < 2.2
-    cpp-options:  -DBYTESTRING_IN_BASE
+    cpp-options: -DBYTESTRING_IN_BASE
   else
     build-depends: base < 2.0 || >= 2.2, bytestring >= 0.9
   includes:        zlib.h
-  ghc-options:     -fvia-C
+  ghc-options:     -Wall
   if !os(windows)
     -- Normally we use the the standard system zlib:
     extra-libraries: z
