diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for file-io
 
+## 0.1.0.2 -- 2023-12-11
+
+* support `os-string` package and newer `filepath`
+
 ## 0.1.0.1 -- YYYY-mm-dd
 
 * Don't use creat flag when only reading files
diff --git a/System/File/Common.hs b/System/File/Common.hs
deleted file mode 100644
--- a/System/File/Common.hs
+++ /dev/null
@@ -1,82 +0,0 @@
-
--- | Like 'openFile', but open the file in binary mode.
--- On Windows, reading a file in text mode (which is the default)
--- will translate CRLF to LF, and writing will translate LF to CRLF.
--- This is usually what you want with text files.  With binary files
--- this is undesirable; also, as usual under Microsoft operating systems,
--- text mode treats control-Z as EOF.  Binary mode turns off all special
--- treatment of end-of-line and end-of-file characters.
--- (See also 'System.IO.hSetBinaryMode'.)
-
--- On POSIX systems, 'openBinaryFile' is an /interruptible operation/ as
--- described in "Control.Exception".
-openBinaryFile :: FILE_PATH -> IOMode -> IO Handle
-openBinaryFile fp iomode = do
-  h <- openFile fp iomode
-  hSetBinaryMode h True
-  pure h
-
--- | Run an action on a file.
---
--- The 'Handle' is automatically closed afther the action.
-withFile :: FILE_PATH -> IOMode -> (Handle -> IO r) -> IO r
-withFile fp iomode action = bracket
-  (openFile fp iomode)
-  hClose
-  action
-
-withBinaryFile :: FILE_PATH -> IOMode -> (Handle -> IO r) -> IO r
-withBinaryFile fp iomode action = bracket
-  (openBinaryFile fp iomode)
-  hClose
-  action
-
--- | Run an action on a file.
---
--- The 'Handle' is not automatically closed to allow lazy IO. Use this
--- with caution.
-withFile'
-  :: FILE_PATH -> IOMode -> (Handle -> IO r) -> IO r
-withFile' fp iomode action = do
-  h <- openFile fp iomode
-  action h
-
-withBinaryFile'
-  :: FILE_PATH -> IOMode -> (Handle -> IO r) -> IO r
-withBinaryFile' fp iomode action = do
-  h <- openBinaryFile fp iomode
-  action h
-
--- | The 'readFile' function reads a file and returns the contents of the file
--- as a 'ByteString'. The file is read lazily, on demand.
-readFile :: FILE_PATH -> IO BSL.ByteString
-readFile fp = withFile' fp ReadMode BSL.hGetContents
-
--- | The 'readFile'' function reads a file and returns the contents of the file
--- as a 'ByteString'. The file is fully read before being returned.
-readFile'
-  :: FILE_PATH -> IO BS.ByteString
-readFile' fp = withFile fp ReadMode BS.hGetContents
-
--- | The computation 'writeFile' @file str@ function writes the lazy 'ByteString' @str@,
--- to the file @file@.
-writeFile :: FILE_PATH -> BSL.ByteString -> IO ()
-writeFile fp contents = withFile fp WriteMode (`BSL.hPut` contents)
-
--- | The computation 'writeFile' @file str@ function writes the strict 'ByteString' @str@,
--- to the file @file@.
-writeFile'
-  :: FILE_PATH -> BS.ByteString -> IO ()
-writeFile' fp contents = withFile fp WriteMode (`BS.hPut` contents)
-
--- | The computation 'appendFile' @file str@ function appends the lazy 'ByteString' @str@,
--- to the file @file@.
-appendFile :: FILE_PATH -> BSL.ByteString -> IO ()
-appendFile fp contents = withFile fp AppendMode (`BSL.hPut` contents)
-
--- | The computation 'appendFile' @file str@ function appends the strict 'ByteString' @str@,
--- to the file @file@.
-appendFile'
-  :: FILE_PATH -> BS.ByteString -> IO ()
-appendFile' fp contents = withFile fp AppendMode (`BS.hPut` contents)
-
diff --git a/System/File/OsPath.hs b/System/File/OsPath.hs
--- a/System/File/OsPath.hs
+++ b/System/File/OsPath.hs
@@ -1,14 +1,6 @@
-{-# LANGUAGE CPP #-}
-
 module System.File.OsPath where
 
-#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
-#define CTOR WS
-import qualified System.File.Windows as P
-#else
-#define CTOR PS
-import qualified System.File.Posix as P
-#endif
+import qualified System.File.Platform as P
 
 import Control.Exception (bracket)
 import System.IO (IOMode(..), Handle, hSetBinaryMode, hClose)
@@ -18,8 +10,86 @@
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Lazy as BSL
 
-#define FILE_PATH OsPath
-#include "Common.hs"
+-- | Like 'openFile', but open the file in binary mode.
+-- On Windows, reading a file in text mode (which is the default)
+-- will translate CRLF to LF, and writing will translate LF to CRLF.
+-- This is usually what you want with text files.  With binary files
+-- this is undesirable; also, as usual under Microsoft operating systems,
+-- text mode treats control-Z as EOF.  Binary mode turns off all special
+-- treatment of end-of-line and end-of-file characters.
+-- (See also 'System.IO.hSetBinaryMode'.)
+
+-- On POSIX systems, 'openBinaryFile' is an /interruptible operation/ as
+-- described in "Control.Exception".
+openBinaryFile :: OsPath -> IOMode -> IO Handle
+openBinaryFile fp iomode = do
+  h <- openFile fp iomode
+  hSetBinaryMode h True
+  pure h
+
+-- | Run an action on a file.
+--
+-- The 'Handle' is automatically closed afther the action.
+withFile :: OsPath -> IOMode -> (Handle -> IO r) -> IO r
+withFile fp iomode action = bracket
+  (openFile fp iomode)
+  hClose
+  action
+
+withBinaryFile :: OsPath -> IOMode -> (Handle -> IO r) -> IO r
+withBinaryFile fp iomode action = bracket
+  (openBinaryFile fp iomode)
+  hClose
+  action
+
+-- | Run an action on a file.
+--
+-- The 'Handle' is not automatically closed to allow lazy IO. Use this
+-- with caution.
+withFile'
+  :: OsPath -> IOMode -> (Handle -> IO r) -> IO r
+withFile' fp iomode action = do
+  h <- openFile fp iomode
+  action h
+
+withBinaryFile'
+  :: OsPath -> IOMode -> (Handle -> IO r) -> IO r
+withBinaryFile' fp iomode action = do
+  h <- openBinaryFile fp iomode
+  action h
+
+-- | The 'readFile' function reads a file and returns the contents of the file
+-- as a 'ByteString'. The file is read lazily, on demand.
+readFile :: OsPath -> IO BSL.ByteString
+readFile fp = withFile' fp ReadMode BSL.hGetContents
+
+-- | The 'readFile'' function reads a file and returns the contents of the file
+-- as a 'ByteString'. The file is fully read before being returned.
+readFile'
+  :: OsPath -> IO BS.ByteString
+readFile' fp = withFile fp ReadMode BS.hGetContents
+
+-- | The computation 'writeFile' @file str@ function writes the lazy 'ByteString' @str@,
+-- to the file @file@.
+writeFile :: OsPath -> BSL.ByteString -> IO ()
+writeFile fp contents = withFile fp WriteMode (`BSL.hPut` contents)
+
+-- | The computation 'writeFile' @file str@ function writes the strict 'ByteString' @str@,
+-- to the file @file@.
+writeFile'
+  :: OsPath -> BS.ByteString -> IO ()
+writeFile' fp contents = withFile fp WriteMode (`BS.hPut` contents)
+
+-- | The computation 'appendFile' @file str@ function appends the lazy 'ByteString' @str@,
+-- to the file @file@.
+appendFile :: OsPath -> BSL.ByteString -> IO ()
+appendFile fp contents = withFile fp AppendMode (`BSL.hPut` contents)
+
+-- | The computation 'appendFile' @file str@ function appends the strict 'ByteString' @str@,
+-- to the file @file@.
+appendFile'
+  :: OsPath -> BS.ByteString -> IO ()
+appendFile' fp contents = withFile fp AppendMode (`BS.hPut` contents)
 
 -- | Open a file and return the 'Handle'.
 openFile :: OsPath -> IOMode -> IO Handle
diff --git a/System/File/PlatformPath.hs b/System/File/PlatformPath.hs
--- a/System/File/PlatformPath.hs
+++ b/System/File/PlatformPath.hs
@@ -1,28 +1,65 @@
-{-# LANGUAGE CPP #-}
-
 module System.File.PlatformPath where
 
-#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
-import qualified System.File.Windows as P
-#else
-import qualified System.File.Posix as P
-#endif
 
-import Control.Exception (bracket)
-import System.IO (IOMode(..), Handle, hSetBinaryMode, hClose)
+import System.IO (IOMode(..), Handle)
 import System.OsPath.Types
 
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Lazy as BSL
 
-#define FILE_PATH PlatformPath
-#include "Common.hs"
+import qualified System.File.OsPath as OsPath
+import System.OsString.Internal.Types
 
--- | Open a file and return the 'Handle'.
+import Data.Coerce (coerce)
+
+-- | Like `OsPath.openBinaryFile`, but takes a `PlatformPath` instead of an `OsPath`.
+openBinaryFile :: PlatformPath -> IOMode -> IO Handle
+openBinaryFile = OsPath.openBinaryFile . coerce
+
+-- | Like `OsPath.withFile`, but takes a `PlatformPath` instead of an `OsPath`.
+withFile :: PlatformPath -> IOMode -> (Handle -> IO r) -> IO r
+withFile = OsPath.withFile . coerce
+
+-- | Like `OsPath.withBinaryFile`, but takes a `PlatformPath` instead of an `OsPath`.
+withBinaryFile :: PlatformPath -> IOMode -> (Handle -> IO r) -> IO r
+withBinaryFile = OsPath.withBinaryFile . coerce
+
+-- | Like `OsPath.withFile'`, but takes a `PlatformPath` instead of an `OsPath`.
+withFile' :: PlatformPath -> IOMode -> (Handle -> IO r) -> IO r
+withFile' = OsPath.withFile' . coerce
+
+-- | Like `OsPath.withBinaryFile'`, but takes a `PlatformPath` instead of an `OsPath`.
+withBinaryFile' :: PlatformPath -> IOMode -> (Handle -> IO r) -> IO r
+withBinaryFile' = OsPath.withBinaryFile' . coerce
+
+-- | Like `OsPath.readFile`, but takes a `PlatformPath` instead of an `OsPath`.
+readFile :: PlatformPath -> IO BSL.ByteString
+readFile = OsPath.readFile . coerce
+
+-- | Like `OsPath.readFile'`, but takes a `PlatformPath` instead of an `OsPath`.
+readFile' :: PlatformPath -> IO BS.ByteString
+readFile' = OsPath.readFile' . coerce
+
+-- | Like `OsPath.writeFile`, but takes a `PlatformPath` instead of an `OsPath`.
+writeFile :: PlatformPath -> BSL.ByteString -> IO ()
+writeFile = OsPath.writeFile . coerce
+
+-- | Like `OsPath.writeFile'`, but takes a `PlatformPath` instead of an `OsPath`.
+writeFile' :: PlatformPath -> BS.ByteString -> IO ()
+writeFile' = OsPath.writeFile' . coerce
+
+-- | Like `OsPath.appendFile`, but takes a `PlatformPath` instead of an `OsPath`.
+appendFile :: PlatformPath -> BSL.ByteString -> IO ()
+appendFile = OsPath.appendFile . coerce
+
+-- | Like `OsPath.appendFile'`, but takes a `PlatformPath` instead of an `OsPath`.
+appendFile' :: PlatformPath -> BS.ByteString -> IO ()
+appendFile' = OsPath.appendFile' . coerce
+
+-- | Like `OsPath.openFile`, but takes a `PlatformPath` instead of an `OsPath`.
 openFile :: PlatformPath -> IOMode -> IO Handle
-openFile fp = P.openFile fp
+openFile = OsPath.openFile . coerce
 
--- | Open an existing file and return the 'Handle'.
+-- | Like `OsPath.openExistingFile`, but takes a `PlatformPath` instead of an `OsPath`.
 openExistingFile :: PlatformPath -> IOMode -> IO Handle
-openExistingFile fp = P.openExistingFile fp
-
+openExistingFile = OsPath.openExistingFile . coerce
diff --git a/System/File/Posix.hs b/System/File/Posix.hs
deleted file mode 100644
--- a/System/File/Posix.hs
+++ /dev/null
@@ -1,32 +0,0 @@
-module System.File.Posix where
-
-import System.IO (IOMode(..), Handle)
-import System.Posix.IO.PosixString
-    ( defaultFileFlags,
-      fdToHandle,
-      openFd,
-      OpenFileFlags(noctty, nonBlock, creat, append, trunc),
-      OpenMode(ReadWrite, ReadOnly, WriteOnly) )
-import System.OsPath.Posix ( PosixPath )
-
--- | Open a file and return the 'Handle'.
-openFile :: PosixPath -> IOMode -> IO Handle
-openFile fp iomode = fdToHandle =<< case iomode of
-  ReadMode      -> open ReadOnly  df
-  WriteMode     -> open WriteOnly df { trunc = True, creat = Just 0o666 }
-  AppendMode    -> open WriteOnly df { append = True, creat = Just 0o666 }
-  ReadWriteMode -> open ReadWrite df { creat = Just 0o666 }
- where
-  open = openFd fp
-  df = defaultFileFlags { noctty = True, nonBlock = True }
-
--- | Open an existing file and return the 'Handle'.
-openExistingFile :: PosixPath -> IOMode -> IO Handle
-openExistingFile fp iomode = fdToHandle =<< case iomode of
-  ReadMode      -> open ReadOnly  df
-  WriteMode     -> open WriteOnly df { trunc = True }
-  AppendMode    -> open WriteOnly df { append = True }
-  ReadWriteMode -> open ReadWrite df
- where
-  open = openFd fp
-  df = defaultFileFlags { noctty = True, nonBlock = True, creat = Nothing }
diff --git a/System/File/Windows.hs b/System/File/Windows.hs
deleted file mode 100644
--- a/System/File/Windows.hs
+++ /dev/null
@@ -1,111 +0,0 @@
-{-# LANGUAGE CPP #-}
-
-module System.File.Windows where
-
-import Control.Exception (bracketOnError)
-import Data.Bits
-import System.IO (IOMode(..), Handle)
-import System.OsPath.Windows ( WindowsPath )
-
-import qualified System.Win32 as Win32
-import qualified System.Win32.WindowsString.File as WS
-import Control.Monad (when, void)
-#if defined(__IO_MANAGER_WINIO__)
-import GHC.IO.SubSystem
-#endif
-
--- | Open a file and return the 'Handle'.
-openFile :: WindowsPath -> IOMode -> IO Handle
-openFile fp iomode = bracketOnError
-    (WS.createFile
-      fp
-      accessMode
-      shareMode
-      Nothing
-      createMode
-#if defined(__IO_MANAGER_WINIO__)
-      (case ioSubSystem of
-        IoPOSIX -> Win32.fILE_ATTRIBUTE_NORMAL
-        IoNative -> Win32.fILE_ATTRIBUTE_NORMAL .|. Win32.fILE_FLAG_OVERLAPPED
-      )
-#else
-      Win32.fILE_ATTRIBUTE_NORMAL
-#endif
-      Nothing)
-    Win32.closeHandle
-    toHandle
- where
-  toHandle h = do
-    when (iomode == AppendMode ) $ void $ Win32.setFilePointerEx h 0 Win32.fILE_END
-    Win32.hANDLEToHandle h
-  accessMode = case iomode of
-    ReadMode      -> Win32.gENERIC_READ
-    WriteMode     -> Win32.gENERIC_WRITE
-    AppendMode    -> Win32.gENERIC_WRITE .|. Win32.fILE_APPEND_DATA
-    ReadWriteMode -> Win32.gENERIC_READ .|. Win32.gENERIC_WRITE
-
-  createMode = case iomode of
-    ReadMode      -> Win32.oPEN_ALWAYS
-    WriteMode     -> Win32.cREATE_ALWAYS
-    AppendMode    -> Win32.oPEN_ALWAYS
-    ReadWriteMode -> Win32.oPEN_ALWAYS
-
-  shareMode = case iomode of
-    ReadMode      -> maxShareMode
-    WriteMode     -> writeShareMode
-    AppendMode    -> writeShareMode
-    ReadWriteMode -> maxShareMode
-
-maxShareMode :: Win32.ShareMode
-maxShareMode =
-  Win32.fILE_SHARE_DELETE .|.
-  Win32.fILE_SHARE_READ   .|.
-  Win32.fILE_SHARE_WRITE
-
-writeShareMode :: Win32.ShareMode
-writeShareMode =
-  Win32.fILE_SHARE_DELETE .|.
-  Win32.fILE_SHARE_READ
-
-  -- | Open an existing file and return the 'Handle'.
-openExistingFile :: WindowsPath -> IOMode -> IO Handle
-openExistingFile fp iomode = bracketOnError
-    (WS.createFile
-      fp
-      accessMode
-      shareMode
-      Nothing
-      createMode
-#if defined(__IO_MANAGER_WINIO__)
-      (case ioSubSystem of
-        IoPOSIX -> Win32.fILE_ATTRIBUTE_NORMAL
-        IoNative -> Win32.fILE_ATTRIBUTE_NORMAL .|. Win32.fILE_FLAG_OVERLAPPED
-      )
-#else
-      Win32.fILE_ATTRIBUTE_NORMAL
-#endif
-      Nothing)
-    Win32.closeHandle
-    toHandle
- where
-  toHandle h = do
-    when (iomode == AppendMode ) $ void $ Win32.setFilePointerEx h 0 Win32.fILE_END
-    Win32.hANDLEToHandle h
-  accessMode = case iomode of
-    ReadMode      -> Win32.gENERIC_READ
-    WriteMode     -> Win32.gENERIC_WRITE
-    AppendMode    -> Win32.gENERIC_WRITE .|. Win32.fILE_APPEND_DATA
-    ReadWriteMode -> Win32.gENERIC_READ .|. Win32.gENERIC_WRITE
-
-  createMode = case iomode of
-    ReadMode      -> Win32.oPEN_EXISTING
-    WriteMode     -> Win32.tRUNCATE_EXISTING
-    AppendMode    -> Win32.oPEN_EXISTING
-    ReadWriteMode -> Win32.oPEN_EXISTING
-
-  shareMode = case iomode of
-    ReadMode      -> maxShareMode
-    WriteMode     -> writeShareMode
-    AppendMode    -> writeShareMode
-    ReadWriteMode -> maxShareMode
-
diff --git a/file-io.cabal b/file-io.cabal
--- a/file-io.cabal
+++ b/file-io.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               file-io
-version:            0.1.0.1
+version:            0.1.0.2
 synopsis:           Basic file IO operations via 'OsPath'
 description:        Basic file IO operations like Prelude, but for 'OsPath'.
 homepage:           https://github.com/hasufell/file-io
@@ -12,30 +12,41 @@
 category:           System
 extra-source-files:
   CHANGELOG.md
-  System/File/Common.hs
 
 source-repository head
   type:     git
   location: https://github.com/hasufell/file-io.git
 
+flag os-string
+  description: Use the new os-string package
+  default: False
+  manual: False
+
 library
   default-language: Haskell2010
 
   if os(windows)
-    other-modules: System.File.Windows
+    hs-source-dirs: windows
     build-depends: Win32 >=2.13.3.0
 
   else
-    other-modules: System.File.Posix
+    hs-source-dirs: posix
     build-depends: unix >=2.8.0.0
 
+  hs-source-dirs: .
   build-depends:
-    , base        >=4.10      && <4.17
+    , base        >=4.10      && <5
     , bytestring  >=0.11.3.0
-    , filepath    >=1.4.100.0
 
+  if flag(os-string)
+    build-depends: filepath >= 1.5.0.0, os-string >= 2.0.0
+  else
+    build-depends: filepath >= 1.4.100.0 && < 1.5.0.0
+
   exposed-modules:
     System.File.OsPath
     System.File.PlatformPath
+
+  other-modules: System.File.Platform
 
   ghc-options:      -Wall
diff --git a/posix/System/File/Platform.hs b/posix/System/File/Platform.hs
new file mode 100644
--- /dev/null
+++ b/posix/System/File/Platform.hs
@@ -0,0 +1,32 @@
+module System.File.Platform where
+
+import System.IO (IOMode(..), Handle)
+import System.Posix.IO.PosixString
+    ( defaultFileFlags,
+      fdToHandle,
+      openFd,
+      OpenFileFlags(noctty, nonBlock, creat, append, trunc),
+      OpenMode(ReadWrite, ReadOnly, WriteOnly) )
+import System.OsPath.Posix ( PosixPath )
+
+-- | Open a file and return the 'Handle'.
+openFile :: PosixPath -> IOMode -> IO Handle
+openFile fp iomode = fdToHandle =<< case iomode of
+  ReadMode      -> open ReadOnly  df
+  WriteMode     -> open WriteOnly df { trunc = True, creat = Just 0o666 }
+  AppendMode    -> open WriteOnly df { append = True, creat = Just 0o666 }
+  ReadWriteMode -> open ReadWrite df { creat = Just 0o666 }
+ where
+  open = openFd fp
+  df = defaultFileFlags { noctty = True, nonBlock = True }
+
+-- | Open an existing file and return the 'Handle'.
+openExistingFile :: PosixPath -> IOMode -> IO Handle
+openExistingFile fp iomode = fdToHandle =<< case iomode of
+  ReadMode      -> open ReadOnly  df
+  WriteMode     -> open WriteOnly df { trunc = True }
+  AppendMode    -> open WriteOnly df { append = True }
+  ReadWriteMode -> open ReadWrite df
+ where
+  open = openFd fp
+  df = defaultFileFlags { noctty = True, nonBlock = True, creat = Nothing }
diff --git a/windows/System/File/Platform.hs b/windows/System/File/Platform.hs
new file mode 100644
--- /dev/null
+++ b/windows/System/File/Platform.hs
@@ -0,0 +1,111 @@
+{-# LANGUAGE CPP #-}
+
+module System.File.Platform where
+
+import Control.Exception (bracketOnError)
+import Data.Bits
+import System.IO (IOMode(..), Handle)
+import System.OsPath.Windows ( WindowsPath )
+
+import qualified System.Win32 as Win32
+import qualified System.Win32.WindowsString.File as WS
+import Control.Monad (when, void)
+#if defined(__IO_MANAGER_WINIO__)
+import GHC.IO.SubSystem
+#endif
+
+-- | Open a file and return the 'Handle'.
+openFile :: WindowsPath -> IOMode -> IO Handle
+openFile fp iomode = bracketOnError
+    (WS.createFile
+      fp
+      accessMode
+      shareMode
+      Nothing
+      createMode
+#if defined(__IO_MANAGER_WINIO__)
+      (case ioSubSystem of
+        IoPOSIX -> Win32.fILE_ATTRIBUTE_NORMAL
+        IoNative -> Win32.fILE_ATTRIBUTE_NORMAL .|. Win32.fILE_FLAG_OVERLAPPED
+      )
+#else
+      Win32.fILE_ATTRIBUTE_NORMAL
+#endif
+      Nothing)
+    Win32.closeHandle
+    toHandle
+ where
+  toHandle h = do
+    when (iomode == AppendMode ) $ void $ Win32.setFilePointerEx h 0 Win32.fILE_END
+    Win32.hANDLEToHandle h
+  accessMode = case iomode of
+    ReadMode      -> Win32.gENERIC_READ
+    WriteMode     -> Win32.gENERIC_WRITE
+    AppendMode    -> Win32.gENERIC_WRITE .|. Win32.fILE_APPEND_DATA
+    ReadWriteMode -> Win32.gENERIC_READ .|. Win32.gENERIC_WRITE
+
+  createMode = case iomode of
+    ReadMode      -> Win32.oPEN_ALWAYS
+    WriteMode     -> Win32.cREATE_ALWAYS
+    AppendMode    -> Win32.oPEN_ALWAYS
+    ReadWriteMode -> Win32.oPEN_ALWAYS
+
+  shareMode = case iomode of
+    ReadMode      -> maxShareMode
+    WriteMode     -> writeShareMode
+    AppendMode    -> writeShareMode
+    ReadWriteMode -> maxShareMode
+
+maxShareMode :: Win32.ShareMode
+maxShareMode =
+  Win32.fILE_SHARE_DELETE .|.
+  Win32.fILE_SHARE_READ   .|.
+  Win32.fILE_SHARE_WRITE
+
+writeShareMode :: Win32.ShareMode
+writeShareMode =
+  Win32.fILE_SHARE_DELETE .|.
+  Win32.fILE_SHARE_READ
+
+  -- | Open an existing file and return the 'Handle'.
+openExistingFile :: WindowsPath -> IOMode -> IO Handle
+openExistingFile fp iomode = bracketOnError
+    (WS.createFile
+      fp
+      accessMode
+      shareMode
+      Nothing
+      createMode
+#if defined(__IO_MANAGER_WINIO__)
+      (case ioSubSystem of
+        IoPOSIX -> Win32.fILE_ATTRIBUTE_NORMAL
+        IoNative -> Win32.fILE_ATTRIBUTE_NORMAL .|. Win32.fILE_FLAG_OVERLAPPED
+      )
+#else
+      Win32.fILE_ATTRIBUTE_NORMAL
+#endif
+      Nothing)
+    Win32.closeHandle
+    toHandle
+ where
+  toHandle h = do
+    when (iomode == AppendMode ) $ void $ Win32.setFilePointerEx h 0 Win32.fILE_END
+    Win32.hANDLEToHandle h
+  accessMode = case iomode of
+    ReadMode      -> Win32.gENERIC_READ
+    WriteMode     -> Win32.gENERIC_WRITE
+    AppendMode    -> Win32.gENERIC_WRITE .|. Win32.fILE_APPEND_DATA
+    ReadWriteMode -> Win32.gENERIC_READ .|. Win32.gENERIC_WRITE
+
+  createMode = case iomode of
+    ReadMode      -> Win32.oPEN_EXISTING
+    WriteMode     -> Win32.tRUNCATE_EXISTING
+    AppendMode    -> Win32.oPEN_EXISTING
+    ReadWriteMode -> Win32.oPEN_EXISTING
+
+  shareMode = case iomode of
+    ReadMode      -> maxShareMode
+    WriteMode     -> writeShareMode
+    AppendMode    -> writeShareMode
+    ReadWriteMode -> maxShareMode
+
