diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 0.8.18.2
+
+* Handle non-ASCII filenames correctly on Windows [#91](https://github.com/snoyberg/yaml/pull/91)
+
 ## 0.8.18.1
 
 * Improve prettyPrintParseException when context is empty [#89](https://github.com/snoyberg/yaml/pull/89)
diff --git a/Text/Libyaml.hs b/Text/Libyaml.hs
--- a/Text/Libyaml.hs
+++ b/Text/Libyaml.hs
@@ -29,6 +29,7 @@
 
 import Prelude hiding (pi)
 
+import Data.Bits ((.|.))
 import Foreign.C
 import Foreign.Ptr
 import Foreign.ForeignPtr
@@ -36,6 +37,7 @@
 import Foreign.ForeignPtr.Unsafe
 #endif
 import Foreign.Marshal.Alloc
+import qualified System.Posix.Internals as Posix
 
 #if !MIN_VERSION_base(4,8,0)
 import Control.Applicative
@@ -147,11 +149,10 @@
 data FileStruct
 type File = Ptr FileStruct
 
-foreign import ccall unsafe "fopen"
-    c_fopen :: Ptr CChar
-            -> Ptr CChar
-            -> IO File
-
+foreign import ccall unsafe "fdopen"
+    c_fdopen :: CInt
+             -> Ptr CChar
+             -> IO File
 foreign import ccall unsafe "fclose"
     c_fclose :: File
              -> IO ()
@@ -503,6 +504,24 @@
         c_yaml_parser_delete ptr
         free ptr
 
+-- XXX copied from GHC.IO.FD
+std_flags, read_flags, output_flags, write_flags :: CInt
+std_flags    = Posix.o_NOCTTY
+output_flags = std_flags    .|. Posix.o_CREAT
+read_flags   = std_flags    .|. Posix.o_RDONLY
+write_flags  = output_flags .|. Posix.o_WRONLY
+
+-- | Open a C FILE* from a file path, using internal GHC API to work correctly
+-- on all platforms, even on non-ASCII filenames. The opening mode must be
+-- indicated via both 'rawOpenFlags' and 'openMode'.
+openFile :: FilePath -> CInt -> String -> IO File
+openFile file rawOpenFlags openMode = do
+  fd <- liftIO $ Posix.withFilePath file $ \file' ->
+    Posix.c_open file' rawOpenFlags 0o666
+  if fd /= (-1)
+    then withCString openMode $ \openMode' -> c_fdopen fd openMode'
+    else return nullPtr
+
 decodeFile :: MonadResource m => FilePath
 #if MIN_VERSION_conduit(1, 0, 0)
            -> Producer m Event
@@ -521,12 +540,9 @@
                 free ptr
                 throwIO $ YamlException "Yaml out of memory"
             else do
-                file' <- liftIO
-                        $ withCString file $ \file' -> withCString "r" $ \r' ->
-                                c_fopen file' r'
+                file' <- openFile file read_flags "r"
                 if file' == nullPtr
                     then do
-                        c_fclose_helper file'
                         c_yaml_parser_delete ptr
                         free ptr
                         throwIO $ YamlException
@@ -599,9 +615,7 @@
     bracketP getFile c_fclose $ \file -> runEmitter (alloc file) (\u _ -> return u)
   where
     getFile = do
-        file <- withCString filePath $
-                    \filePath' -> withCString "w" $
-                    \w' -> c_fopen filePath' w'
+        file <- openFile filePath write_flags "w"
         if file == nullPtr
             then throwIO $ YamlException $ "could not open file for write: " ++ filePath
             else return file
diff --git a/c/helper.c b/c/helper.c
--- a/c/helper.c
+++ b/c/helper.c
@@ -13,10 +13,10 @@
 {
 	buffer_t *b = ext;
 	int new_size, new_used;
-	char *tmp;
+	unsigned char *tmp;
 
 	new_used = b->used + size;
-	for (new_size = b->size || 8; new_size < new_used; new_size *= 2);
+	for (new_size = b->size ? b->size : 8; new_size < new_used; new_size *= 2);
 
 	if (new_size != b->size) {
 		tmp = realloc(b->buff, new_size);
@@ -46,12 +46,12 @@
 	yaml_emitter_set_output(e, buffer_append, b);
 }
 
-unsigned char const * get_parser_error_problem(yaml_parser_t *p)
+char const * get_parser_error_problem(yaml_parser_t *p)
 {
 	return p->problem;
 }
 
-unsigned char const * get_parser_error_context(yaml_parser_t *p)
+char const * get_parser_error_context(yaml_parser_t *p)
 {
 	return p->context;
 }
@@ -71,7 +71,7 @@
 	return p->problem_mark.column;
 }
 
-unsigned char const * get_emitter_error(yaml_emitter_t *e)
+char const * get_emitter_error(yaml_emitter_t *e)
 {
 	return e->problem;
 }
@@ -104,13 +104,13 @@
 unsigned char * get_scalar_tag(yaml_event_t *e)
 {
 	unsigned char *s = e->data.scalar.tag;
-	if (!s) s = "";
+	if (!s) s = (unsigned char *) "";
 	return s;
 }
 
 unsigned long get_scalar_tag_len(yaml_event_t *e)
 {
-	return strlen(get_scalar_tag(e));
+	return strlen((char *) get_scalar_tag(e));
 }
 
 int get_scalar_style(yaml_event_t *e)
@@ -143,6 +143,7 @@
 	FILE *in = fopen(filename, "r");
 	if (!in) return 0;
 	yaml_parser_set_input_file(parser, in);
+	return 1;
 }
 
 int fclose_helper(FILE *file)
diff --git a/c/helper.h b/c/helper.h
--- a/c/helper.h
+++ b/c/helper.h
@@ -14,11 +14,11 @@
 
 void my_emitter_set_output(yaml_emitter_t *e, buffer_t *b);
 
-unsigned char const * get_parser_error_problem(yaml_parser_t *p);
-unsigned char const * get_parser_error_context(yaml_parser_t *p);
+char const * get_parser_error_problem(yaml_parser_t *p);
+char const * get_parser_error_context(yaml_parser_t *p);
 unsigned int    get_parser_error_offset(yaml_parser_t *p);
 
-unsigned char const * get_emitter_error(yaml_emitter_t *e);
+char const * get_emitter_error(yaml_emitter_t *e);
 
 int simple_document_start(yaml_event_t *e);
 
diff --git a/examples/Config.hs b/examples/Config.hs
--- a/examples/Config.hs
+++ b/examples/Config.hs
@@ -9,6 +9,7 @@
 import Text.RawString.QQ
 import Data.ByteString (ByteString)
 import Control.Applicative
+import Prelude -- Ensure Applicative is in scope and we have no warnings, before/after AMP.
 
 configYaml :: ByteString
 configYaml = [r|
diff --git a/test/Data/YamlSpec.hs b/test/Data/YamlSpec.hs
--- a/test/Data/YamlSpec.hs
+++ b/test/Data/YamlSpec.hs
@@ -19,6 +19,7 @@
 import Control.Exception (try, SomeException)
 import Test.Hspec
 import Data.Either.Compat
+import System.Directory (createDirectory)
 import Test.Mockery.Directory
 
 import qualified Data.Yaml as D
@@ -63,6 +64,7 @@
     describe "Data.Yaml" $ do
         it "encode/decode" caseEncodeDecodeData
         it "encode/decode file" caseEncodeDecodeFileData
+        it "encode/decode files with non-ASCII names" caseEncodeDecodeNonAsciiFileData
         it "encode/decode strings" caseEncodeDecodeStrings
         it "decode invalid file" caseDecodeInvalid
         it "processes datatypes" caseDataTypes
@@ -316,6 +318,17 @@
     D.encodeFile fp sample
     out <- D.decodeFile fp
     out @?= Just sample
+
+caseEncodeDecodeNonAsciiFileData :: Assertion
+caseEncodeDecodeNonAsciiFileData = do
+  let mySample = (object ["foo" .= True])
+  inTempDirectory $ do
+    createDirectory "accenté"
+    D.encodeFile "accenté/bar.yaml" mySample
+    out1 <- D.decodeFile "accenté/bar.yaml"
+    out1 @?= Just mySample
+  out2 <- D.decodeFile "test/resources/accenté/foo.yaml"
+  out2 @?= Just mySample
 
 caseEncodeDecodeStrings :: Assertion
 caseEncodeDecodeStrings = do
diff --git a/test/resources/accente/foo.yaml b/test/resources/accente/foo.yaml
new file mode 100644
--- /dev/null
+++ b/test/resources/accente/foo.yaml
@@ -0,0 +1,1 @@
+foo: true
diff --git a/yaml.cabal b/yaml.cabal
--- a/yaml.cabal
+++ b/yaml.cabal
@@ -1,5 +1,5 @@
 name:            yaml
-version:         0.8.18.1
+version:         0.8.18.2
 license:         BSD3
 license-file:    LICENSE
 author:          Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov 
@@ -20,6 +20,7 @@
                     test/resources/foo.yaml
                     test/resources/bar.yaml
                     test/resources/baz.yaml
+                    test/resources/accenté/foo.yaml
                     test/resources/loop/foo.yaml
                     test/resources/loop/bar.yaml
                     README.md
@@ -130,6 +131,7 @@
                    , text
                    , aeson >= 0.7
                    , unordered-containers
+                   , directory
                    , vector
                    , resourcet
                    , aeson-qq
