Index: src/file.c
==================================================================
--- src/file.c
+++ src/file.c
@@ -72,13 +72,13 @@
   }else{
     return stat(zFilename, buf);
   }
 #else
   int rc = 0;
-  wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename);
+  wchar_t *zMbcs = fossil_utf8_to_filename(zFilename);
   rc = _wstati64(zMbcs, buf);
-  fossil_unicode_free(zMbcs);
+  fossil_filename_free(zMbcs);
   return rc;
 #endif
 }
 
 /*
@@ -303,13 +303,13 @@
 /*
 ** Wrapper around the access() system call.
 */
 int file_access(const char *zFilename, int flags){
 #ifdef _WIN32
-  wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename);
+  wchar_t *zMbcs = fossil_utf8_to_filename(zFilename);
   int rc = _waccess(zMbcs, flags);
-  fossil_unicode_free(zMbcs);
+  fossil_filename_free(zMbcs);
 #else
   int rc = access(zFilename, flags);
 #endif
   return rc;
 }
@@ -405,15 +405,15 @@
   tv[0].tv_sec = newMTime;
   tv[1].tv_sec = newMTime;
   utimes(zFilename, tv);
 #else
   struct _utimbuf tb;
-  wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename);
+  wchar_t *zMbcs = fossil_utf8_to_filename(zFilename);
   tb.actime = newMTime;
   tb.modtime = newMTime;
   _wutime(zMbcs, &tb);
-  fossil_unicode_free(zMbcs);
+  fossil_filename_free(zMbcs);
 #endif
 }
 
 /*
 ** COMMAND: test-set-mtime
@@ -441,13 +441,13 @@
 /*
 ** Delete a file.
 */
 void file_delete(const char *zFilename){
 #ifdef _WIN32
-  wchar_t *z = fossil_utf8_to_unicode(zFilename);
+  wchar_t *z = fossil_utf8_to_filename(zFilename);
   _wunlink(z);
-  fossil_unicode_free(z);
+  fossil_filename_free(z);
 #else
   unlink(zFilename);
 #endif
 }
 
@@ -465,13 +465,13 @@
     file_delete(zName);
   }
   if( rc!=1 ){
 #if defined(_WIN32)
     int rc;
-    wchar_t *zMbcs = fossil_utf8_to_unicode(zName);
+    wchar_t *zMbcs = fossil_utf8_to_filename(zName);
     rc = _wmkdir(zMbcs);
-    fossil_unicode_free(zMbcs);
+    fossil_filename_free(zMbcs);
     return rc;
 #else
     return mkdir(zName, 0755);
 #endif
   }
