Bug 1440278 - port bug 1428258 to mailnews: Stop using GetNativePath(). r=jorgk
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Fri, 23 Feb 2018 00:04:39 +0900
changeset 31157 1580fa402264dd3b467389b4c141f480a683e514
parent 31156 552fd5ab0b444663219016fc19c824f93008dc46
child 31158 c6418eab10bc0b2bf89e11427786a7b5cb0b4bb2
push id383
push userclokep@gmail.com
push dateMon, 07 May 2018 21:52:48 +0000
reviewersjorgk
bugs1440278, 1428258
Bug 1440278 - port bug 1428258 to mailnews: Stop using GetNativePath(). r=jorgk
db/mork/public/mdb.h
db/mork/src/morkConfig.h
db/mork/src/morkEnv.cpp
db/mork/src/morkEnv.h
db/mork/src/morkFactory.cpp
db/mork/src/morkFactory.h
db/mork/src/morkFile.cpp
db/mork/src/morkFile.h
db/mork/src/morkSink.cpp
db/mork/src/morkStore.cpp
db/mork/src/morkStream.cpp
mailnews/addrbook/src/nsAddrDatabase.cpp
mailnews/addrbook/src/nsAddrDatabase.h
mailnews/base/src/nsMessenger.cpp
mailnews/base/src/nsMessenger.h
mailnews/base/src/nsMsgFolderCache.cpp
mailnews/base/src/nsMsgFolderCache.h
mailnews/compose/src/nsMsgCompUtils.cpp
mailnews/compose/src/nsMsgCompose.cpp
mailnews/db/msgdb/public/nsMsgDatabase.h
mailnews/db/msgdb/src/nsMsgDatabase.cpp
mailnews/imap/src/nsImapMailFolder.cpp
mailnews/import/outlook/src/MapiApi.cpp
mailnews/import/outlook/src/MapiApi.h
mailnews/import/outlook/src/MapiMessage.cpp
mailnews/local/src/nsLocalUtils.cpp
mailnews/local/src/nsMailboxService.cpp
--- a/db/mork/public/mdb.h
+++ b/db/mork/public/mdb.h
@@ -34,16 +34,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _MDB_
 #define _MDB_ 1
 
+#include "mozilla/Path.h"
 #include "nscore.h"
 #include "nsISupports.h"
 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
 
 // { %%%%% begin scalar typedefs %%%%%
 typedef unsigned char  mdb_u1;  // make sure this is one byte
 typedef unsigned short mdb_u2;  // make sure this is two bytes
 typedef short          mdb_i2;  // make sure this is two bytes
@@ -643,34 +644,35 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMdbEnv,
 #define NS_IMDBFACTORY_IID_STR "2b80395c-b91e-4990-b1a7-023e99ab14e9"
 
 #define NS_IMDBFACTORY_IID \
 {0xf04aa4ab, 0x1fe, 0x4115, \
 { 0xa4, 0xa5, 0x68, 0x19, 0xdf, 0xf1, 0x10, 0x3d}}
 
 
 class nsIMdbFactory : public nsISupports { // suite entry points
+  using PathChar = mozilla::filesystem::Path::value_type;
 public:
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMDBFACTORY_IID)
 // { ===== begin nsIMdbFactory methods =====
 
   // { ----- begin file methods -----
   NS_IMETHOD OpenOldFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap,
-    const char* inFilePath,
+    const PathChar* inFilePath,
     mdb_bool inFrozen, nsIMdbFile** acqFile) = 0;
   // Choose some subclass of nsIMdbFile to instantiate, in order to read
   // (and write if not frozen) the file known by inFilePath.  The file
   // returned should be open and ready for use, and presumably positioned
   // at the first byte position of the file.  The exact manner in which
   // files must be opened is considered a subclass specific detail, and
   // other portions or Mork source code don't want to know how it's done.
 
   NS_IMETHOD CreateNewFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap,
-    const char* inFilePath,
+    const PathChar* inFilePath,
     nsIMdbFile** acqFile) = 0;
   // Choose some subclass of nsIMdbFile to instantiate, in order to read
   // (and write if not frozen) the file known by inFilePath.  The file
   // returned should be created and ready for use, and presumably positioned
   // at the first byte position of the file.  The exact manner in which
   // files must be opened is considered a subclass specific detail, and
   // other portions or Mork source code don't want to know how it's done.
   // } ----- end file methods -----
--- a/db/mork/src/morkConfig.h
+++ b/db/mork/src/morkConfig.h
@@ -53,19 +53,23 @@
 #define MORK_FILEREAD(outbuf, insize, file) fread(outbuf, 1, insize, file) 
 #if defined(MORK_WIN)
 void mork_fileflush(FILE * file);
 #define MORK_FILEFLUSH(file) mork_fileflush(file) 
 #else
 #define MORK_FILEFLUSH(file) fflush(file) 
 #endif /*MORK_WIN*/
 
-#define MORK_FILEOPEN(file, how) fopen(file, how) 
+#if defined(MORK_WIN)
+#define MORK_FILEOPEN(file, how) _wfopen(char16ptr_t(file), NS_ConvertASCIItoUTF16(how).get())
+#else
+#define MORK_FILEOPEN(file, how) fopen(file, how)
+#endif /*MORK_WIN*/
 #define MORK_FILECLOSE(file) fclose(file) 
-#endif /*MORK_WIN*/
+#endif /*defined(MORK_WIN) || defined(MORK_UNIX) || defined(MORK_MAC)*/
 
 /* ===== separating switchable features ===== */
 
 #define MORK_ENABLE_ZONE_ARENAS 1 /* using morkZone for pooling */
 
 //#define MORK_ENABLE_PROBE_MAPS 1 /* use smaller hash tables */
 
 #define MORK_BEAD_OVER_NODE_MAPS 1 /* use bead not node maps */
