diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -5,3 +5,5 @@
 unix/linux's `/dev/urandom`, or the RDRAND instruction.
 
 This package supports Windows, {li,u}nix, QNX, and has preliminary support for HaLVM.
+
+[![Build Status](https://travis-ci.org/TomMD/entropy.svg?branch=master)](https://travis-ci.org/TomMD/entropy)
diff --git a/System/Entropy.hs b/System/Entropy.hs
--- a/System/Entropy.hs
+++ b/System/Entropy.hs
@@ -8,10 +8,10 @@
 
  Currently supporting:
 
-    - Windows via CryptoAPO
+    - Windows via CryptoAPI
     - *nix systems via @\/dev\/urandom@
-    - QNX
-    - Xen only when RDRAND is available.
+       - Includes QNX
+    - Xen (only when RDRAND is available)
 -}
 
 module System.Entropy
@@ -21,19 +21,25 @@
         ) where
 import System.EntropyWindows
 #else
+#ifdef XEN
+         module System.EntropyXen
+        ) where
+import System.EntropyXen
+#else
          module System.EntropyNix
         ) where
 import System.EntropyNix
 #endif
+#endif
 
 import qualified Data.ByteString as B
 
--- |Inefficiently get a specific number of bytes of cryptographically
+-- |Get a specific number of bytes of cryptographically
 -- secure random data using the system-specific facilities.
 --
--- Use '/dev/urandom' on *nix and CryptAPI when on Windows.  In short,
--- this entropy is considered cryptographically secure but not true
--- entropy.
+-- Use RDRAND if available and XOR with '/dev/urandom' on *nix and CryptAPI when on
+-- Windows.  In short, this entropy is considered cryptographically secure
+-- but not true entropy.
 getEntropy :: Int -> IO B.ByteString
 getEntropy n = do
     h <- openHandle
diff --git a/System/EntropyNix.hs b/System/EntropyNix.hs
--- a/System/EntropyNix.hs
+++ b/System/EntropyNix.hs
@@ -18,6 +18,7 @@
 import Control.Monad (liftM, when)
 import Data.ByteString as B
 import System.IO.Error (mkIOError, eofErrorType, ioeSetErrorString)
+import Data.Bits (xor)
 
 import Foreign (allocaBytes)
 import Foreign.Ptr
@@ -29,13 +30,6 @@
 #undef HAVE_RDRAND
 #endif
 
-#ifdef XEN
-#ifndef HAVE_RDRAND
-#error "The entropy package requires RDRAND support when using the halvm/Xen"
-#endif
-data CryptHandle = UseRdRand -- or die trying
-#else
-
 import System.Posix (openFd, closeFd, fdReadBuf, OpenMode(..), defaultFileFlags, Fd)
 
 source :: FilePath
@@ -45,8 +39,7 @@
 data CryptHandle
     = CH Fd
 #ifdef HAVE_RDRAND
-    | UseRdRand
-#endif
+    | UseRdRand Fd
 #endif
 
 -- |Open a `CryptHandle`
@@ -54,46 +47,33 @@
 openHandle = do
 #ifdef HAVE_RDRAND
     b <- cpuHasRdRand
-    if b then return UseRdRand
-         else nonRDRandHandle
+    if b then UseRdRand `fmap` nonRDRandHandle
+         else CH `fmap` nonRDRandHandle
 #else
-              nonRDRandHandle
+              CH `fmap` nonRDRandHandle
 #endif
  where
-#ifdef XEN
-  nonRDRandHandle :: IO CryptHandle
-  nonRDRandHandle = error "entropy: On halvm there is no entropy other than RDRAND."
-#else
-  nonRDRandHandle :: IO CryptHandle
-  nonRDRandHandle = liftM CH (openFd source ReadOnly Nothing defaultFileFlags)
-#endif
+  nonRDRandHandle :: IO Fd
+  nonRDRandHandle = openFd source ReadOnly Nothing defaultFileFlags
 
 -- |Close the `CryptHandle`
 closeHandle :: CryptHandle -> IO ()
