diff --git a/csrc/sendfile_linux.c b/csrc/sendfile_linux.c
--- a/csrc/sendfile_linux.c
+++ b/csrc/sendfile_linux.c
@@ -1,29 +1,9 @@
 
 /* LINUX */
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
+#include <stdlib.h>
 #include <sys/sendfile.h>
-#include <sys/stat.h>
 
-/* return value is an errno code or 0 if there is no error */
-int c_sendfile_linux(const int out_fd, const char* in_fp, const long _offset, const long _count) {
-    off_t offset = _offset;
-    size_t count = _count;
-    int in_fd = open(in_fp, O_RDONLY);
-    
-    if(in_fd == -1) {
-        return errno;
-    }
-    
-    if(sendfile(out_fd, in_fd, &offset, count) == -1) {
-        return errno;
-    }
-
-    if(close(in_fd) == -1) {
-        return errno;
-    }
-    
-    /* return 0 to indicate no errors */
-    return 0;
+ssize_t c_sendfile_linux(const int out_fd, const int in_fd, const size_t count) {
+    return sendfile(out_fd, in_fd, NULL, count);
 }
+
diff --git a/csrc/sendfile_win32.c b/csrc/sendfile_win32.c
--- a/csrc/sendfile_win32.c
+++ b/csrc/sendfile_win32.c
@@ -2,39 +2,16 @@
 /* WIN32 */
 #include <windows.h>
 #include <mswsock.h>
+#include <io.h>
 
-/* return value is 0 if there is no error otherwise it is a system error code defined here:
- * http://msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx
- */
-int c_sendfile_win32(const int out_fd, const char* in_fp, const long _offset, const long _count) {
-    LONG offset = _offset;
-    DWORD count = _count;
-    HANDLE in_hdl = CreateFile(
-        in_fp,
-        GENERIC_READ,
-        FILE_SHARE_READ,
-        NULL,
-        OPEN_EXISTING,
-        FILE_FLAG_SEQUENTIAL_SCAN,
-        NULL
-    );
-    
-    if(in_hdl == INVALID_HANDLE_VALUE) {
-        return GetLastError();
-    }
-    
-    if(SetFilePointer(in_hdl, offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
-        return GetLastError();
-    }
-    
-    if(! TransmitFile(out_fd, in_hdl, count, 0, NULL, NULL, TF_USE_KERNEL_APC)) {
-        return WSAGetLastError();
-    }
-    
-    if(! CloseHandle(in_hdl)) {
-        return GetLastError();
-    }
-    
-    /* return 0 to indicate no errors */
-    return 0;
+BOOL c_TransmitFile(SOCKET out_fd, HANDLE in_hdl, DWORD count) {
+    /* http://msdn.microsoft.com/en-us/library/ms740565(VS.85).aspx */
+    return TransmitFile(out_fd, in_hdl, count, 0, NULL, NULL, TF_USE_KERNEL_APC);
 }
+
+long c_get_osfhandle(int fd) {
+    /* http://support.microsoft.com/kb/99173 - MAY BE IMPORTANT */
+    /* http://msdn.microsoft.com/en-us/library/ks2530z6.aspx */
+    return _get_osfhandle(fd);
+}
+
diff --git a/sendfile.cabal b/sendfile.cabal
--- a/sendfile.cabal
+++ b/sendfile.cabal
@@ -1,13 +1,10 @@
 name:          sendfile
-version:       0.2
+version:       0.3
 stability:     experimental
 synopsis:      A portable sendfile library
 description:   A library which exposes zero-copy sendfile functionality in a portable way. If a platform does not support sendfile, a fallback implementation in haskell is provided.
                .
-               Currently supported platforms:
-               * Windows 2000+ (Native)
-               * Linux 2.6+ (Native)
-               * Everything else (Haskell)
+               Currently supported platforms: Windows 2000+ (Native), Linux 2.6+ (Native), Everything else (Haskell).
 
 license:       BSD3
 license-file:  LICENSE
@@ -25,23 +22,29 @@
 library
     hs-source-dirs:  src
 
-    exposed-modules: SendFile
+    exposed-modules: Network.Socket.SendFile
 
-    other-modules:   SendFile.Internal
+    other-modules:   Network.Socket.SendFile.Internal
     
-    build-depends:   base >= 3 && < 5,
+    build-depends:   base >= 4 && < 5,
                      network >= 2 && < 3
-    
+
+    ghc-options: -Wall
+
     if os(windows) && !flag(portable)
-      cc-options: -DWIN32_SENDFILE
+      cpp-options: -DWIN32_SENDFILE
+      build-depends: Win32
       c-sources: csrc/sendfile_win32.c
-      extra-libraries: kernel32, mswsock
+      extra-libraries: mswsock
+      other-modules: Network.Socket.SendFile.Win32
     else
       if os(linux) && !flag(portable)
-        cc-options: -DLINUX_SENDFILE
+        cpp-options: -DLINUX_SENDFILE
         c-sources: csrc/sendfile_linux.c
+        other-modules: Network.Socket.SendFile.Linux
       else
-        cc-options: -DPORTABLE_SENDFILE
+        cpp-options: -DPORTABLE_SENDFILE
+        other-modules: Network.Socket.SendFile.Portable
         build-depends: bytestring >= 0.9.1.4 && < 0.10
 
 source-repository head
diff --git a/src/Network/Socket/SendFile.hs b/src/Network/Socket/SendFile.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Socket/SendFile.hs
@@ -0,0 +1,28 @@
+-- | A cross-platform wrapper for sendfile -- this implements an available operating-system call if supported, otherwise it falls back to a portable haskell implementation. SendFile will flush the output Handle before transmission.
+--
+--   Keep in mind that the input should only be a `Handle` derived from a network socket (by using socketToHandle). Using something other than a network socket for the input Handle will result in undefined behavior. Furthermore, for consistent read/write behavior, both the output and input handles should be opened in Binary mode rather than Text mode (especially if you are using hSeek).
+module Network.Socket.SendFile (
+    sendFile,
+    sendFile',
+    sendFileMode
+    ) where
+    
+import qualified Network.Socket.SendFile.Internal (sendFile, sendFile', sendFileMode)
+import System.IO (Handle)
+
+-- | The simplest interface. Simply give it an output `Handle` and the `FilePath` to the input file.
+sendFile :: Handle   -- ^ The output handle
+         -> FilePath -- ^ The path where the input file resides
+         -> IO ()
+sendFile = Network.Socket.SendFile.Internal.sendFile
+
+-- | A more powerful interface than sendFile, sendFile' accepts a `Handle` for the input file instead of a `FilePath` and the number of bytes you would like to read. This unlocks the full potential `Handle`(s). For instance, if you wanted to start reading from a particular offset, you could utilize `hSeek`. If you need the file size you can use 'hFileSize'.
+sendFile' :: Handle  -- ^ The output handle
+          -> Handle  -- ^ The input handle
+          -> Integer -- ^ The number of bytes to read
+          -> IO ()
+sendFile' = Network.Socket.SendFile.Internal.sendFile'
+
+-- | Returns the mode that sendfile was compiled with. Mainly for debugging use. Possible values are 'WIN32_SENDFILE', 'LINUX_SENDFILE', and 'PORTABLE_SENDFILE'.
+sendFileMode :: String -- ^ The mode that sendfile was compiled with
+sendFileMode = Network.Socket.SendFile.Internal.sendFileMode
diff --git a/src/Network/Socket/SendFile/Internal.hs b/src/Network/Socket/SendFile/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Socket/SendFile/Internal.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE CPP #-}
+module Network.Socket.SendFile.Internal (
+    sendFile,
+    sendFile',
+    sendFileMode
+    ) where
+
+import System.IO (
+    Handle,
+    IOMode(..),
+    hFileSize,
+    withBinaryFile
+    )
+
+#if defined(WIN32_SENDFILE)
+import Network.Socket.SendFile.Win32 (sendFile')
+
+sendFileMode :: String
+sendFileMode = "WIN32_SENDFILE"
+#endif
+
+#if defined(LINUX_SENDFILE)
+import Network.Socket.SendFile.Linux (sendFile')
+
+sendFileMode :: String
+sendFileMode = "LINUX_SENDFILE"
+#endif
+
+#if defined(PORTABLE_SENDFILE)
+import Network.Socket.SendFile.Portable (sendFile')
+
+sendFileMode :: String
+sendFileMode = "PORTABLE_SENDFILE"
+#endif
+
+sendFile :: Handle -> FilePath -> IO ()
+sendFile outp infp = withBinaryFile infp ReadMode $ \inp -> do
+    count <- hFileSize inp
+    sendFile' outp inp count
diff --git a/src/Network/Socket/SendFile/Linux.hsc b/src/Network/Socket/SendFile/Linux.hsc
new file mode 100644
--- /dev/null
+++ b/src/Network/Socket/SendFile/Linux.hsc
@@ -0,0 +1,27 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+-- | Linux system-dependent code for 'sendfile'.
+module Network.Socket.SendFile.Linux (sendFile') where
+import Data.Int
+import Data.Word
+import Foreign.C.Error (throwErrno)
+import GHC.IOBase (FD, haFD)
+import GHC.Handle (withHandle_)
+import System.IO (Handle, hFlush)
+
+#include <sys/sendfile.h>
+
+sendFile' :: Handle -> Handle -> Integer -> IO ()
+sendFile' outp inp count = do
+    -- flush outp before sending
+    hFlush outp
+    withHandle_ "Network.Socket.SendFile.Linux.sendFile'" outp $ \outp' -> do
+    withHandle_ "Network.Socket.SendFile.Linux.sendFile'" inp $ \inp' -> do 
+    let out_fd = haFD outp'
+    let in_fd = haFD inp'
+    res <- c_sendfile_linux out_fd in_fd (fromIntegral count)
+    if res == -1
+        then throwErrno "Network.Socket.SendFile.Linux.sendFile'"
+        else return ()
+
+foreign import ccall
+    c_sendfile_linux :: FD -> FD -> (#type size_t) -> IO (#type ssize_t)
diff --git a/src/Network/Socket/SendFile/Portable.hs b/src/Network/Socket/SendFile/Portable.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Socket/SendFile/Portable.hs
@@ -0,0 +1,13 @@
+-- | Portable implementation of sendfile.
+module Network.Socket.SendFile.Portable (sendFile') where
+
+import Data.ByteString.Char8
+import Prelude hiding (readFile)
+import System.IO (Handle, hFlush)
+
+
+-- FIXME: possibly immature / inefficient implementation
+sendFile' :: Handle -> Handle -> Integer -> IO ()
+sendFile' outp inp count = do
+    hPutStr outp =<< hGet inp (fromIntegral count)
+    hFlush outp -- match the behavior that all data is "flushed to the os" of native implementations
diff --git a/src/Network/Socket/SendFile/Win32.hsc b/src/Network/Socket/SendFile/Win32.hsc
new file mode 100644
--- /dev/null
+++ b/src/Network/Socket/SendFile/Win32.hsc
@@ -0,0 +1,43 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+-- | Win32 system-dependent code for 'TransmitFile'.
+module Network.Socket.SendFile.Win32 (sendFile') where
+import Data.Int
+import Data.Word
+import Foreign.C.Error (throwErrno)
+import Foreign.Ptr (IntPtr, intPtrToPtr)
+import GHC.Handle (withHandle_)
+import GHC.IOBase (FD, haFD)
+import System.IO (Handle, hFlush)
+import System.Win32.Types
+
+#include <windows.h>
+
+sendFile' :: Handle -> Handle -> Integer -> IO ()
+sendFile' outp inp count = do
+    hFlush outp -- flush the buffer before invoking transmitFile
+    withHandle_ "Network.Socket.SendFile.Win32.sendFile'" outp $ \outp' -> do
+    withHandle_ "Network.Socket.SendFile.Win32.sendFile'" inp $ \inp' -> do
+    let out_fd = haFD outp'
+    in_hdl <- get_osfhandle (haFD inp')
+    transmitFile (fromIntegral out_fd) in_hdl (fromIntegral count)
+
+get_osfhandle :: FD        -- ^ User file descriptor.
+              -> IO HANDLE -- ^ The operating-system file handle.
+get_osfhandle fd = do
+    res <- c_get_osfhandle fd
+    if res == (#const INVALID_HANDLE_VALUE)
+      then throwErrno "Network.Socket.SendFile.Win32.get_osfhandle"
+      else return (intPtrToPtr res)
+
+transmitFile :: FD     -- ^ A handle to a connected socket.
+             -> HANDLE -- ^ A handle to the open file that the TransmitFile function transmits.
+             -> DWORD  -- ^ The number of bytes in the file to transmit.
+             -> IO ()
+transmitFile out_fd in_hdl count =
+    failIf_ (== 0) "Network.Socket.SendFile.Win32.transmitFile" (c_TransmitFile out_fd in_hdl count)
+    
+foreign import ccall
+    c_get_osfhandle :: FD -> IO IntPtr
+    
+foreign import ccall
+    c_TransmitFile :: FD -> HANDLE -> DWORD -> IO (#type BOOL)
diff --git a/src/SendFile.hs b/src/SendFile.hs
deleted file mode 100644
--- a/src/SendFile.hs
+++ /dev/null
@@ -1,33 +0,0 @@
-module SendFile (
-    fileSize,
-    sendFile,
-    sendFile',
-    sendFileMode
-    ) where
-    
-import qualified SendFile.Internal
-import System.IO (Handle(..))
-
--- | Get the size of a file.
-fileSize :: FilePath -- ^ The path of the file
-         -> IO Int   -- ^ The size of the file (in bytes)
-fileSize = SendFile.Internal.fileSize
-
--- | A cross-platform wrapper for sendfile -- this implements an available operating-system call if supported, otherwise it falls back to a portable haskell implementation. It will flush the output Handle before handing it to the operating system for transmission.
-sendFile :: Handle   -- ^ The output Handle
-         -> FilePath -- ^ The path where the input file resides
-         -> IO ()
-sendFile = SendFile.Internal.sendFile
-
--- | Like sendFile except that it additionally allows you to specify an offset and count. The behavior of reading beyond the end of the file is undefined.
-sendFile' :: Handle   -- ^ The output Handle
-          -> FilePath -- ^ The path where the input file resides
-          -> Int      -- ^ The starting offset of the file (in bytes)
-          -> Int      -- ^ The number of bytes to read
-          -> IO ()
-sendFile' = SendFile.Internal.sendFile'
-
--- | Returns the mode that sendfile was compiled with. Mainly for debugging use. Possible values are 'WIN32_SENDFILE', 'LINUX_SENDFILE', and 'PORTABLE_SENDFILE'.
-sendFileMode :: String -- ^ The mode that sendfile was compiled with
-sendFileMode = SendFile.Internal.sendFileMode
-
diff --git a/src/SendFile/Internal.hsc b/src/SendFile/Internal.hsc
deleted file mode 100644
--- a/src/SendFile/Internal.hsc
+++ /dev/null
@@ -1,91 +0,0 @@
-{-# LANGUAGE CPP, ForeignFunctionInterface #-}
-module SendFile.Internal (
-    fileSize,
-    sendFile,
-    sendFile',
-    sendFileMode
-    ) where
-
-import System.IO (
-    Handle(..),
-    IOMode(..),
-    SeekMode(..),
-    hFileSize,
-    hFlush,
-    hSeek,
-    withBinaryFile
-    )
-
-#if defined(WIN32_SENDFILE)
-import Foreign.C
-import GHC.IOBase (haFD)
-import GHC.Handle (withHandle_)
-
-sendFileMode :: String
-sendFileMode = "WIN32_SENDFILE"
-
-sendFile' :: Handle -> FilePath -> Int -> Int -> IO ()
-sendFile' outh infp offset count = do
-    -- flush outh before handing it sendFile
-    hFlush outh
-    withHandle_ "sendFile" outh $ \outh' -> do 
-    withCString infp $ \in_fp -> do
-    let out_fd = haFD outh'
-    err <- c_sendfile_win32 out_fd in_fp (fromIntegral offset) (fromIntegral count)
-    if err == 0
-        then return ()
-        else fail ("system error " ++ show err)
-    
-foreign import ccall
-    c_sendfile_win32 :: CInt -> CString -> CLong -> CLong -> IO Int
-#endif
-
-#if defined(LINUX_SENDFILE)
-import Foreign.C
-import GHC.IOBase (haFD)
-import GHC.Handle (withHandle_)
-
-sendFileMode :: String
-sendFileMode = "LINUX_SENDFILE"
-
-sendFile' :: Handle -> FilePath -> Int -> Int -> IO ()
-sendFile' outh infp offset count = do
-    -- flush outh before handing it sendFile
-    hFlush outh
-    withHandle_ "sendFile" outh $ \outh' -> do 
-    withCString infp $ \in_fp -> do
-    let out_fd = haFD outh'
-    err <- c_sendfile_linux out_fd in_fp (fromIntegral offset) (fromIntegral count)
-    if err == 0
-        then return ()
-        else fail ("errno " ++ show err)
-    
-foreign import ccall
-    c_sendfile_linux :: CInt -> CString -> CLong -> CLong -> IO Int
-#endif
-
-#if defined(PORTABLE_SENDFILE)
-import Prelude hiding (readFile)
-import Data.ByteString.Char8
-
-sendFileMode :: String
-sendFileMode = "PORTABLE_SENDFILE"
-
--- FIXME: possibly immature / inefficient implementation
-sendFile' :: Handle -> FilePath -> Int -> Int -> IO ()
-sendFile' outh infp offset count =
-    withBinaryFile infp ReadMode $ \inh -> do
-    hSeek inh AbsoluteSeek (fromIntegral offset)
-    hPutStr outh =<< hGet inh count
-    hFlush outh 
-    return ()
-#endif
-
-fileSize :: FilePath -> IO Int
-fileSize fp = fmap fromIntegral (withBinaryFile fp ReadMode hFileSize)
-
-sendFile :: Handle -> FilePath -> IO ()
-sendFile outh infp = do
-    count <- fileSize infp
-    sendFile' outh infp 0 count
-
