diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,10 @@
+haskell-libmagic (1.3.1) unstable; urgency=medium
+
+  * Fix filename encoding on Windows reversion.
+  * Added magicFD.
+
+ -- Joey Hess <id@joeyh.name>  Tue, 27 Oct 2026 19:28:00 -0400
+
 haskell-libmagic (1.3) unstable; urgency=medium
 
   * Use ByteString for magic results, rather than String
diff --git a/Magic/Init.hsc b/Magic/Init.hsc
--- a/Magic/Init.hsc
+++ b/Magic/Init.hsc
@@ -20,7 +20,7 @@
 Written by John Goerzen, jgoerzen\@complete.org
 -}
 
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE QuasiQuotes #-}
 
 module Magic.Init(magicOpen, magicLoad, magicLoadDefault)
 where
@@ -32,9 +32,8 @@
 import Magic.Utils
 import Magic.TypesLL
 import qualified Data.List.NonEmpty as NE
+import System.OsString
 import System.OsPath.Types
-import System.OsString.Internal.Types
-import Data.Type.Coercion
 import qualified Data.ByteString.Short as SBS
 
 {- | Create a Magic object.  You must call either 'magicLoadDefault'
@@ -52,15 +51,12 @@
 
 {- | Load the specified magic databases. -}
 magicLoad :: Magic -> NE.NonEmpty OsPath -> IO ()
-magicLoad m l = withMagicPtr m $ \cmagic ->
-    SBS.useAsCString s $ \cs ->
+magicLoad m l = withMagicPtr m $ \cmagic -> do
+    sbs <- decodeOsPath s
+    SBS.useAsCString sbs $ \cs ->
      checkIntError "magicLoad" cmagic $ magic_load cmagic cs
   where
-    s = SBS.intercalate ":" (map conv (NE.toList l))
-
-    conv p = case coercionToPlatformTypes of
-        Left (_, co) -> getWindowsString (coerceWith co p)
-        Right (_, co) -> getPosixString (coerceWith co p)
+    s = intercalate [osstr|:|] (NE.toList l)
 
 foreign import ccall unsafe "magic.h magic_open"
   magic_open :: CInt -> IO (Ptr CMagic)
diff --git a/Magic/Operations.hsc b/Magic/Operations.hsc
--- a/Magic/Operations.hsc
+++ b/Magic/Operations.hsc
@@ -21,7 +21,7 @@
 -}
 
 module Magic.Operations(-- * Guessing the type
-                        magicFile, magicStdin,
+                        magicFile, magicStdin, magicFD,
                         magicString, magicCString,
                         -- * Other operations
                         magicSetFlags)
@@ -35,22 +35,18 @@
 import Magic.Utils
 import Magic.TypesLL
 import System.OsPath.Types
-import System.OsString.Internal.Types
-import Data.Type.Coercion
+import GHC.IO.FD
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Short as SBS
 
 {- | Calls the Magic system on the specified file. -}
 magicFile :: Magic -> OsPath -> IO BS.ByteString
 magicFile magic fp =
-    withMagicPtr magic $ \cmagic ->
+    withMagicPtr magic $ \cmagic -> do
+      sbsfp <- decodeOsPath fp
       SBS.useAsCString sbsfp $ \cfp -> do
         res <- throwErrorIfNull "magicFile" cmagic (magic_file cmagic cfp)
         BS.packCString res
-  where
-      sbsfp = case coercionToPlatformTypes of
-        Left (_, co) -> getWindowsString (coerceWith co fp)
-        Right (_, co) -> getPosixString (coerceWith co fp)
 
 {- | Calls the Magic system on stdin. -}
 magicStdin :: Magic -> IO BS.ByteString
@@ -59,6 +55,13 @@
      do res <- throwErrorIfNull "magicStdin" cmagic (magic_file cmagic nullPtr)
         BS.packCString res
 
+{- | Calls the Magic system on the contents of the file descriptor. -}
+magicFD :: Magic -> FD -> IO BS.ByteString
+magicFD magic fd =
+    withMagicPtr magic $ \cmagic ->
+     do res <- throwErrorIfNull "magicFD" cmagic (magic_descriptor cmagic (fdFD fd))
+        BS.packCString res
+
 {- | Calls the Magic system to process the given String.  Please note:
 it is not evaluated lazily. -}
 magicString :: Magic -> String -> IO BS.ByteString
@@ -81,6 +84,10 @@
 -- Does file I/O -> safe
 foreign import ccall safe "magic.h magic_file"
   magic_file :: Ptr CMagic -> CString -> IO CString
+
+-- Does file I/O -> safe
+foreign import ccall safe "magic.h magic_descriptor"
+  magic_descriptor :: Ptr CMagic -> CInt -> IO CString
 
 -- Does not do I/O -> unsafe
 foreign import ccall unsafe "magic.h magic_buffer"
diff --git a/Magic/Utils.hsc b/Magic/Utils.hsc
--- a/Magic/Utils.hsc
+++ b/Magic/Utils.hsc
@@ -21,7 +21,7 @@
 -}
 
 module Magic.Utils (flaglist2int, fromMagicPtr, withMagicPtr, checkIntError,
-                    throwErrorIfNull)
+                    throwErrorIfNull, decodeOsPath)
 where
 
 import Foreign
@@ -31,6 +31,11 @@
 import Magic.Types
 import Foreign.C.Types
 import Control.Concurrent.MVar
+import System.OsPath.Types
+import System.OsString.Internal.Types
+import System.OsString.Encoding
+import Data.Type.Coercion
+import qualified Data.ByteString.Short as SBS
 
 flaglist2int :: [MagicFlag] -> CInt
 flaglist2int mfl =
@@ -68,6 +73,16 @@
           then return ()
           else throwError caller cmagic
 
+decodeOsPath :: OsPath -> IO (SBS.ShortByteString)
+decodeOsPath p = case coercionToPlatformTypes of
+    Right (_, co) -> return (getPosixString (coerceWith co p))
+    -- libmagic built for windows with MinGW by eg
+    -- https://github.com/nscaife/file-windows does not use
+    -- wide bytes as are in WindowsString, so convert it using
+    -- the locale encoding
+    Left (_, co) ->
+            encodeWithBasePosix' =<< decodeWithBaseWindows
+                (getWindowsString (coerceWith co p))
 
 foreign import ccall unsafe "magic.h &magic_close"
   magic_close :: FunPtr (Ptr CMagic -> IO ())
diff --git a/libmagic.cabal b/libmagic.cabal
--- a/libmagic.cabal
+++ b/libmagic.cabal
@@ -1,5 +1,5 @@
 Name: libmagic
-Version: 1.3
+Version: 1.3.1
 Cabal-Version: >= 1.10
 License: BSD3
 Maintainer: Joey Hess <id@joeyh.name>