-#ifndef XEN
 closeHandle (CH h) = closeFd h
-#endif
 #ifdef HAVE_RDRAND
-closeHandle UseRdRand = return ()
+closeHandle (UseRdRand h) = closeFd h
 #endif
 
 -- |Read random data from a `CryptHandle`
-#ifdef XEN
 hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
-hGetEntropy UseRdRand = \n -> do
-    B.create n $ \ptr ->  do
-                r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
-                when (r /= 0)
-                     (fail "RDRand failed to gather entropy")
-#else
-hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
 hGetEntropy (CH h) = fdReadBS h
 #ifdef HAVE_RDRAND
-hGetEntropy UseRdRand = \n -> do
-    B.create n $ \ptr ->  do
-                r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
-                when (r /= 0)
-                     (fail "RDRand failed to gather entropy")
+hGetEntropy (UseRdRand h) = \n ->
+ do bsURandom <- fdReadBS h n
+    bsRDRAND  <- B.create n $ \ptr ->  do
+                  r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
+                  when (r /= 0)
+                       (fail "RDRand failed to gather entropy")
+    return $ B.pack $ B.zipWith xor bsURandom bsRDRAND
 #endif
 
 fdReadBS :: Fd -> Int -> IO B.ByteString
@@ -103,8 +83,6 @@
         case rc of
             0 -> ioError (ioeSetErrorString (mkIOError eofErrorType "fdRead" Nothing Nothing) "EOF")
             n' -> B.packCStringLen (castPtr buf, fromIntegral n')
-#endif
-
 
 #ifdef HAVE_RDRAND
 foreign import ccall unsafe "cpu_has_rdrand"
diff --git a/System/EntropyWindows.hs b/System/EntropyWindows.hs
--- a/System/EntropyWindows.hs
+++ b/System/EntropyWindows.hs
@@ -20,6 +20,7 @@
 import Data.ByteString as B
 import Data.ByteString.Internal as BI
 import Data.Int (Int32)
+import Data.Bits (xor)
 import Data.Word (Word32, Word8)
 import Foreign.C.String (CString, withCString)
 import Foreign.C.Types
@@ -59,7 +60,7 @@
 data CryptHandle
     = CH Word32
 #ifdef HAVE_RDRAND
-    | UseRdRand
+    | UseRdRand Word32
 #endif
 
 -- Define the constants we need from WinCrypt.h 
@@ -107,22 +108,27 @@
 openHandle = do
 #ifdef HAVE_RDRAND
     b <- cpuHasRdRand
-    if b then return UseRdRand
+    if b then UseRdRand `fmap` cryptAcquireCtx
          else do
 #endif
-                  liftM CH cryptAcquireCtx
+                  CH `fmap` cryptAcquireCtx
 
 -- |Close the `CryptHandle`
 closeHandle :: CryptHandle -> IO ()
-closeHandle (CH h) = cryptReleaseCtx h
+closeHandle (CH h)        = cryptReleaseCtx h
+#ifdef HAVE_RDRAND
+closeHandle (UseRdRand h) = cryptReleaseCtx h
+#endif
 
 -- |Read from `CryptHandle`
 hGetEntropy :: CryptHandle -> Int -> IO B.ByteString 
 hGetEntropy (CH h) n = cryptGenRandom h n
 #ifdef HAVE_RDRAND
-hGetEntropy UseRdRand n =
-    BI.create n $ \ptr ->  do
-                r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
-                when (r /= 0)
-                     (fail "RDRand failed to gather entropy")
+hGetEntropy (UseRdRand h) n =
+ do bsRDRAND <- BI.create n $ \ptr ->  do
+                  r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
+                  when (r /= 0)
+                       (fail "RDRand failed to gather entropy")
+    bsWinCrypt <- cryptGenRandom h n
+    return $ B.pack $ B.zipWith xor bsRDRAND bsWinCrypt
 #endif