@@ -1121,13 +1121,13 @@
 ** Return the value of an environment variable as UTF8.
 ** Use fossil_filename_free() to release resources.
 */
 char *fossil_getenv(const char *zName){
 #ifdef _WIN32
-  wchar_t *uName = fossil_utf8_to_unicode(zName);
+  wchar_t *uName = fossil_utf8_to_filename(zName);
   void *zValue = _wgetenv(uName);
-  fossil_unicode_free(uName);
+  fossil_filename_free(uName);
 #else
   char *zValue = getenv(zName);
 #endif
   if( zValue ) zValue = fossil_filename_to_utf8(zValue);
   return zValue;
@@ -1137,14 +1137,14 @@
 ** Like fopen() but always takes a UTF8 argument.
 */
 FILE *fossil_fopen(const char *zName, const char *zMode){
 #ifdef _WIN32
   wchar_t *uMode = fossil_utf8_to_unicode(zMode);
-  wchar_t *uName = fossil_utf8_to_unicode(zName);
+  wchar_t *uName = fossil_utf8_to_filename(zName);
   FILE *f = _wfopen(uName, uMode);
-  fossil_unicode_free(uName);
+  fossil_filename_free(uName);
   fossil_unicode_free(uMode);
 #else
   FILE *f = fopen(zName, zMode);
 #endif
   return f;
 }

Index: src/rebuild.c
==================================================================
--- src/rebuild.c
+++ src/rebuild.c
@@ -841,11 +841,11 @@
   Blob aContent; /* content of the just read artifact */
   static int nFileRead = 0;
   void *zUnicodePath;
   char *zUtf8Name;
 
-  zUnicodePath = fossil_utf8_to_unicode(zPath);
+  zUnicodePath = fossil_utf8_to_filename(zPath);
   d = opendir(zUnicodePath);
   if( d ){
     while( (pEntry=readdir(d))!=0 ){
       Blob path;
       char *zSubpath;
@@ -875,11 +875,11 @@
     closedir(d);
   }else {
     fossil_panic("encountered error %d while trying to open \"%s\".",
                   errno, g.argv[3]);
   }
-  fossil_unicode_free(zUnicodePath);
+  fossil_filename_free(zUnicodePath);
 }
 
 /*
 ** COMMAND: reconstruct*
 **

Index: src/utf8.c
==================================================================
--- src/utf8.c
+++ src/utf8.c
@@ -24,34 +24,27 @@
 #include <sqlite3.h>
 #ifdef _WIN32
 # include <windows.h>
 #endif
 
+#ifdef _WIN32
 /*
 ** Translate MBCS to UTF8.  Return a pointer to the translated text.
 ** Call fossil_mbcs_free() to deallocate any memory used to store the
 ** returned pointer when done.
 */
 char *fossil_mbcs_to_utf8(const char *zMbcs){
-#ifdef _WIN32
   extern char *sqlite3_win32_mbcs_to_utf8(const char*);
   return sqlite3_win32_mbcs_to_utf8(zMbcs);
-#else
-  return (char*)zMbcs;  /* No-op on unix */
-#endif
 }
 
 /*
 ** After translating from UTF8 to MBCS, invoke this routine to deallocate
 ** any memory used to hold the translation
 */
 void fossil_mbcs_free(char *zOld){
-#ifdef _WIN32
   sqlite3_free(zOld);
-#else
-  /* No-op on unix */
-#endif
 }
 
 /*
 ** Translate Unicode text into UTF8.
 ** Return a pointer to the translated text.
@@ -66,11 +59,11 @@
     return 0;
   }
   WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0);
   return zUtf;
 #else
-  return (char *)zUnicode;  /* No-op on unix */
+  return (char *)zUnicode;  /* TODO: implement for unix */
 #endif
 }
 
 /*
 ** Translate UTF8 to unicode for use in system calls.  Return a pointer to the
@@ -85,11 +78,11 @@
     return 0;
   }
   MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
   return zUnicode;
 #else
-  return (void *)zUtf8;  /* No-op on unix */
+  return (void *)zUtf8;  /* TODO: implement for unix */
 #endif
 }
 
 /*
 ** Deallocate any memory that was previously allocated by
@@ -97,13 +90,14 @@
 */
 void fossil_unicode_free(void *pOld){
 #ifdef _WIN32
   sqlite3_free(pOld);
 #else
-  /* No-op on unix */
+  /* TODO: implement for unix */
 #endif
 }
+#endif /* _WIN32 */
 
 #if defined(__APPLE__) && !defined(WITHOUT_ICONV)
 # include <iconv.h>
 #endif
 
@@ -149,16 +143,38 @@
   return zOut;
 #else
   return (char *)zFilename;  /* No-op on non-mac unix */
 #endif
 }
+
+/*
+** Translate UTF8 to unicode for use in filename translations.
+** Return a pointer to the translated text..  Call fossil_filename_free()
+** to deallocate any memory used to store the returned pointer when done.
+**
+*/
+void *fossil_utf8_to_filename(const char *zUtf8){
+#ifdef _WIN32
+  int nByte = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
+  wchar_t *zUnicode = sqlite3_malloc( nByte * 2 );
+  if( zUnicode==0 ){
+    return 0;
+  }
+  MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
+  return zUnicode;
+#elif defined(__APPLE__) && !defined(WITHOUT_ICONV)
+  return fossil_strdup(zUtf8);
+#else
+  return (void *)zUtf8;  /* No-op on unix */
+#endif
+}
 
 /*
 ** Deallocate any memory that was previously allocated by
-** fossil_filename_to_utf8().
+** fossil_filename_to_utf8() or fossil_utf8_to_filename().
 */
-void fossil_filename_free(char *pOld){
+void fossil_filename_free(void *pOld){
 #if defined(_WIN32)
   sqlite3_free(pOld);
 #elif defined(__APPLE__) && !defined(WITHOUT_ICONV)
   fossil_free(pOld);
 #else

Index: src/vfile.c
==================================================================
--- src/vfile.c
+++ src/vfile.c
@@ -459,11 +459,11 @@
     );
   }
   depth++;
 
   zDir = blob_str(pPath);
-  zNative = fossil_utf8_to_unicode(zDir);
+  zNative = fossil_utf8_to_filename(zDir);
   d = opendir(zNative);
   if( d ){
     while( (pEntry=readdir(d))!=0 ){
       char *zPath;
       char *zUtf8;
@@ -491,11 +491,11 @@
       fossil_filename_free(zUtf8);
       blob_resize(pPath, origSize);
     }
     closedir(d);
   }
-  fossil_unicode_free(zNative);
+  fossil_filename_free(zNative);
 
   depth--;
   if( depth==0 ){
     db_finalize(&ins);
   }