@@ -118,20 +122,28 @@ extern void mork_assertion_signal(const 
 #define MORK_USE_C_STDLIB 1
 #endif /*MORK_WIN*/
 
 #ifdef MORK_USE_C_STDLIB
 #define MORK_MEMCMP(src1,src2,size)  memcmp(src1,src2,size)
 #define MORK_MEMCPY(dest,src,size)   memcpy(dest,src,size)
 #define MORK_MEMMOVE(dest,src,size)  memmove(dest,src,size)
 #define MORK_MEMSET(dest,byte,size)  memset(dest,byte,size)
+#if defined(MORK_WIN)
+#define MORK_STRCPY(dest,src)        wcscpy(char16ptr_t(dest),char16ptr_t(src))
+#else
 #define MORK_STRCPY(dest,src)        strcpy(dest,src)
+#endif /*MORK_WIN*/
 #define MORK_STRCMP(one,two)         strcmp(one,two)
 #define MORK_STRNCMP(one,two,length) strncmp(one,two,length)
+#if defined(MORK_WIN)
+#define MORK_STRLEN(string)          wcslen(char16ptr_t(string))
+#else
 #define MORK_STRLEN(string)          strlen(string)
+#endif /*MORK_WIN*/
 #endif /*MORK_USE_C_STDLIB*/
 
 #ifdef MORK_PROVIDE_STDLIB
 MORK_LIB(mork_i4) mork_memcmp(const void* a, const void* b, mork_size inSize);
 MORK_LIB(void) mork_memcpy(void* dst, const void* src, mork_size inSize);
 MORK_LIB(void) mork_memmove(void* dst, const void* src, mork_size inSize);
 MORK_LIB(void) mork_memset(void* dst, int inByte, mork_size inSize);
 MORK_LIB(void) mork_strcpy(void* dst, const void* src);
--- a/db/mork/src/morkEnv.cpp
+++ b/db/mork/src/morkEnv.cpp
@@ -22,16 +22,18 @@
 #ifndef _MORKENV_
 #include "morkEnv.h"
 #endif
 
 #ifndef _MORKFACTORY_
 #include "morkFactory.h"
 #endif
 
+#include "mozilla/Char16.h"
+
 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
 
 // ````` ````` ````` ````` ````` 
 // { ===== begin morkNode interface =====
 
 /*public virtual*/ void
 morkEnv::CloseMorkNode(morkEnv* ev) /*i*/ // CloseEnv() only if open
 {
@@ -283,21 +285,21 @@ morkEnv::TokenAsHex(void* outBuf, mork_t
   {
     *p++ = '0'; // write a zero digit
     *p = 0; // end with a null byte
     return 1; // one digit in hex representation
   }
 }
 
 void
-morkEnv::StringToYarn(const char* inString, mdbYarn* outYarn)
+morkEnv::StringToYarn(const PathChar* inString, mdbYarn* outYarn)
 {
   if ( outYarn )
   {
-    mdb_fill fill = ( inString )? (mdb_fill) MORK_STRLEN(inString) : 0; 
+    mdb_fill fill = ( inString )? (mdb_fill) MORK_STRLEN(inString) * sizeof(PathChar) : 0; 
       
     if ( fill ) // have nonempty content?
     {
       mdb_size size = outYarn->mYarn_Size; // max dest size
       if ( fill > size ) // too much string content?
       {
         outYarn->mYarn_More = fill - size; // extra string bytes omitted
         fill = size; // copy no more bytes than size of yarn buffer
@@ -316,34 +318,34 @@ morkEnv::StringToYarn(const char* inStri
       outYarn->mYarn_Fill = 0; // tell yarn that string has no bytes
     }
     outYarn->mYarn_Form = 0; // always update the form slot
   }
   else
     this->NilPointerError();
 }
 
-char*
-morkEnv::CopyString(nsIMdbHeap* ioHeap, const char* inString)
+morkEnv::PathChar*
+morkEnv::CopyString(nsIMdbHeap* ioHeap, const PathChar* inString)
 {
-  char* outString = 0;
+  PathChar* outString = nullptr;
   if ( ioHeap && inString )
   {
-    mork_size size = MORK_STRLEN(inString) + 1;
+    mork_size size = (MORK_STRLEN(inString) + 1) * sizeof(PathChar);
     ioHeap->Alloc(this->AsMdbEnv(), size, (void**) &outString);
     if ( outString )
       MORK_STRCPY(outString, inString);
   }
   else
     this->NilPointerError();
   return outString;
 }
 
 void
-morkEnv::FreeString(nsIMdbHeap* ioHeap, char* ioString)
+morkEnv::FreeString(nsIMdbHeap* ioHeap, PathChar* ioString)
 {
   if ( ioHeap )
   {
     if ( ioString )
       ioHeap->Free(this->AsMdbEnv(), ioString);
   }
   else
     this->NilPointerError();
--- a/db/mork/src/morkEnv.h
+++ b/db/mork/src/morkEnv.h
@@ -14,16 +14,17 @@
 #include "morkObject.h"
 #endif
 
 #ifndef _MORKPOOL_
 #include "morkPool.h"
 #endif
 
 // sean was here
+#include "mozilla/Path.h"
 #include "nsError.h"
 
 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
 
 #define morkDerived_kEnv     /*i*/ 0x4576 /* ascii 'Ev' */
 
 // use NS error codes to make Mork easier to use with the rest of mozilla 
 #define morkEnv_kNoError         NS_SUCCEEDED /* no error has happened */
@@ -43,16 +44,17 @@
 #define morkEnv_kNonOpenNodeError    NS_ERROR_FAILURE 
 
 
 #define morkEnv_kWeakRefCountEnvBonus 0 /* try NOT to leak all env instances */
 
 /*| morkEnv:
 |*/
 class morkEnv : public morkObject, public nsIMdbEnv {
+  using PathChar = mozilla::filesystem::Path::value_type;
   NS_DECL_ISUPPORTS_INHERITED
 
 // public: // slots inherited from morkObject (meant to inform only)
   // nsIMdbHeap*       mNode_Heap;
 
   // mork_base      mNode_Base;     // must equal morkBase_kNode
   // mork_derived   mNode_Derived;  // depends on specific node subclass
   
@@ -142,19 +144,19 @@ public: // utility env methods
   mork_u1 HexToByte(mork_ch inFirstHex, mork_ch inSecondHex);
 
   mork_size TokenAsHex(void* outBuf, mork_token inToken);
   // TokenAsHex() is the same as sprintf(outBuf, "%lX", (long) inToken);
  
   mork_size OidAsHex(void* outBuf, const mdbOid& inOid);
   // sprintf(buf, "%lX:^%lX", (long) inOid.mOid_Id, (long) inOid.mOid_Scope);
  
-  char* CopyString(nsIMdbHeap* ioHeap, const char* inString);
-  void  FreeString(nsIMdbHeap* ioHeap, char* ioString);
-  void  StringToYarn(const char* inString, mdbYarn* outYarn);
+  PathChar* CopyString(nsIMdbHeap* ioHeap, const PathChar* inString);
+  void  FreeString(nsIMdbHeap* ioHeap, PathChar* ioString);
+  void  StringToYarn(const PathChar* inString, mdbYarn* outYarn);
 
 public: // other env methods
 
   morkHandleFace*  NewHandle(mork_size inSize)
   { return mEnv_HandlePool->NewHandle(this, inSize, (morkZone*) 0); }
   
   void ZapHandle(morkHandleFace* ioHandle)
   { mEnv_HandlePool->ZapHandle(this, ioHandle); }
--- a/db/mork/src/morkFactory.cpp
+++ b/db/mork/src/morkFactory.cpp
@@ -160,17 +160,17 @@ void
 morkFactory::NonFactoryTypeError(morkEnv* ev)
 {
   ev->NewError("non morkFactory");
 }
 
 
 NS_IMETHODIMP
 morkFactory::OpenOldFile(nsIMdbEnv* mev, nsIMdbHeap* ioHeap,
-  const char* inFilePath,
+  const PathChar* inFilePath,
   mork_bool inFrozen, nsIMdbFile** acqFile)
   // Choose some subclass of nsIMdbFile to instantiate, in order to read
   // (and write if not frozen) the file known by inFilePath.  The file
   // returned should be open and ready for use, and presumably positioned
   // at the first byte position of the file.  The exact manner in which
   // files must be opened is considered a subclass specific detail, and
   // other portions or Mork source code don't want to know how it's done.
 {
@@ -190,17 +190,17 @@ morkFactory::OpenOldFile(nsIMdbEnv* mev,
   if ( acqFile )
     *acqFile = file;
     
   return outErr;
 }
 
 NS_IMETHODIMP
 morkFactory::CreateNewFile(nsIMdbEnv* mev, nsIMdbHeap* ioHeap,
-  const char* inFilePath, nsIMdbFile** acqFile)
+  const PathChar* inFilePath, nsIMdbFile** acqFile)
   // Choose some subclass of nsIMdbFile to instantiate, in order to read
   // (and write if not frozen) the file known by inFilePath.  The file
   // returned should be created and ready for use, and presumably positioned
   // at the first byte position of the file.  The exact manner in which
   // files must be opened is considered a subclass specific detail, and
   // other portions or Mork source code don't want to know how it's done.
 {
   nsresult outErr = NS_OK;
@@ -399,17 +399,17 @@ morkFactory::ThumbToOpenPort( // redeemi
 
 mork_bool
 morkFactory::CanOpenMorkTextFile(morkEnv* ev,
   // const mdbYarn* inFirst512Bytes,
   nsIMdbFile* ioFile)
 {
   MORK_USED_1(ev);
   mork_bool outBool = morkBool_kFalse;
-  mork_size headSize = MORK_STRLEN(morkWriter_kFileHeader);
+  mork_size headSize = strlen(morkWriter_kFileHeader);
   
   char localBuf[ 256 + 4 ]; // for extra for sloppy safety
   mdbYarn localYarn;
   mdbYarn* y = &localYarn;
   y->mYarn_Buf = localBuf; // space to hold content
   y->mYarn_Fill = 0;       // no logical content yet
   y->mYarn_Size = 256;     // physical capacity is 256 bytes
   y->mYarn_More = 0;
--- a/db/mork/src/morkFactory.h
+++ b/db/mork/src/morkFactory.h
@@ -27,16 +27,17 @@
 class nsIMdbFactory;
 
 #define morkDerived_kFactory  /*i*/ 0x4663 /* ascii 'Fc' */
 #define morkFactory_kWeakRefCountBonus 0 /* try NOT to leak all factories */
 
 /*| morkFactory: 
 |*/
 class morkFactory : public morkObject, public nsIMdbFactory { // nsIMdbObject
+  using PathChar = mozilla::filesystem::Path::value_type;
 
 // public: // slots inherited from morkObject (meant to inform only)
   // nsIMdbHeap*     mNode_Heap;
   // mork_able    mNode_Mutable; // can this node be modified?
   // mork_load    mNode_Load;    // is this node clean or dirty?
   // mork_base    mNode_Base;    // must equal morkBase_kNode
   // mork_derived mNode_Derived; // depends on specific node subclass
   // mork_access  mNode_Access;  // kOpen, kClosing, kShut, or kDead
@@ -57,27 +58,27 @@ public: // state is public because the e
 public: // morkFactory virtual methods
   virtual void CloseMorkNode(morkEnv* ev) override; // CloseFactory() only if open
 
 
 // { ===== begin nsIMdbFactory methods =====
 
   // { ----- begin file methods -----
   NS_IMETHOD OpenOldFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap,
-    const char* inFilePath,
+    const PathChar* inFilePath,
     mdb_bool inFrozen, nsIMdbFile** acqFile) override;
   // Choose some subclass of nsIMdbFile to instantiate, in order to read
   // (and write if not frozen) the file known by inFilePath.  The file
   // returned should be open and ready for use, and presumably positioned
   // at the first byte position of the file.  The exact manner in which
   // files must be opened is considered a subclass specific detail, and
   // other portions or Mork source code don't want to know how it's done.
 
   NS_IMETHOD CreateNewFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap,
-    const char* inFilePath,
+    const PathChar* inFilePath,
     nsIMdbFile** acqFile) override;
   // Choose some subclass of nsIMdbFile to instantiate, in order to read
   // (and write if not frozen) the file known by inFilePath.  The file
   // returned should be created and ready for use, and presumably positioned
   // at the first byte position of the file.  The exact manner in which
   // files must be opened is considered a subclass specific detail, and
   // other portions or Mork source code don't want to know how it's done.
   // } ----- end file methods -----
--- a/db/mork/src/morkFile.cpp
+++ b/db/mork/src/morkFile.cpp
@@ -24,16 +24,17 @@
 #endif
 
 #ifdef MORK_WIN
 #include "io.h"
 #include <windows.h>
 #endif
 
 #include "mozilla/Unused.h"
+#include "nsString.h"
 
 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
 
 
 // ````` ````` ````` ````` ````` 
 // { ===== begin morkNode interface =====
 
 /*public virtual*/ void
@@ -89,46 +90,46 @@ morkFile::CloseFile(morkEnv* ev) // call
     if ( this->IsNode() )
     {
       mFile_Frozen = 0;
       mFile_DoTrace = 0;
       mFile_IoOpen = 0;
       mFile_Active = 0;
       
       if ( mFile_Name )
-        this->SetFileName(ev, (const char*) 0);
+        this->SetFileName(ev, nullptr);
 
       nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mFile_SlotHeap);
       nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mFile_Thief);
 
       this->MarkShut();
     }
     else
       this->NonNodeError(ev);
 }
 
 // } ===== end morkNode methods =====
 // ````` ````` ````` ````` ````` 
 
 /*static*/ morkFile*
 morkFile::OpenOldFile(morkEnv* ev, nsIMdbHeap* ioHeap,
-  const char* inFilePath, mork_bool inFrozen)
+  const PathChar* inFilePath, mork_bool inFrozen)
   // Choose some subclass of morkFile to instantiate, in order to read
   // (and write if not frozen) the file known by inFilePath.  The file
   // returned should be open and ready for use, and presumably positioned
   // at the first byte position of the file.  The exact manner in which
   // files must be opened is considered a subclass specific detail, and
   // other portions or Mork source code don't want to know how it's done.
 {
   return morkStdioFile::OpenOldStdioFile(ev, ioHeap, inFilePath, inFrozen);
 }
 
 /*static*/ morkFile*
 morkFile::CreateNewFile(morkEnv* ev, nsIMdbHeap* ioHeap,
-  const char* inFilePath)
+  const PathChar* inFilePath)
   // Choose some subclass of morkFile to instantiate, in order to read
   // (and write if not frozen) the file known by inFilePath.  The file
   // returned should be created and ready for use, and presumably positioned
   // at the first byte position of the file.  The exact manner in which
   // files must be opened is considered a subclass specific detail, and
   // other portions or Mork source code don't want to know how it's done.
 {
   return morkStdioFile::CreateNewStdioFile(ev, ioHeap, inFilePath);
@@ -160,22 +161,22 @@ morkFile::NilFileNameError(morkEnv* ev)
 
 void
 morkFile::SetThief(morkEnv* ev, nsIMdbFile* ioThief)
 {
   nsIMdbFile_SlotStrongFile(ioThief, ev, &mFile_Thief);
 }
 
 void
-morkFile::SetFileName(morkEnv* ev, const char* inName) // inName can be nil
+morkFile::SetFileName(morkEnv* ev, const PathChar* inName) // inName can be nil
 {
   nsIMdbHeap* heap = mFile_SlotHeap;
   if ( heap )
   {
-    char* name = mFile_Name;
+    PathChar* name = mFile_Name;
     if ( name )
     {
       mFile_Name = 0;
       ev->FreeString(heap, name);
     }
     if ( ev->Good() && inName )
       mFile_Name = ev->CopyString(heap, inName);
   }
@@ -387,17 +388,17 @@ morkStdioFile::CloseStdioFile(morkEnv* e
 
 // } ===== end morkNode methods =====
 // ````` ````` ````` ````` ````` 
 
 // compatible with the morkFile::MakeFile() entry point
 
 /*static*/ morkStdioFile* 
 morkStdioFile::OpenOldStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap,
-  const char* inFilePath, mork_bool inFrozen)
+  const PathChar* inFilePath, mork_bool inFrozen)
 {
   morkStdioFile* outFile = 0;
   if ( ioHeap && inFilePath )
   {
     const char* mode = (inFrozen)? "rb" : "rb+";
     outFile = new(*ioHeap, ev)
       morkStdioFile(ev, morkUsage::kHeap, ioHeap, ioHeap, inFilePath, mode); 
       
@@ -409,17 +410,17 @@ morkStdioFile::OpenOldStdioFile(morkEnv*
   else
     ev->NilPointerError();
   
   return outFile;
 }
 
 /*static*/ morkStdioFile* 
 morkStdioFile::CreateNewStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap,
-  const char* inFilePath)
+  const PathChar* inFilePath)
 {
   morkStdioFile* outFile = 0;
   if ( ioHeap && inFilePath )
   {
     const char* mode = "wb+";
     outFile = new(*ioHeap, ev)
       morkStdioFile(ev, morkUsage::kHeap, ioHeap, ioHeap, inFilePath, mode); 
   }
@@ -466,17 +467,17 @@ morkStdioFile::AcquireBud(nsIMdbEnv * md
   if ( this->IsOpenAndActiveFile() )
   {
     FILE* file = (FILE*) mStdioFile_File;
     if ( file )
     {
 //#ifdef MORK_WIN
 //      truncate(file, /*eof*/ 0);
 //#else /*MORK_WIN*/
-      char* name = mFile_Name;
+      PathChar* name = mFile_Name;
       if ( name )
       {
         if ( MORK_FILECLOSE(file) >= 0 )
         {
           this->SetFileActive(morkBool_kFalse);
           this->SetFileIoOpen(morkBool_kFalse);
           mStdioFile_File = 0;
           
@@ -722,38 +723,38 @@ morkStdioFile::morkStdioFile(morkEnv* ev
 , mStdioFile_File( 0 )
 {
   if ( ev->Good() )
     mNode_Derived = morkDerived_kStdioFile;
 }
 
 morkStdioFile::morkStdioFile(morkEnv* ev, const morkUsage& inUsage,
   nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap,
-  const char* inName, const char* inMode)
+  const PathChar* inName, const char* inMode)
   // calls OpenStdio() after construction
 : morkFile(ev, inUsage, ioHeap, ioSlotHeap)
 , mStdioFile_File( 0 )
 {
   if ( ev->Good() )
     this->OpenStdio(ev, inName, inMode);
 }
 
 morkStdioFile::morkStdioFile(morkEnv* ev, const morkUsage& inUsage,
    nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap,
-   void* ioFile, const char* inName, mork_bool inFrozen)
+   void* ioFile, const PathChar* inName, mork_bool inFrozen)
   // calls UseStdio() after construction
 : morkFile(ev, inUsage, ioHeap, ioSlotHeap)
 , mStdioFile_File( 0 )
 {
   if ( ev->Good() )
     this->UseStdio(ev, ioFile, inName, inFrozen);
 }
 
 void
-morkStdioFile::OpenStdio(morkEnv* ev, const char* inName, const char* inMode)
+morkStdioFile::OpenStdio(morkEnv* ev, const PathChar* inName, const char* inMode)
   // Open a new FILE with name inName, using mode flags from inMode.
 {
   if ( ev->Good() )
   {
     if ( !inMode )
       inMode = "";
     
     mork_bool frozen = (*inMode == 'r'); // cursory attempt to note readonly
@@ -784,17 +785,17 @@ morkStdioFile::OpenStdio(morkEnv* ev, co
       }
       else ev->NewError("file already active");
     }
     else this->NewFileDownError(ev);
   }
 }
 
 void
-morkStdioFile::UseStdio(morkEnv* ev, void* ioFile, const char* inName,
+morkStdioFile::UseStdio(morkEnv* ev, void* ioFile, const PathChar* inName,
   mork_bool inFrozen)
   // Use an existing file, like stdin/stdout/stderr, which should not
   // have the io stream closed when the file is closed.  The ioFile
   // parameter must actually be of type FILE (but we don't want to make
   // this header file include the stdio.h header file).
 {
   if ( ev->Good() )
   {
--- a/db/mork/src/morkFile.h
+++ b/db/mork/src/morkFile.h
@@ -45,25 +45,28 @@
 #ifndef _MORKNODE_
 #include "morkNode.h"
 #endif
 
 #ifndef _MORKOBJECT_
 #include "morkObject.h"
 #endif
 
+#include "mozilla/Path.h"
+
 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
 
 /*=============================================================================
  * morkFile: abstract file interface
  */
 
 #define morkDerived_kFile     /*i*/ 0x4669 /* ascii 'Fi' */
 
 class morkFile /*d*/ : public morkObject, public nsIMdbFile { /* ````` simple file API ````` */
+  using PathChar = mozilla::filesystem::Path::value_type;
 
 // public: // slots inherited from morkNode (meant to inform only)
   // nsIMdbHeap*    mNode_Heap;
 
   // mork_base      mNode_Base;     // must equal morkBase_kNode
   // mork_derived   mNode_Derived;  // depends on specific node subclass
   
   // mork_access    mNode_Access;   // kOpen, kClosing, kShut, or kDead
@@ -84,17 +87,17 @@ protected: // protected morkFile members
   virtual ~morkFile(); // assert that CloseFile() executed earlier
 
   mork_u1     mFile_Frozen;   // 'F' => file allows only read access
   mork_u1     mFile_DoTrace;  // 'T' trace if ev->DoTrace()
   mork_u1     mFile_IoOpen;   // 'O' => io stream is open (& needs a close)
   mork_u1     mFile_Active;   // 'A' => file is active and usable
   
   nsIMdbHeap* mFile_SlotHeap; // heap for Name and other allocated slots
-  char*       mFile_Name; // can be nil if SetFileName() is never called
+  PathChar*   mFile_Name; // can be nil if SetFileName() is never called
   // mFile_Name convention: managed with morkEnv::CopyString()/FreeString()
 
   nsIMdbFile* mFile_Thief; // from a call to orkinFile::Steal()
   
 // { ===== begin morkNode interface =====
 public: // morkNode virtual methods
   NS_DECL_ISUPPORTS_INHERITED
   virtual void CloseMorkNode(morkEnv* ev) override; // CloseFile() only if open
@@ -112,26 +115,26 @@ public: // dynamic type identification
   mork_bool IsFile() const
   { return IsNode() && mNode_Derived == morkDerived_kFile; }
 // } ===== end morkNode methods =====
     
 // ````` ````` ````` `````   ````` ````` ````` `````  
 public: // public static standard file creation entry point
 
   static morkFile* OpenOldFile(morkEnv* ev, nsIMdbHeap* ioHeap,
-    const char* inFilePath, mork_bool inFrozen);
+    const PathChar* inFilePath, mork_bool inFrozen);
   // Choose some subclass of morkFile to instantiate, in order to read
   // (and write if not frozen) the file known by inFilePath.  The file
   // returned should be open and ready for use, and presumably positioned
   // at the first byte position of the file.  The exact manner in which
   // files must be opened is considered a subclass specific detail, and
   // other portions or Mork source code don't want to know how it's done.
 
   static morkFile* CreateNewFile(morkEnv* ev, nsIMdbHeap* ioHeap,
-    const char* inFilePath);
+    const PathChar* inFilePath);
   // Choose some subclass of morkFile to instantiate, in order to read
   // (and write if not frozen) the file known by inFilePath.  The file
   // returned should be created and ready for use, and presumably positioned
   // at the first byte position of the file.  The exact manner in which
   // files must be opened is considered a subclass specific detail, and
   // other portions or Mork source code don't want to know how it's done.
   
 public: // non-poly morkFile methods
@@ -154,18 +157,18 @@ public: // non-poly morkFile methods
   mork_bool IsOpenAndActiveFile() const
   { return ( this->IsOpenNode() && this->FileActive() ); }
     // call IsOpenAndActiveFile() before using a file
     
 
   nsIMdbFile* GetThief() const { return mFile_Thief; }
   void SetThief(morkEnv* ev, nsIMdbFile* ioThief); // ioThief can be nil
     
-  const char* GetFileNameString() const { return mFile_Name; }
-  void SetFileName(morkEnv* ev, const char* inName); // inName can be nil
+  const PathChar* GetFileNameString() const { return mFile_Name; }
+  void SetFileName(morkEnv* ev, const PathChar* inName); // inName can be nil
   static void NilSlotHeapError(morkEnv* ev);
   static void NilFileNameError(morkEnv* ev);
   static void NonFileTypeError(morkEnv* ev);
     
   void NewMissingIoError(morkEnv* ev) const;
     
   void NewFileDownError(morkEnv* ev) const;
     // call NewFileDownError() when either IsOpenAndActiveFile()
@@ -230,16 +233,17 @@ public:
 
 /*=============================================================================
  * morkStdioFile: concrete file using standard C file io
  */
 
 #define morkDerived_kStdioFile     /*i*/ 0x7346 /* ascii 'sF' */
 
 class morkStdioFile /*d*/ : public morkFile { /* `` copied from IronDoc `` */
+  using PathChar = mozilla::filesystem::Path::value_type;
 
 // ````` ````` ````` `````   ````` ````` ````` `````  
 protected: // protected morkStdioFile members
 
   void* mStdioFile_File;
   // actually type FILE*, but using opaque void* type
 
 // { ===== begin morkNode interface =====
@@ -263,20 +267,20 @@ public: // dynamic type identification
 
 public: // typing
   static void NonStdioFileTypeError(morkEnv* ev);
     
 // ````` ````` ````` `````   ````` ````` ````` `````  
 public: // compatible with the morkFile::OpenOldFile() entry point
 
   static morkStdioFile* OpenOldStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap,
-    const char* inFilePath, mork_bool inFrozen);
+    const PathChar* inFilePath, mork_bool inFrozen);
 
   static morkStdioFile* CreateNewStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap,
-    const char* inFilePath);
+    const PathChar* inFilePath);
 
   virtual mork_pos   Length(morkEnv* ev) const override; // eof
 
   NS_IMETHOD Tell(nsIMdbEnv* ev, mdb_pos* outPos) const override;
   NS_IMETHOD Seek(nsIMdbEnv* ev, mdb_pos inPos, mdb_pos *outPos) override;
 //  NS_IMETHOD Eof(nsIMdbEnv* ev, mdb_pos* outPos);
   // } ----- end pos methods -----
 
@@ -310,28 +314,28 @@ protected: // protected non-poly morkStd
 
   void new_stdio_file_fault(morkEnv* ev) const;
     
 // ````` ````` ````` `````   ````` ````` ````` `````  
 public: // public non-poly morkStdioFile methods
     
   morkStdioFile(morkEnv* ev, const morkUsage& inUsage, 
     nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap,
-    const char* inName, const char* inMode);
+    const PathChar* inName, const char* inMode);
     // calls OpenStdio() after construction
 
   morkStdioFile(morkEnv* ev, const morkUsage& inUsage,
     nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap,
-     void* ioFile, const char* inName, mork_bool inFrozen);
+     void* ioFile, const PathChar* inName, mork_bool inFrozen);
     // calls UseStdio() after construction
   
-  void OpenStdio(morkEnv* ev, const char* inName, const char* inMode);
+  void OpenStdio(morkEnv* ev, const PathChar* inName, const char* inMode);
     // Open a new FILE with name inName, using mode flags from inMode.
   
-  void UseStdio(morkEnv* ev, void* ioFile, const char* inName,
+  void UseStdio(morkEnv* ev, void* ioFile, const PathChar* inName,
     mork_bool inFrozen);
     // Use an existing file, like stdin/stdout/stderr, which should not
     // have the io stream closed when the file is closed.  The ioFile
     // parameter must actually be of type FILE (but we don't want to make
     // this header file include the stdio.h header file).
     
   void CloseStdio(morkEnv* ev);
     // Close the stream io if both and FileActive() and FileIoOpen(), but
--- a/db/mork/src/morkSink.cpp
+++ b/db/mork/src/morkSink.cpp
@@ -278,15 +278,15 @@ morkSpool::Write(morkEnv* ev, const void
 
 mork_bool
 morkSpool::PutString(morkEnv* ev, const char* inString)
 // call Write() with inBuf=inString and inSize=strlen(inString),
 // unless inString is null, in which case we then do nothing at all.
 {
   if ( inString )
   {
-    mork_size size = MORK_STRLEN(inString);
+    mork_size size = strlen(inString);
     this->Write(ev, inString, size);
   }
   return ev->Good();
 }
 
 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
--- a/db/mork/src/morkStore.cpp
+++ b/db/mork/src/morkStore.cpp
@@ -395,17 +395,17 @@ morkStore::StageYarnAsFarBookAtom(morkEn
 }
 
 morkFarBookAtom*
 morkStore::StageStringAsFarBookAtom(morkEnv* ev, const char* inString,
    mork_cscode inForm, morkAtomSpace* ioSpace)
 {
   if ( inString )
   {
-    mork_size length = MORK_STRLEN(inString);
+    mork_size length = strlen(inString);
     if ( length <= morkBookAtom_kMaxBodySize )
     {
       morkBuf buf(inString, length);
       mork_aid dummyAid = 1;
       //mStore_BookAtom.InitMaxBookAtom(ev, buf, inForm, ioSpace, dummyAid);
       mStore_FarBookAtom.InitFarBookAtom(ev, buf, inForm, ioSpace, dummyAid);
       return &mStore_FarBookAtom;
     }
--- a/db/mork/src/morkStream.cpp
+++ b/db/mork/src/morkStream.cpp
@@ -203,17 +203,17 @@ morkStream::PutStringThenIndent(morkEnv*
   mdb_size bytesWritten;
   nsIMdbEnv *mev = ev->AsMdbEnv();
   
   if ( inDepth > morkStream_kMaxIndentDepth )
     inDepth = morkStream_kMaxIndentDepth;
   
   if ( inString )
   {
-    mork_size length = MORK_STRLEN(inString);
+    mork_size length = strlen(inString);
     if ( length && ev->Good() ) // any bytes to write?
       this->Write(mev, inString, length, &bytesWritten);
   }
   
   if ( ev->Good() )
   {
     this->PutLineBreak(ev);
     if ( ev->Good() )
@@ -229,17 +229,17 @@ morkStream::PutStringThenIndent(morkEnv*
 mork_size
 morkStream::PutString(morkEnv* ev, const char* inString)
 {
   nsIMdbEnv *mev = ev->AsMdbEnv();
   mork_size outSize = 0;
   mdb_size bytesWritten;
   if ( inString )
   {
-    outSize = MORK_STRLEN(inString);
+    outSize = strlen(inString);
     if ( outSize && ev->Good() ) // any bytes to write?
     {
       this->Write(mev, inString, outSize, &bytesWritten);
     }
   }
   return outSize;
 }
 
@@ -247,17 +247,17 @@ mork_size
 morkStream::PutStringThenNewline(morkEnv* ev, const char* inString)
   // PutStringThenNewline() returns total number of bytes written.
 {
   nsIMdbEnv *mev = ev->AsMdbEnv();
   mork_size outSize = 0;
   mdb_size bytesWritten;
   if ( inString )
   {
-    outSize = MORK_STRLEN(inString);
+    outSize = strlen(inString);
     if ( outSize && ev->Good() ) // any bytes to write?
     {
       this->Write(mev, inString, outSize, &bytesWritten);
       if ( ev->Good() )
         outSize += this->PutLineBreak(ev);
     }
   }
   return outSize;
--- a/mailnews/addrbook/src/nsAddrDatabase.cpp
+++ b/mailnews/addrbook/src/nsAddrDatabase.cpp
@@ -466,20 +466,18 @@ NS_IMETHODIMP nsAddrDatabase::OpenMDB(ns
   nsCOMPtr<nsIMdbFactory> mdbFactory;
   GetMDBFactory(getter_AddRefs(mdbFactory));
   NS_ENSURE_TRUE(mdbFactory, NS_ERROR_FAILURE);
 
   ret = mdbFactory->MakeEnv(NULL, &m_mdbEnv);
   if (NS_SUCCEEDED(ret))
   {
     nsIMdbThumb *thumb = nullptr;
-    nsAutoCString filePath;
-
-    ret = dbName->GetNativePath(filePath);
-    NS_ENSURE_SUCCESS(ret, ret);
+
+    PathString filePath = dbName->NativePath();
 
     nsIMdbHeap* dbHeap = nullptr;
 
     if (m_mdbEnv)
       m_mdbEnv->SetAutoClear(true);
 
     bool dbNameExists = false;
     ret = dbName->Exists(&dbNameExists);
--- a/mailnews/addrbook/src/nsAddrDatabase.h
+++ b/mailnews/addrbook/src/nsAddrDatabase.h
@@ -3,32 +3,34 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _nsAddrDatabase_H_
 #define _nsAddrDatabase_H_
 
 #include "mozilla/Attributes.h"
 #include "nsIAddrDatabase.h"
+#include "nsIFile.h"
 #include "mdb.h"
 #include "nsString.h"
 #include "nsIAddrDBListener.h"
 #include "nsCOMPtr.h"
 #include "nsTObserverArray.h"
 #include "nsWeakPtr.h"
 
 typedef enum
 {
   AB_NotifyInserted,
   AB_NotifyDeleted,
   AB_NotifyPropertyChanged
 } AB_NOTIFY_CODE;
 
 class nsAddrDatabase : public nsIAddrDatabase
 {
+  using PathString = mozilla::PathString;
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIADDRDBANNOUNCER
   //////////////////////////////////////////////////////////////////////////////
   // nsIAddrDatabase methods:
 
   NS_IMETHOD GetDbPath(nsIFile * *aDbPath) override;
   NS_IMETHOD SetDbPath(nsIFile * aDbPath) override;
--- a/mailnews/base/src/nsMessenger.cpp
+++ b/mailnews/base/src/nsMessenger.cpp
@@ -6,21 +6,22 @@
 #include "prsystem.h"
 
 #include "nsMessenger.h"
 
 // xpcom
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 #include "nsIStringStream.h"
-#include "nsIFile.h"
+#include "nsLocalFile.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsQuickSort.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsIMutableArray.h"
+#include "mozilla/Path.h"
 #include "mozilla/Services.h"
 
 // necko
 #include "nsMimeTypes.h"
 #include "nsIURL.h"
 #include "nsIPrompt.h"
 #include "nsIStreamListener.h"
 #include "nsIStreamConverterService.h"
@@ -131,16 +132,17 @@ static void ConvertAndSanitizeFileName(c
 //
 class nsSaveAllAttachmentsState;
 
 class nsSaveMsgListener : public nsIUrlListener,
                           public nsIMsgCopyServiceListener,
                           public nsIStreamListener,
                           public nsICancelable
 {
+  using PathChar = mozilla::filesystem::Path::value_type;
 public:
   nsSaveMsgListener(nsIFile *file, nsMessenger *aMessenger, nsIUrlListener *aListener);
 
   NS_DECL_ISUPPORTS
 
   NS_DECL_NSIURLLISTENER
   NS_DECL_NSIMSGCOPYSERVICELISTENER
   NS_DECL_NSISTREAMLISTENER
@@ -179,29 +181,30 @@ public:
   nsresult InitializeDownload(nsIRequest * aRequest);
 
 private:
   virtual ~nsSaveMsgListener();
 };
 
 class nsSaveAllAttachmentsState
 {
+  using PathChar = mozilla::filesystem::Path::value_type;
 public:
   nsSaveAllAttachmentsState(uint32_t count,
                             const char **contentTypeArray,
                             const char **urlArray,
                             const char **displayNameArray,
                             const char **messageUriArray,
-                            const char *directoryName,
+                            const PathChar *directoryName,
                             bool detachingAttachments);
   virtual ~nsSaveAllAttachmentsState();
 
   uint32_t m_count;
   uint32_t m_curIndex;
-  char* m_directoryName;
+  PathChar* m_directoryName;
   char** m_contentTypeArray;
   char** m_urlArray;
   char** m_displayNameArray;
   char** m_messageUriArray;
   bool m_detachingAttachments;
 
   // if detaching, do without warning? Will create unique files instead of
   //  prompting if duplicate files exist.
@@ -620,19 +623,17 @@ nsMessenger::DetachAttachmentsWOPrompts(
   NS_ENSURE_ARG_POINTER(aDisplayNameArray);
   if (!aCount)
     return NS_OK;
   nsSaveAllAttachmentsState *saveState;
   nsCOMPtr<nsIFile> attachmentDestination;
   nsresult rv = aDestFolder->Clone(getter_AddRefs(attachmentDestination));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsAutoCString path;
-  rv = attachmentDestination->GetNativePath(path);
-  NS_ENSURE_SUCCESS(rv, rv);
+  PathString path = attachmentDestination->NativePath();
 
   nsAutoString unescapedFileName;
   ConvertAndSanitizeFileName(aDisplayNameArray[0], unescapedFileName);
   rv = attachmentDestination->Append(unescapedFileName);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = attachmentDestination->CreateUnique(nsIFile::NORMAL_FILE_TYPE, ATTACHMENT_PERMISSION);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -869,19 +870,17 @@ nsMessenger::SaveOneAttachment(const cha
   if (NS_FAILED(rv) || dialogResult == nsIFilePicker::returnCancel)
     return rv;
 
   rv = filePicker->GetFile(getter_AddRefs(localFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   SetLastSaveDirectory(localFile);
 
-  nsCString dirName;
-  rv = localFile->GetNativePath(dirName);
-  NS_ENSURE_SUCCESS(rv, rv);
+  PathString dirName = localFile->NativePath();
 
   nsSaveAllAttachmentsState *saveState =
     new nsSaveAllAttachmentsState(1,
                                   &aContentType,
                                   &aURL,
                                   &aDisplayName,
                                   &aMessageUri,
                                   dirName.get(),
@@ -940,20 +939,18 @@ nsMessenger::SaveAllAttachments(uint32_t
     return rv;
 
   rv = filePicker->GetFile(getter_AddRefs(localFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = SetLastSaveDirectory(localFile);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCString dirName;
   nsSaveAllAttachmentsState *saveState = nullptr;
-  rv = localFile->GetNativePath(dirName);
-  NS_ENSURE_SUCCESS(rv, rv);
+  PathString dirName = localFile->NativePath();
 
   saveState = new nsSaveAllAttachmentsState(count,
                                             contentTypeArray,
                                             urlArray,
                                             displayNameArray,
                                             messageUriArray,
                                             dirName.get(),
                                             detaching);
@@ -1880,21 +1877,22 @@ nsSaveMsgListener::OnStopRequest(nsIRequ
   if (m_saveAllAttachmentsState)
   {
     m_saveAllAttachmentsState->m_curIndex++;
     if (!mCanceled && m_saveAllAttachmentsState->m_curIndex < m_saveAllAttachmentsState->m_count)
     {
       nsSaveAllAttachmentsState *state = m_saveAllAttachmentsState;
       uint32_t i = state->m_curIndex;
       nsString unescapedName;
-      nsCOMPtr<nsIFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
-      if (NS_FAILED(rv)) goto done;
-      rv = localFile->InitWithNativePath(nsDependentCString(state->m_directoryName));
-
-      if (NS_FAILED(rv)) goto done;
+      RefPtr<nsLocalFile> localFile =
+        new nsLocalFile(nsTDependentString<PathChar>(state->m_directoryName));
+      if (localFile->NativePath().IsEmpty()) {
+        rv = NS_ERROR_FAILURE;
+        goto done;
+      }
 
       ConvertAndSanitizeFileName(state->m_displayNameArray[i], unescapedName);
       rv = localFile->Append(unescapedName);
       if (NS_FAILED(rv))
         goto done;
 
       // When we are running with no warnings (typically filters and other automatic
       //  uses), then don't prompt for duplicates, but create a unique file
@@ -2042,17 +2040,17 @@ nsMessenger::GetString(const nsString& a
   return;
 }
 
 nsSaveAllAttachmentsState::nsSaveAllAttachmentsState(uint32_t count,
                                                      const char **contentTypeArray,
                                                      const char **urlArray,
                                                      const char **nameArray,
                                                      const char **uriArray,
-                                                     const char *dirName,
+                                                     const PathChar *dirName,
                                                      bool detachingAttachments)
     : m_withoutWarning(false)
 {
     uint32_t i;
     NS_ASSERTION(count && urlArray && nameArray && uriArray && dirName,
                  "fatal - invalid parameters\n");
 
     m_count = count;
@@ -2063,17 +2061,17 @@ nsSaveAllAttachmentsState::nsSaveAllAtta
     m_messageUriArray = new char*[count];
     for (i = 0; i < count; i++)
     {
         m_contentTypeArray[i] = strdup(contentTypeArray[i]);
         m_urlArray[i] = strdup(urlArray[i]);
         m_displayNameArray[i] = strdup(nameArray[i]);
         m_messageUriArray[i] = strdup(uriArray[i]);
     }
-    m_directoryName = strdup(dirName);
+    m_directoryName = NS_strdup(dirName);
     m_detachingAttachments = detachingAttachments;
 }
 
 nsSaveAllAttachmentsState::~nsSaveAllAttachmentsState()
 {
     uint32_t i;
     for (i = 0; i < m_count; i++)
     {
--- a/mailnews/base/src/nsMessenger.h
+++ b/mailnews/base/src/nsMessenger.h
@@ -18,16 +18,17 @@
 #include "nsIFilePicker.h"
 #include "nsWeakReference.h"
 #include "mozIDOMWindow.h"
 #include "nsTArray.h"
 #include "nsIFolderListener.h"
 
 class nsMessenger : public nsIMessenger, public nsSupportsWeakReference, public nsIFolderListener
 {
+  using PathString = mozilla::PathString;
 
 public:
   nsMessenger();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMESSENGER
   NS_DECL_NSIFOLDERLISTENER
 
--- a/mailnews/base/src/nsMsgFolderCache.cpp
+++ b/mailnews/base/src/nsMsgFolderCache.cpp
@@ -121,17 +121,17 @@ nsresult nsMsgFolderCache::InitExistingD
     }
   }
   else
     err = NS_ERROR_FAILURE;
 
   return err;
 }
 
-nsresult nsMsgFolderCache::OpenMDB(const nsACString& dbName, bool exists)
+nsresult nsMsgFolderCache::OpenMDB(const PathString& dbName, bool exists)
 {
   nsresult ret=NS_OK;
   nsCOMPtr<nsIMdbFactory> mdbFactory;
   GetMDBFactory(getter_AddRefs(mdbFactory));
   if (mdbFactory)
   {
     ret = mdbFactory->MakeEnv(nullptr, &m_mdbEnv);
     if (NS_SUCCEEDED(ret))
@@ -143,17 +143,17 @@ nsresult nsMsgFolderCache::OpenMDB(const
         m_mdbEnv->SetAutoClear(true);
       if (exists)
       {
         mdbOpenPolicy inOpenPolicy;
         mdb_bool canOpen;
         mdbYarn outFormatVersion;
 
         nsIMdbFile* oldFile = nullptr;
-        ret = mdbFactory->OpenOldFile(m_mdbEnv, dbHeap, nsCString(dbName).get(),
+        ret = mdbFactory->OpenOldFile(m_mdbEnv, dbHeap, dbName.get(),
                                       mdbBool_kFalse, // not readonly, we want modifiable
                                       &oldFile);
         if ( oldFile )
         {
           if (NS_SUCCEEDED(ret))
           {
             ret = mdbFactory->CanOpenFilePort(m_mdbEnv, oldFile, // file to investigate
               &canOpen, &outFormatVersion);
@@ -197,17 +197,17 @@ nsresult nsMsgFolderCache::OpenMDB(const
         }
 #ifdef DEBUG_bienvenu1
         DumpContents();
 #endif
       }
       else // ### need error code saying why open file store failed
       {
         nsIMdbFile* newFile = 0;
-        ret = mdbFactory->CreateNewFile(m_mdbEnv, dbHeap, nsCString(dbName).get(), &newFile);
+        ret = mdbFactory->CreateNewFile(m_mdbEnv, dbHeap, dbName.get(), &newFile);
         if ( newFile )
         {
           if (NS_SUCCEEDED(ret))
           {
             mdbOpenPolicy inOpenPolicy;
 
             inOpenPolicy.mOpenPolicy_ScopePlan.mScopeStringSet_Count = 0;
             inOpenPolicy.mOpenPolicy_MinMemory = 0;
@@ -230,18 +230,17 @@ nsresult nsMsgFolderCache::OpenMDB(const
 
 NS_IMETHODIMP nsMsgFolderCache::Init(nsIFile *aFile)
 {
   NS_ENSURE_ARG_POINTER(aFile);
 
   bool exists;
   aFile->Exists(&exists);
 
-  nsAutoCString dbPath;
-  aFile->GetNativePath(dbPath);
+  PathString dbPath = aFile->NativePath();
   // ### evil cast until MDB supports file streams.
   nsresult rv = OpenMDB(dbPath, exists);
   // if this fails and panacea.dat exists, try blowing away the db and recreating it
   if (NS_FAILED(rv) && exists)
   {
     if (m_mdbStore)
       m_mdbStore->Release();
     aFile->Remove(false);
--- a/mailnews/base/src/nsMsgFolderCache.h
+++ b/mailnews/base/src/nsMsgFolderCache.h
@@ -2,23 +2,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsMsgFolderCache_H
 #define nsMsgFolderCache_H
 
 #include "nsIMsgFolderCache.h"
+#include "nsIFile.h"
 #include "nsIMsgFolderCacheElement.h"
 #include "nsInterfaceHashtable.h"
 #include "nsCOMPtr.h"
 #include "mdb.h"
 
 class nsMsgFolderCache : public nsIMsgFolderCache
 {
+  using PathString = mozilla::PathString;
 
 public:
   friend class nsMsgFolderCacheElement;
 
   nsMsgFolderCache();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMSGFOLDERCACHE
@@ -27,17 +29,17 @@ protected:
   virtual ~nsMsgFolderCache();
 
   void GetMDBFactory(nsIMdbFactory ** aMdbFactory);
   nsresult AddCacheElement(const nsACString& key, nsIMdbRow *row, nsIMsgFolderCacheElement **result);
   nsresult RowCellColumnToCharPtr(nsIMdbRow *hdrRow, mdb_token columnToken, nsACString& resultPtr);
   nsresult InitMDBInfo();
   nsresult InitNewDB();
   nsresult InitExistingDB();
-  nsresult OpenMDB(const nsACString& dbName, bool create);
+  nsresult OpenMDB(const PathString& dbName, bool create);
   nsIMdbEnv *GetEnv() {return m_mdbEnv;}
   nsIMdbStore *GetStore() {return m_mdbStore;}
   nsInterfaceHashtable<nsCStringHashKey, nsIMsgFolderCacheElement> m_cacheElements;
   // mdb stuff
   nsIMdbEnv           *m_mdbEnv; // to be used in all the db calls.
   nsIMdbStore         *m_mdbStore;
   nsIMdbTable         *m_mdbAllFoldersTable;
   mdb_token           m_folderRowScopeToken;
--- a/mailnews/compose/src/nsMsgCompUtils.cpp
+++ b/mailnews/compose/src/nsMsgCompUtils.cpp
@@ -90,51 +90,16 @@ nsMsgCreateTempFile(const char *tFileNam
 
   rv = (*tFile)->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00600);
   if (NS_FAILED(rv))
     NS_RELEASE(*tFile);
 
   return rv;
 }
 
-//
-// Create a file spec for the a unique temp file
-// on the local machine. Caller must free memory
-// returned
-//
-char *
-nsMsgCreateTempFileName(const char *tFileName)
-{
-  if ((!tFileName) || (!*tFileName))
-    tFileName = "nsmail.tmp";
-
-  nsCOMPtr<nsIFile> tmpFile;
-
-  nsresult rv = GetSpecialDirectoryWithFileName(NS_OS_TEMP_DIR,
-                                                tFileName,
-                                                getter_AddRefs(tmpFile));
-  if (NS_FAILED(rv))
-    return nullptr;
-
-  rv = tmpFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00600);
-  if (NS_FAILED(rv))
-    return nullptr;
-
-  nsCString tempString;
-  rv = tmpFile->GetNativePath(tempString);
-  if (NS_FAILED(rv))
-    return nullptr;
-
-  char *tString = ToNewCString(tempString);
-  if (!tString)
-    return PL_strdup("mozmail.tmp");  // No need to I18N
-
-  return tString;
-}
-
 // This is the value a caller will Get if they don't Set first (like MDN
 // sending a return receipt), so init to the default value of the
 // mail.strictly_mime_headers preference.
 static bool mime_headers_use_quoted_printable_p = true;
 
 bool
 nsMsgMIMEGetConformToStandard (void)
 {
--- a/mailnews/compose/src/nsMsgCompose.cpp
+++ b/mailnews/compose/src/nsMsgCompose.cpp
@@ -4328,17 +4328,16 @@ nsMsgCompose::ProcessSignature(nsIMsgIde
   // insert the correct HTML into the composer to have it work, but if we
   // are doing plain text compose, we should insert some sort of message
   // saying "Image Signature Omitted" or something (not done yet).
   //
   // If there's a sig pref, it will only be used if there is no sig file defined,
   // thus if attach_signature is checked, htmlSigText is ignored (bug 324495).
   // Plain-text signatures may or may not have a trailing line break (bug 428040).
 
-  nsAutoCString sigNativePath;
   bool          attachFile = false;
   bool          useSigFile = false;
   bool          htmlSig = false;
   bool          imageSig = false;
   nsAutoString  sigData;
   nsAutoString sigOutput;
   int32_t      reply_on_top = 0;
   bool         sig_bottom = true;
@@ -4354,18 +4353,17 @@ nsMsgCompose::ProcessSignature(nsIMsgIde
     identity->GetSigBottom(&sig_bottom);
     identity->GetSuppressSigSep(&suppressSigSep);
 
     rv = identity->GetAttachSignature(&attachFile);
     if (NS_SUCCEEDED(rv) && attachFile)
     {
       rv = identity->GetSignature(getter_AddRefs(sigFile));
       if (NS_SUCCEEDED(rv) && sigFile) {
-        rv = sigFile->GetNativePath(sigNativePath);
-        if (NS_SUCCEEDED(rv) && !sigNativePath.IsEmpty()) {
+        if (!sigFile->NativePath().IsEmpty()) {
           bool exists = false;
           sigFile->Exists(&exists);
           if (exists) {
             useSigFile = true; // ok, there's a signature file
 
             // Now, most importantly, we need to figure out what the content type is for
             // this signature...if we can't, we assume text
             nsAutoCString sigContentType;
--- a/mailnews/db/msgdb/public/nsMsgDatabase.h
+++ b/mailnews/db/msgdb/public/nsMsgDatabase.h
@@ -3,16 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _nsMsgDatabase_H_
 #define _nsMsgDatabase_H_
 
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/Path.h"
+#include "nsIFile.h"
 #include "nsIMsgDatabase.h"
 #include "nsMsgHdr.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "nsIDBChangeListener.h"
 #include "nsIDBChangeAnnouncer.h"
 #include "nsMsgMessageFlags.h"
 #include "nsIMsgFolder.h"
@@ -124,16 +126,18 @@ protected:
 namespace mozilla {
 namespace mailnews {
 class MsgDBReporter;
 }
 }
 
 class nsMsgDatabase : public nsIMsgDatabase
 {
+  using PathChar = mozilla::filesystem::Path::value_type;
+  using PathString = mozilla::PathString;
 public:
   friend class nsMsgDBService;
   friend class nsMsgPropertyEnumerator; // accesses m_mdbEnv and m_mdbStore
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDBCHANGEANNOUNCER
   NS_DECL_NSIMSGDATABASE
 
@@ -156,17 +160,17 @@ public:
   virtual nsresult Open(nsMsgDBService *aDBService, nsIFile *aFolderName,
                         bool aCreate, bool aLeaveInvalidDB);
   virtual nsresult IsHeaderRead(nsIMsgDBHdr *hdr, bool *pRead);
   virtual nsresult MarkHdrReadInDB(nsIMsgDBHdr *msgHdr, bool bRead,
                                nsIDBChangeListener *instigator);
   nsresult OpenInternal(nsMsgDBService *aDBService, nsIFile *aFolderName,
                         bool aCreate, bool aLeaveInvalidDB, bool sync);
   nsresult CheckForErrors(nsresult err, bool sync, nsMsgDBService *aDBService, nsIFile *summaryFile);
-  virtual nsresult OpenMDB(const char *dbName, bool create, bool sync);
+  virtual nsresult OpenMDB(const PathChar *dbName, bool create, bool sync);
   virtual nsresult CloseMDB(bool commit);
   virtual nsresult CreateMsgHdr(nsIMdbRow* hdrRow, nsMsgKey key, nsIMsgDBHdr **result);
   virtual nsresult GetThreadForMsgKey(nsMsgKey msgKey, nsIMsgThread **result);
   virtual nsresult EnumerateMessagesWithFlag(nsISimpleEnumerator* *result, uint32_t *pFlag);
   nsresult         GetSearchResultsTable(const char *searchFolderUri, bool createIfMissing, nsIMdbTable **table);
 
   // this might just be for debugging - we'll see.
   nsresult ListAllThreads(nsTArray<nsMsgKey> *threadIds);
@@ -310,17 +314,17 @@ protected:
 
   // Used for asynchronous db opens. If non-null, we're still opening
   // the underlying mork database. If null, the db has been completely opened.
   nsCOMPtr<nsIMdbThumb> m_thumb;
   // used to remember the args to Open for async open.
   bool m_create;
   bool m_leaveInvalidDB;
 
-  nsCString     m_dbName;
+  PathString    m_dbName;
   nsTArray<nsMsgKey> m_newSet;  // new messages since last open.
   bool          m_mdbTokensInitialized;
   nsTObserverArray<nsCOMPtr<nsIDBChangeListener> > m_ChangeListeners;
   mdb_token     m_hdrRowScopeToken;
   mdb_token     m_threadRowScopeToken;
   mdb_token     m_hdrTableKindToken;
   mdb_token     m_threadTableKindToken;
   mdb_token     m_allThreadsTableKindToken;
--- a/mailnews/db/msgdb/src/nsMsgDatabase.cpp
+++ b/mailnews/db/msgdb/src/nsMsgDatabase.cpp
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // this file implements the nsMsgDatabase interface using the MDB Interface.
 
 #include "nscore.h"
 #include "msgCore.h"
+#include "nsLocalFile.h"
 #include "nsMailDatabase.h"
 #include "nsDBFolderInfo.h"
 #include "nsMsgKeySet.h"
 #include "nsMsgThread.h"
 #include "nsIMsgSearchTerm.h"
 #include "nsMsgBaseCID.h"
 #include "nsMorkCID.h"
 #include "nsIMdbFactoryFactory.h"
@@ -541,20 +542,18 @@ NS_IMETHODIMP nsMsgDatabase::SetLastUseT
   return NS_OK;
 }
 
 NS_IMETHODIMP nsMsgDatabase::GetDatabaseSize(int64_t *_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
 
   nsresult rv;
-  nsCOMPtr<nsIFile> summaryFilePath = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = summaryFilePath->InitWithNativePath(m_dbName);
-  NS_ENSURE_SUCCESS(rv, rv);
+  RefPtr<nsLocalFile> summaryFilePath = new nsLocalFile(m_dbName);
+  NS_ENSURE_TRUE(!summaryFilePath->NativePath().IsEmpty(), NS_ERROR_FAILURE);
 
   bool exists;
   rv = summaryFilePath->Exists(&exists);
   if (NS_SUCCEEDED(rv))
   {
     if (exists)
       rv = summaryFilePath->GetFileSize(_retval);
     else
@@ -931,19 +930,17 @@ NS_IMETHODIMP nsMsgDatabase::NotifyParen
 NS_IMETHODIMP nsMsgDatabase::NotifyAnnouncerGoingAway(void)
 {
   NOTIFY_LISTENERS(OnAnnouncerGoingAway, (this));
   return NS_OK;
 }
 
 bool nsMsgDatabase::MatchDbName(nsIFile *dbName)  // returns true if they match
 {
-  nsCString dbPath;
-  dbName->GetNativePath(dbPath);
-  return dbPath.Equals(m_dbName);
+  return dbName->NativePath().Equals(m_dbName);
 }
 
 void nsMsgDBService::AddToCache(nsMsgDatabase* pMessageDB)
 {
 #ifdef DEBUG_David_Bienvenu
   NS_ASSERTION(m_dbCache.Length() < 50, "50 or more open db's");
 #endif
 #ifdef DEBUG
@@ -1074,17 +1071,16 @@ NS_IMPL_ISUPPORTS(MsgDBReporter, nsIMemo
 
 nsMsgDatabase::nsMsgDatabase()
         : m_dbFolderInfo(nullptr),
         m_nextPseudoMsgKey(kFirstPseudoKey),
         m_mdbEnv(nullptr), m_mdbStore(nullptr),
         m_mdbAllMsgHeadersTable(nullptr), m_mdbAllThreadsTable(nullptr),
         m_create(false),
         m_leaveInvalidDB(false),
-        m_dbName(""),
         m_mdbTokensInitialized(false),
         m_hdrRowScopeToken(0),
         m_hdrTableKindToken(0),
         m_threadTableKindToken(0),
         m_subjectColumnToken(0),
         m_senderColumnToken(0),
         m_messageIdColumnToken(0),
         m_referencesColumnToken(0),
@@ -1188,21 +1184,20 @@ nsresult nsMsgDatabase::Open(nsMsgDBServ
   return nsMsgDatabase::OpenInternal(aDBService, aFolderName, aCreate, aLeaveInvalidDB,
                                      true /* open synchronously */);
 }
 
 nsresult nsMsgDatabase::OpenInternal(nsMsgDBService *aDBService,
                                      nsIFile *summaryFile, bool aCreate,
                                      bool aLeaveInvalidDB, bool sync)
 {
-  nsAutoCString summaryFilePath;
-  summaryFile->GetNativePath(summaryFilePath);
+  PathString summaryFilePath = summaryFile->NativePath();
 
   MOZ_LOG(DBLog, LogLevel::Info, ("nsMsgDatabase::Open(%s, %s, %p, %s)\n",
-    (const char*)summaryFilePath.get(), aCreate ? "TRUE":"FALSE",
+    summaryFile->HumanReadablePath().get(), aCreate ? "TRUE":"FALSE",
     this, aLeaveInvalidDB ? "TRUE":"FALSE"));
 
 
   nsresult rv = OpenMDB(summaryFilePath.get(), aCreate, sync);
   if (NS_FAILED(rv))
     MOZ_LOG(DBLog, LogLevel::Info, ("error opening db %" PRIx32, static_cast<uint32_t>(rv)));
 
   if (MOZ_LOG_TEST(DBLog, LogLevel::Debug))
@@ -1309,37 +1304,35 @@ nsresult nsMsgDatabase::CheckForErrors(n
   return (summaryFileExists) ? err : NS_MSG_ERROR_FOLDER_SUMMARY_MISSING;
 }
 
 /**
  * Open the MDB database synchronously or async based on sync argument.
  * If successful, this routine will set up the m_mdbStore and m_mdbEnv of
  * the database object so other database calls can work.
  */
-nsresult nsMsgDatabase::OpenMDB(const char *dbName, bool create, bool sync)
+nsresult nsMsgDatabase::OpenMDB(const PathChar *dbName, bool create, bool sync)
 {
   nsresult ret = NS_OK;
   nsCOMPtr<nsIMdbFactory> mdbFactory;
   GetMDBFactory(getter_AddRefs(mdbFactory));
   if (mdbFactory)
   {
     ret = mdbFactory->MakeEnv(NULL, &m_mdbEnv);
     if (NS_SUCCEEDED(ret))
     {
       nsIMdbHeap* dbHeap = nullptr;
 
       if (m_mdbEnv)
         m_mdbEnv->SetAutoClear(true);
       m_dbName = dbName;
       bool exists = false;
-      nsCOMPtr<nsIFile> dbFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &ret);
-      if (NS_SUCCEEDED(ret) && dbFile) {
-        ret = dbFile->InitWithNativePath(m_dbName);
-        if (NS_SUCCEEDED(ret))
-          ret = dbFile->Exists(&exists);
+      RefPtr<nsLocalFile> dbFile = new nsLocalFile(m_dbName);
+      if (!dbFile->NativePath().IsEmpty()) {
+        ret = dbFile->Exists(&exists);
       }
       if (!exists)
       {
         ret = NS_MSG_ERROR_FOLDER_SUMMARY_MISSING;
       }
       // If m_thumb is set, we're asynchronously opening the db already.
       else if (!m_thumb)
       {
@@ -1555,17 +1548,21 @@ NS_IMETHODIMP nsMsgDatabase::Commit(nsMs
   if (NS_SUCCEEDED(rv) && accountManager)
   {
     nsCOMPtr<nsIMsgFolderCache> folderCache;
 
     rv = accountManager->GetFolderCache(getter_AddRefs(folderCache));
     if (NS_SUCCEEDED(rv) && folderCache)
     {
       nsCOMPtr <nsIMsgFolderCacheElement> cacheElement;
-      rv = folderCache->GetCacheElement(m_dbName, false, getter_AddRefs(cacheElement));
+      RefPtr<nsLocalFile> dbFile = new nsLocalFile(m_dbName);
+      nsCString persistentPath;
+      rv = dbFile->GetPersistentDescriptor(persistentPath);
+      NS_ENSURE_SUCCESS(rv, err);
+      rv = folderCache->GetCacheElement(persistentPath, false, getter_AddRefs(cacheElement));
       if (NS_SUCCEEDED(rv) && cacheElement && m_dbFolderInfo)
       {
         int32_t totalMessages, unreadMessages, pendingMessages, pendingUnreadMessages;
 
         m_dbFolderInfo->GetNumMessages(&totalMessages);
         m_dbFolderInfo->GetNumUnreadMessages(&unreadMessages);
         m_dbFolderInfo->GetImapUnreadPendingMessages(&pendingUnreadMessages);
         m_dbFolderInfo->GetImapTotalPendingMessages(&pendingMessages);
--- a/mailnews/imap/src/nsImapMailFolder.cpp
+++ b/mailnews/imap/src/nsImapMailFolder.cpp
@@ -3215,18 +3215,17 @@ NS_IMETHODIMP nsImapMailFolder::BeginCop
 {
   NS_ENSURE_TRUE(m_copyState, NS_ERROR_NULL_POINTER);
   nsresult rv;
   if (m_copyState->m_tmpFile) // leftover file spec nuke it
   {
     rv = m_copyState->m_tmpFile->Remove(false);
     if (NS_FAILED(rv))
     {
-      nsCString nativePath;
-      m_copyState->m_tmpFile->GetNativePath(nativePath);
+      nsCString nativePath = m_copyState->m_tmpFile->HumanReadablePath();
       MOZ_LOG(IMAP, mozilla::LogLevel::Info, ("couldn't remove prev temp file %s: %" PRIx32 "\n", nativePath.get(), static_cast<uint32_t>(rv)));
     }
     m_copyState->m_tmpFile = nullptr;
   }
   if (message)
     m_copyState->m_message = do_QueryInterface(message, &rv);
 
   rv = GetSpecialDirectoryWithFileName(NS_OS_TEMP_DIR,
@@ -8876,19 +8875,16 @@ NS_IMETHODIMP nsImapMailFolder::RenameSu
     rv = GetFilePath(getter_AddRefs(newParentPathFile));
     if (NS_FAILED(rv)) return rv;
 
     rv = AddDirectorySeparator(newParentPathFile);
     nsAutoCString oldLeafName;
     oldPathFile->GetNativeLeafName(oldLeafName);
     newParentPathFile->AppendNative(oldLeafName);
 
-    nsCString newPathStr;
-    newParentPathFile->GetNativePath(newPathStr);
-
     nsCOMPtr<nsIFile> newPathFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     newPathFile->InitWithFile(newParentPathFile);
 
     nsCOMPtr<nsIFile> dbFilePath = newPathFile;
 
     nsCOMPtr<nsIMsgFolder> child;
 
--- a/mailnews/import/outlook/src/MapiApi.cpp
+++ b/mailnews/import/outlook/src/MapiApi.cpp
@@ -198,17 +198,17 @@ HRESULT CMapiApi::MAPILogonEx(ULONG ulUI
 {
   return (m_hMapi32 && gpMapiLogonEx) ?
     (*gpMapiLogonEx)(ulUIParam, lpszProfileName, lpszPassword, flFlags, lppSession) :
      MAPI_E_NOT_INITIALIZED;
 }
 
 HRESULT CMapiApi::OpenStreamOnFile(LPALLOCATEBUFFER lpAllocateBuffer,
                                    LPFREEBUFFER lpFreeBuffer, ULONG ulFlags,
-                                   LPTSTR lpszFileName, LPTSTR lpszPrefix,
+                                   LPCTSTR lpszFileName, LPTSTR lpszPrefix,
                                    LPSTREAM FAR * lppStream)
 {
   return (m_hMapi32 && gpMapiOpenStreamOnFile) ?
     (*gpMapiOpenStreamOnFile)(lpAllocateBuffer, lpFreeBuffer, ulFlags,
                               lpszFileName, lpszPrefix, lppStream) :
     MAPI_E_NOT_INITIALIZED;
 }
 
--- a/mailnews/import/outlook/src/MapiApi.h
+++ b/mailnews/import/outlook/src/MapiApi.h
@@ -72,17 +72,17 @@ public:
 
   static HINSTANCE  m_hMapi32;
 
   static void    MAPIUninitialize(void);
   static HRESULT  MAPIInitialize(LPVOID lpInit);
   static SCODE  MAPIAllocateBuffer(ULONG cbSize, LPVOID FAR * lppBuffer);
   static ULONG  MAPIFreeBuffer(LPVOID lpBuff);
   static HRESULT  MAPILogonEx(ULONG ulUIParam, LPTSTR lpszProfileName, LPTSTR lpszPassword, FLAGS flFlags, LPMAPISESSION FAR * lppSession);
-  static HRESULT  OpenStreamOnFile(LPALLOCATEBUFFER lpAllocateBuffer, LPFREEBUFFER lpFreeBuffer, ULONG ulFlags, LPTSTR lpszFileName, LPTSTR lpszPrefix, LPSTREAM FAR * lppStream);
+  static HRESULT  OpenStreamOnFile(LPALLOCATEBUFFER lpAllocateBuffer, LPFREEBUFFER lpFreeBuffer, ULONG ulFlags, LPCTSTR lpszFileName, LPTSTR lpszPrefix, LPSTREAM FAR * lppStream);
   static void    FreeProws(LPSRowSet prows);
 
 
   BOOL  Initialize(void);
   BOOL  LogOn(void);
 
   void  AddMessageStore(CMsgStore *pStore);
   void  SetCurrentMsgStore(LPMDB lpMdb) { m_lpMdb = lpMdb;}
--- a/mailnews/import/outlook/src/MapiMessage.cpp
+++ b/mailnews/import/outlook/src/MapiMessage.cpp
@@ -12,16 +12,17 @@
 #endif
 
 #include "nscore.h"
 #include <time.h>
 #include "nsString.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsMsgUtils.h"
 #include "nsMimeTypes.h"
+#include "nsNativeCharsetUtils.h"
 #include "nsIOutputStream.h"
 
 #include "nsMsgCompCID.h"
 #include "nsIMutableArray.h"
 #include "MapiDbgLog.h"
 #include "MapiApi.h"
 
 #include "MapiMimeTypes.h"
@@ -867,24 +868,27 @@ bool CMapiMessage::CopyBinAttachToFile(L
   nsresult rv = GetSpecialDirectoryWithFileName(NS_OS_TEMP_DIR,
     "mapiattach.tmp",
     getter_AddRefs(_tmp_file));
   NS_ENSURE_SUCCESS(rv, false);
 
   rv = _tmp_file->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00600);
   NS_ENSURE_SUCCESS(rv, false);
 
-  nsCString tmpPath;
-  _tmp_file->GetNativePath(tmpPath);
+  nsString tmpPath = _tmp_file->NativePath();
+  // We have to use native charset unless we migrate to Outlook 2013 "W" API.
+  nsCString tmpNativePath;
+  rv = NS_CopyUnicodeToNative(tmpPath, tmpNativePath);
+  NS_ENSURE_SUCCESS(rv, false);
   LPSTREAM lpStreamFile;
   HRESULT hr = CMapiApi::OpenStreamOnFile(gpMapiAllocateBuffer, gpMapiFreeBuffer, STGM_READWRITE | STGM_CREATE,
-    const_cast<char*>(tmpPath.get()), NULL, &lpStreamFile);
+    tmpNativePath.get(), NULL, &lpStreamFile);
   if (HR_FAILED(hr)) {
     MAPI_TRACE1("~~ERROR~~ OpenStreamOnFile failed - temp path: %s\r\n",
-                tmpPath.get());
+                tmpNativePath.get());
     return false;
   }
 
   bool bResult = true;
   LPSTREAM lpAttachStream;
   hr = lpAttach->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, 0, 0, (LPUNKNOWN *)&lpAttachStream);
 
   if (HR_FAILED(hr)) {
--- a/mailnews/local/src/nsLocalUtils.cpp
+++ b/mailnews/local/src/nsLocalUtils.cpp
@@ -139,19 +139,22 @@ nsLocalURI2Path(const char* rootURI, con
     return rv;
 
   // now ask the server what it's root is
   // and begin pathResult with the mailbox root
   nsCOMPtr<nsIFile> localPath;
   rv = server->GetLocalPath(getter_AddRefs(localPath));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCString localNativePath;
-
-  localPath->GetNativePath(localNativePath);
+#ifdef XP_WIN
+  // The protocol handler can handle UTF-8 paths even on Windows.
+  nsCString localNativePath = NS_ConvertUTF16toUTF8(localPath->NativePath());
+#else
+  nsCString localNativePath = localPath->NativePath();
+#endif
   nsEscapeNativePath(localNativePath);
   pathResult = localNativePath.get();
   const char *curPos = uriStr + PL_strlen(rootURI);
   if (curPos) {
     // advance past hostname
     while ((*curPos)=='/') curPos++;
     while (*curPos && (*curPos)!='/') curPos++;
 
--- a/mailnews/local/src/nsMailboxService.cpp
+++ b/mailnews/local/src/nsMailboxService.cpp
@@ -45,19 +45,22 @@ nsresult nsMailboxService::ParseMailbox(
 
   nsresult rv;
   nsCOMPtr<nsIMailboxUrl> mailboxurl =
     do_CreateInstance(NS_MAILBOXURL_CONTRACTID, &rv);
   if (NS_SUCCEEDED(rv) && mailboxurl)
   {
     nsCOMPtr<nsIMsgMailNewsUrl> url = do_QueryInterface(mailboxurl);
     // okay now generate the url string
-    nsCString mailboxPath;
-
-    aMailboxPath->GetNativePath(mailboxPath);
+#ifdef XP_WIN
+    // The protocol handler can handle UTF-8 paths even on Windows.
+    nsCString mailboxPath = NS_ConvertUTF16toUTF8(aMailboxPath->NativePath());
+#else
+    nsCString mailboxPath = aMailboxPath->NativePath();
+#endif
     nsAutoCString buf;
     MsgEscapeURL(mailboxPath,
                  nsINetUtil::ESCAPE_URL_MINIMAL | nsINetUtil::ESCAPE_URL_FORCED, buf);
     nsEscapeNativePath(buf);
     url->SetUpdatingFolder(true);
     url->SetMsgWindow(aMsgWindow);
     nsAutoCString uriSpec("mailbox://");
     uriSpec.Append(buf);