diff --git a/System/EntropyXen.hs b/System/EntropyXen.hs
new file mode 100644
--- /dev/null
+++ b/System/EntropyXen.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE CPP, ForeignFunctionInterface, BangPatterns, ScopedTypeVariables #-}
+{-|
+ Maintainer: Thomas.DuBuisson@gmail.com
+ Stability: beta
+ Portability: portable
+
+ Obtain entropy from system sources or x86 RDRAND when available.
+
+-}
+
+module System.EntropyXen
+        ( CryptHandle
+        , openHandle
+        , hGetEntropy
+        , closeHandle
+        ) where
+
+import Control.Monad (liftM, when)
+import Data.ByteString as B
+import System.IO.Error (mkIOError, eofErrorType, ioeSetErrorString)
+
+import Foreign (allocaBytes)
+import Foreign.Ptr
+import Foreign.C.Types
+import Data.ByteString.Internal as B
+
+#ifdef arch_i386
+-- See .cabal wrt GCC 4.8.2 asm compilation bug
+#undef HAVE_RDRAND
+#endif
+
+#ifndef HAVE_RDRAND
+#error "The entropy package requires RDRAND support when using the halvm/Xen"
+#endif
+data CryptHandle = UseRdRand -- or die trying
+
+-- |Open a `CryptHandle`
+openHandle :: IO CryptHandle
+openHandle = do
+    b <- cpuHasRdRand
+    if b then return UseRdRand
+         else nonRDRandHandle
+ where
+  nonRDRandHandle :: IO CryptHandle
+  nonRDRandHandle = error "entropy: On halvm there is no entropy other than RDRAND."
+
+-- |Close the `CryptHandle`
+closeHandle :: CryptHandle -> IO ()
+closeHandle UseRdRand = return ()
+
+-- |Read random data from a `CryptHandle`
+hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
+hGetEntropy UseRdRand = \n -> do
+    B.create n $ \ptr ->  do
+                r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
+                when (r /= 0)
+                     (fail "RDRand failed to gather entropy")
+
+foreign import ccall unsafe "cpu_has_rdrand"
+   c_cpu_has_rdrand :: IO CInt
+
+foreign import ccall unsafe "get_rand_bytes"
+  c_get_rand_bytes :: Ptr CUChar -> CSize -> IO CInt
+
+cpuHasRdRand :: IO Bool
+cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
diff --git a/entropy.cabal b/entropy.cabal
--- a/entropy.cabal
+++ b/entropy.cabal
@@ -1,5 +1,5 @@
 name:           entropy
-version:        0.3.2
+version:        0.3.3
 description:    A platform independent method to obtain cryptographically strong entropy 
                 (RDRAND when available anywhere, urandom on nix, CryptAPI on Windows, patches welcome).
                 Users looking for cryptographically strong (number-theoretically
@@ -35,12 +35,16 @@
   exposed-modules: System.Entropy
   if os(windows)
     other-modules: System.EntropyWindows
-  else
-    other-modules: System.EntropyNix
+  else {
+       if os(halvm)
+         other-modules: System.EntropyXen
+       else
+         other-modules: System.EntropyNix
+  }
   other-extensions:    CPP, ForeignFunctionInterface, BangPatterns, ScopedTypeVariables
   build-depends: base == 4.*, bytestring
   default-language:    Haskell2010
-  if(flag(halvm))
+  if(os(halvm))
     cpp-options: -DXEN -DHAVE_RDRAND
     cc-options:  -DXEN -DHAVE_RDRAND
   if arch(x86_64)
@@ -57,7 +61,7 @@
     cc-options:  -DisWindows
     extra-libraries: advapi32
   else
-    if !flag(halvm)
+    if !os(halvm)
        Build-Depends: unix
 
 source-repository head
