diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.markdown
@@ -0,0 +1,6 @@
+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-2014, 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,16 @@
+terminal-size
+=============
+
+[![Hackage](https://budueba.com/hackage/terminal-size)](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})
+```
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,24 @@
+
+module System.Console.Terminal.Common
+  ( Window(..)
+  ) where
+
+import Control.Applicative
+import Data.Foldable (Foldable(..))
+import Data.Traversable (Traversable(..))
+import Data.Monoid (mappend)
+
+-- | Terminal window width and height
+data Window a = Window
+  { height :: !a
+  , width  :: !a
+  } deriving (Show, Eq, Read)
+
+instance Functor Window where
+  fmap f (Window { height = h, width = w }) = Window { height = f h, width = f w }
+
+instance Foldable Window where
+  foldMap f (Window { height = h, width = w }) = f h `mappend` f w
+
+instance Traversable Window where
+  traverse f (Window { height = h, width = w }) = Window <$> f h <*> f w
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,64 @@
+
+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>
+
+
+#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
+
+
+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
+
+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,56 @@
+{-# 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, hSize
+#endif
+  ) 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)
+import System.IO(Handle)
+#endif
+
+
+-- | 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
+
+-- | /Not available on Windows:/
+--   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 = Host.hSize
+#endif
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,41 @@
+
+module System.Console.Terminal.Windows(size) where
+
+import System.Console.Terminal.Common
+
+import Control.Monad
+import Data.Word
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.Marshal.Alloc
+
+type HANDLE = Ptr ()
+
+data CONSOLE_SCREEN_BUFFER_INFO
+
+sizeCONSOLE_SCREEN_BUFFER_INFO :: Int
+sizeCONSOLE_SCREEN_BUFFER_INFO = 22
+
+posCONSOLE_SCREEN_BUFFER_INFO_srWindow :: Int
+posCONSOLE_SCREEN_BUFFER_INFO_srWindow = 10 -- 4 x Word16 Left,Top,Right,Bottom
+
+c_STD_OUTPUT_HANDLE :: Word32
+c_STD_OUTPUT_HANDLE = -11
+
+foreign import stdcall unsafe "windows.h GetConsoleScreenBufferInfo"
+    c_GetConsoleScreenBufferInfo :: HANDLE -> Ptr CONSOLE_SCREEN_BUFFER_INFO -> IO Bool
+
+foreign import stdcall unsafe "windows.h GetStdHandle"
+    c_GetStdHandle :: Word32 -> IO HANDLE
+
+
+size :: Integral n => IO (Maybe (Window n))
+size = do
+    hdl <- c_GetStdHandle c_STD_OUTPUT_HANDLE
+    allocaBytes sizeCONSOLE_SCREEN_BUFFER_INFO $ \p -> do
+        b <- c_GetConsoleScreenBufferInfo hdl p
+        if not b then return Nothing else do
+            [left,top,right,bottom] <- forM [0..3] $ \i -> do
+                v <- peekByteOff p ((i*2) + posCONSOLE_SCREEN_BUFFER_INFO_srWindow)
+                return $ fromIntegral (v :: Word16)
+            return $ Just $ Window (1+bottom-top) (1+right-left)
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.0
 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,6 +10,9 @@
 category:            System
 build-type:          Simple
 cabal-version:       >= 1.10
+extra-source-files:
+  README.markdown
+  CHANGELOG.markdown
 
 library
   default-language:  Haskell2010
@@ -19,6 +20,11 @@
   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
 
