diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.markdown
@@ -0,0 +1,36 @@
+0.3.4
+=====
+
+  * Provided `hSize` on Windows. (https://github.com/biegunka/terminal-size/pull/18)
+
+0.3.3
+=====
+
+  * Fixed ioctl foreign import. (https://github.com/biegunka/terminal-size/pull/16)
+
+  * `#alignment` is a hsc2hs built-in since some unspecified GHC 7.x. (https://github.com/biegunka/terminal-size/pull/12)
+
+  * Captured possible `stty` stderr output with a pipe. (https://github.com/biegunka/terminal-size/pull/13)
+
+
+0.3.2.1
+=======
+
+  * GHC 7.2 support (https://github.com/biegunka/terminal-size/pull/9)
+
+0.3.2
+=====
+
+  * Cygwin/MSYS support (https://github.com/biegunka/terminal-size/pull/8)
+
+0.3.1
+=====
+
+  * `Typeable`, `Data`, `Generic`, and `Generic1` instances for `Window`.
+
+0.3.0
+=====
+
+  * Windows support (https://github.com/biegunka/terminal-size/pull/4)
+
+  * Added `Eq`, `Foldable` and `Traversable` instances for `Window`
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2013, Matvey Aksenov
+Copyright (c) 2013-2015, Matvey Aksenov
 
 All rights reserved.
 
diff --git a/README.markdown b/README.markdown
new file mode 100644
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,57 @@
+terminal-size
+=============
+
+[![Hackage](https://img.shields.io/hackage/v/terminal-size.svg?style=flat)](https://hackage.haskell.org/package/terminal-size)
+[![Build Status](https://travis-ci.org/biegunka/terminal-size.png)](https://travis-ci.org/biegunka/terminal-size)
+
+Get terminal window width and height
+
+Usage
+-----
+
+```
+>>> import System.Console.Terminal.Size
+>>> size
+Just (Window {height = 60, width = 112})
+```
+
+Test
+----
+
+Compile test.hs and run it in a terminal. Here is what I get on Linux:
+
+```
+> ghc test.hs
+> ./test
+With redirected stdin
+  hSize stdin = Nothing
+  hSize stdout = Just (Window {height = 19, width = 87})
+  hSize stderr = Just (Window {height = 19, width = 87})
+With redirected stdout
+  hSize stdin = Just (Window {height = 19, width = 87})
+  hSize stdout = Nothing
+  hSize stderr = Just (Window {height = 19, width = 87})
+With redirected stderr
+  hSize stdin = Just (Window {height = 19, width = 87})
+  hSize stdout = Just (Window {height = 19, width = 87})
+  hSize stderr = Nothing
+```
+
+On MINGW/MSYS the output is the same.
+
+On Windows with cmd.exe I get
+
+```
+With redirected stdin
+  hSize stdin = Nothing
+  hSize stdout = Just (Window {height = 40, width = 164})
+  hSize stderr = Just (Window {height = 40, width = 164})
+With redirected stdout
+  hSize stdin = Nothing
+  hSize stdout = Nothing
+  hSize stderr = Just (Window {height = 40, width = 164})
+With redirected stderr
+  hSize stdin = Nothing
+  hSize stdout = Just (Window {height = 40, width = 164})
+  hSize stderr = Nothing
+```
diff --git a/src/System/Console/Terminal/Common.hs b/src/System/Console/Terminal/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/System/Console/Terminal/Common.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveFoldable #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE DeriveTraversable #-}
+
+#if __GLASGOW_HASKELL__ >= 702
+#define LANGUAGE_DeriveGeneric
+{-# LANGUAGE DeriveGeneric #-}
+#endif
+
+module System.Console.Terminal.Common
+  ( Window(..)
+  ) where
+
+import Data.Data (Typeable, Data)
+
+#if __GLASGOW_HASKELL__ < 710
+import Data.Foldable (Foldable)
+import Data.Traversable (Traversable)
+#endif
+
+#ifdef LANGUAGE_DeriveGeneric
+import GHC.Generics
+  ( Generic
+#if __GLASGOW_HASKELL__ >= 706
+  , Generic1
+#endif
+  )
+#endif
+
+-- | Terminal window width and height
+data Window a = Window
+  { height :: !a
+  , width  :: !a
+  } deriving
+    ( Show, Eq, Read, Data, Typeable
+    , Foldable, Functor, Traversable
+#ifdef LANGUAGE_DeriveGeneric
+    , Generic
+#if __GLASGOW_HASKELL__ >= 706
+    , Generic1
+#endif
+#endif
+    )
diff --git a/src/System/Console/Terminal/Posix.hsc b/src/System/Console/Terminal/Posix.hsc
new file mode 100644
--- /dev/null
+++ b/src/System/Console/Terminal/Posix.hsc
@@ -0,0 +1,65 @@
+{-# LANGUAGE CApiFFI #-}
+
+module System.Console.Terminal.Posix
+  ( size, fdSize, hSize
+  ) where
+
+import System.Console.Terminal.Common
+import Control.Exception (catch)
+import Data.Typeable (cast)
+import Foreign
+import Foreign.C.Error
+import Foreign.C.Types
+import GHC.IO.FD (FD(FD, fdFD))
+import GHC.IO.Handle.Internals (withHandle_)
+import GHC.IO.Handle.Types (Handle, Handle__(Handle__, haDevice))
+#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 706)
+import Prelude hiding (catch)
+#endif
+import System.Posix.Types (Fd(Fd))
+
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 800)
+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
+#endif
+
+-- Interesting part of @struct winsize@
+data CWin = CWin CUShort CUShort
+
+instance Storable CWin where
+  sizeOf _ = (#size struct winsize)
+  alignment _ = (#alignment struct winsize)
+  peek ptr = do
+    row <- (#peek struct winsize, ws_row) ptr
+    col <- (#peek struct winsize, ws_col) ptr
+    return $ CWin row col
+  poke ptr (CWin row col) = do
+    (#poke struct winsize, ws_row) ptr row
+    (#poke struct winsize, ws_col) ptr col
+
+
+fdSize :: Integral n => Fd -> IO (Maybe (Window n))
+fdSize (Fd fd) = with (CWin 0 0) $ \ws -> do
+  throwErrnoIfMinus1 "ioctl" $
+    ioctl fd (#const TIOCGWINSZ) ws
+  CWin row col <- peek ws
+  return . Just $ Window (fromIntegral row) (fromIntegral col)
+ `catch`
+  handler
+ where
+  handler :: IOError -> IO (Maybe (Window h))
+  handler _ = return Nothing
+
+foreign import capi "sys/ioctl.h ioctl"
+  ioctl :: CInt -> CULong -> Ptr CWin -> IO CInt
+
+size :: Integral n => IO (Maybe (Window n))
+size = fdSize (Fd (#const STDOUT_FILENO))
+
+hSize :: Integral n => Handle -> IO (Maybe (Window n))
+hSize h = withHandle_ "hSize" h $ \Handle__ { haDevice = dev } ->
+  case cast dev of
+    Nothing -> return Nothing
+    Just FD { fdFD = fd } -> fdSize (Fd fd)
diff --git a/src/System/Console/Terminal/Size.hs b/src/System/Console/Terminal/Size.hs
new file mode 100644
--- /dev/null
+++ b/src/System/Console/Terminal/Size.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE CPP #-}
+{- |
+Get terminal window height and width without ncurses dependency
+
+Based on answer by Andreas Hammar at <http://stackoverflow.com/a/12807521/972985>
+-}
+module System.Console.Terminal.Size
+  ( Window(..)
+  , size
+#if !defined(mingw32_HOST_OS)
+  , fdSize
+#endif
+  , hSize
+  ) where
+
+import System.Console.Terminal.Common
+#if defined(mingw32_HOST_OS)
+import qualified System.Console.Terminal.Windows as Host
+#else
+import qualified System.Console.Terminal.Posix as Host
+import System.Posix.Types(Fd)
+#endif
+import System.IO(Handle)
+
+
+-- | Get terminal window width and height for @stdout@.
+--
+-- >>> import System.Console.Terminal.Size
+-- >>> size
+-- Just (Window {height = 60, width = 112})
+size :: Integral n => IO (Maybe (Window n))
+size = Host.size
+
+#if !defined(mingw32_HOST_OS)
+-- | /Not available on Windows:/
+-- Get terminal window width and height for a specified file descriptor. If
+-- it's not attached to a terminal then 'Nothing' is returned.
+--
+-- >>> import System.Console.Terminal.Size
+-- >>> import System.Posix
+-- >>> fdSize stdOutput
+-- Just (Window {height = 56, width = 85})
+-- >>> fd <- openFd "foo" ReadWrite (Just stdFileMode) defaultFileFlags
+-- >>> fdSize fd
+-- Nothing
+fdSize :: Integral n => Fd -> IO (Maybe (Window n))
+fdSize = Host.fdSize
+#endif
+
+-- | Same as 'fdSize', but takes 'Handle' instead of 'Fd' (file descriptor).
+--
+-- Note that on Windows with shells that use the native console API (cmd.exe,
+-- PowerShell) this works only for output handles like 'stdout' and 'stderr';
+-- for input handles like 'stdin' it always returns 'Nothing'.
+--
+-- >>> import System.Console.Terminal.Size
+-- >>> import System.IO
+-- >>> hSize stdout
+-- Just (Window {height = 56, width = 85})
+hSize :: Integral n => Handle -> IO (Maybe (Window n))
+hSize = Host.hSize
diff --git a/src/System/Console/Terminal/Size.hsc b/src/System/Console/Terminal/Size.hsc
deleted file mode 100644
--- a/src/System/Console/Terminal/Size.hsc
+++ /dev/null
@@ -1,99 +0,0 @@
-{- |
-Get terminal window height and width without ncurses dependency
-
-Only tested to work on GNU/Linux systems
-
-Based on answer by Andreas Hammar at <http://stackoverflow.com/a/12807521/972985>
--}
-module System.Console.Terminal.Size
-  ( Window(..), size, fdSize, hSize
-  ) where
-
-import Control.Exception (catch)
-import Data.Typeable (cast)
-import Foreign
-import Foreign.C.Error
-import Foreign.C.Types
-import GHC.IO.FD (FD(FD, fdFD))
-import GHC.IO.Handle.Internals (withHandle_)
-import GHC.IO.Handle.Types (Handle, Handle__(Handle__, haDevice))
-#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 706)
-import Prelude hiding (catch)
-#endif
-import System.Posix.Types (Fd(Fd))
-
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-
-#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
-
-
--- Interesting part of @struct winsize@
-data CWin = CWin CUShort CUShort
-
-instance Storable CWin where
-  sizeOf _ = (#size struct winsize)
-  alignment _ = (#alignment struct winsize)
-  peek ptr = do
-    row <- (#peek struct winsize, ws_row) ptr
-    col <- (#peek struct winsize, ws_col) ptr
-    return $ CWin row col
-  poke ptr (CWin row col) = do
-    (#poke struct winsize, ws_row) ptr row
-    (#poke struct winsize, ws_col) ptr col
-
-
--- | Terminal window width and height
-data Window a = Window
-  { height :: !a
-  , width  :: !a
-  } deriving (Show, Read)
-
-instance Functor Window where
-  fmap f (Window { height = h, width = w }) = Window { height = f h, width = f w }
-
--- | Get terminal window width and height for a specified file descriptor. If
--- it's not attached to a terminal then 'Nothing' is returned.
---
--- >>> import System.Console.Terminal.Size
--- >>> import System.Posix
--- >>> fdSize stdOutput
--- Just (Window {height = 56, width = 85})
--- >>> fd <- openFd "foo" ReadWrite (Just stdFileMode) defaultFileFlags
--- >>> fdSize fd
--- Nothing
-fdSize :: Integral n => Fd -> IO (Maybe (Window n))
-fdSize (Fd fd) = with (CWin 0 0) $ \ws -> do
-  throwErrnoIfMinus1 "ioctl" $
-    ioctl fd (#const TIOCGWINSZ) ws
-  CWin row col <- peek ws
-  return . Just $ Window (fromIntegral row) (fromIntegral col)
- `catch`
-  handler
- where
-  handler :: IOError -> IO (Maybe (Window h))
-  handler _ = return Nothing
-
-foreign import ccall "sys/ioctl.h ioctl"
-  ioctl :: CInt -> CInt -> Ptr CWin -> IO CInt
-
--- | Get terminal window width and height for @stdout@.
---
--- >>> import System.Console.Terminal.Size
--- >>> size
--- Just (Window {height = 60, width = 112})
-size :: Integral n => IO (Maybe (Window n))
-size = fdSize (Fd (#const STDOUT_FILENO))
-
--- | Same as 'fdSize', but takes 'Handle' instead of 'Fd' (file descriptor).
---
--- >>> import System.Console.Terminal.Size
--- >>> import System.IO
--- >>> hSize stdout
--- Just (Window {height = 56, width = 85})
-hSize :: Integral n => Handle -> IO (Maybe (Window n))
-hSize h = withHandle_ "hSize" h $ \Handle__ { haDevice = dev } ->
-  case cast dev of
-    Nothing -> return Nothing
-    Just FD { fdFD = fd } -> fdSize (Fd fd)
diff --git a/src/System/Console/Terminal/Windows.hs b/src/System/Console/Terminal/Windows.hs
new file mode 100644
--- /dev/null
+++ b/src/System/Console/Terminal/Windows.hs
@@ -0,0 +1,48 @@
+module System.Console.Terminal.Windows(size, hSize) where
+
+import System.Console.Terminal.Common
+
+import System.Exit
+import System.IO
+import System.IO.Error (catchIOError)
+import System.Process
+import System.Win32.Console
+  ( CONSOLE_SCREEN_BUFFER_INFO(srWindow)
+  , SMALL_RECT(..)
+  , getConsoleScreenBufferInfo
+  )
+import System.Win32.Types (HANDLE, withHandleToHANDLE)
+
+size :: Integral n => IO (Maybe (Window n))
+size = hSize stdout
+
+hSize :: Integral n => Handle -> IO (Maybe (Window n))
+hSize hdl =
+    withHandleToHANDLE hdl nativeSize
+    `catchIOError` \_ -> do
+        -- Fallback to use for Cygwin or MSYS
+        let stty = (shell "stty size") {
+              std_in  = UseHandle hdl
+            , std_out = CreatePipe
+            , std_err = CreatePipe
+            }
+        (_, mbStdout, _, rStty) <- createProcess stty
+        exStty <- waitForProcess rStty
+        case exStty of
+            ExitFailure _ -> return Nothing
+            ExitSuccess ->
+                maybe (return Nothing)
+                      (\out -> do
+                          sizeStr <- hGetContents out
+                          let [r, c] = map read $ words sizeStr :: [Int]
+                          return $ Just $ Window (fromIntegral r) (fromIntegral c)
+                      )
+                      mbStdout
+
+nativeSize :: Integral n => HANDLE -> IO (Maybe (Window n))
+nativeSize hdl = do
+    rect <- srWindow <$> getConsoleScreenBufferInfo hdl
+    return $ Just $ Window
+        { height = fromIntegral (1 + bottomPos rect - topPos rect)
+        , width = fromIntegral (1 + rightPos rect - leftPos rect)
+        }
diff --git a/terminal-size.cabal b/terminal-size.cabal
--- a/terminal-size.cabal
+++ b/terminal-size.cabal
@@ -1,10 +1,8 @@
 name:                terminal-size
-version:             0.2.1.0
+version:             0.3.4
 synopsis:            Get terminal window height and width
 description:
-  Get terminal window height and width without ncurses dependency
-  .
-  Only tested to work on GNU/Linux systems
+  Get terminal window height and width without ncurses dependency.
 license:             BSD3
 license-file:        LICENSE
 author:              Andreas Hammar, Matvey Aksenov
@@ -12,16 +10,49 @@
 category:            System
 build-type:          Simple
 cabal-version:       >= 1.10
-
-library
-  default-language:  Haskell2010
-  build-depends:     base >= 4 && < 5
-  build-tools:       hsc2hs
-  hs-source-dirs:    src
-  exposed-modules:   System.Console.Terminal.Size
-  ghc-options:       -Wall
-                     -fno-warn-unused-do-bind
+extra-source-files:
+  README.markdown
+  CHANGELOG.markdown
 
 source-repository head
   type:     git
   location: https://github.com/biegunka/terminal-size
+
+source-repository this
+  type:     git
+  location: https://github.com/biegunka/terminal-size
+  tag:      0.3.4
+
+library
+  default-language:
+    Haskell2010
+
+  build-depends:
+    base >= 4 && < 5
+  if impl(ghc >= 7.2 && < 7.6)
+     build-depends:
+       ghc-prim
+  if os(windows)
+     build-depends:
+       process,
+       Win32 >= 2.13.2.0 && < 2.14
+
+  build-tools:
+    hsc2hs
+  hs-source-dirs:
+    src
+  exposed-modules:
+    System.Console.Terminal.Size
+
+  other-modules:
+    System.Console.Terminal.Common
+  if os(Windows)
+    other-modules:
+      System.Console.Terminal.Windows
+  else
+    other-modules:
+      System.Console.Terminal.Posix
+
+  ghc-options:
+    -Wall
+    -fno-warn-unused-do-bind
