Browse Source

wip: support windows unicode filenames in plugin

David Rose 14 years ago
parent
commit
9150bd2f6c

+ 9 - 1
direct/src/plugin/Sources.pp

@@ -34,6 +34,7 @@
     handleStreamBuf.cxx handleStreamBuf.h handleStreamBuf.I \
     mkdir_complete.cxx mkdir_complete.h \
     parse_color.cxx parse_color.h \
+    wstring_encode.cxx wstring_encode.h \
     p3d_lock.h p3d_plugin.h \
     p3d_plugin_config.h \
     p3d_plugin_common.h \
@@ -172,6 +173,11 @@
 #endif
   #define TARGET p3dcert
 
+  #define SOURCES $[SOURCES] \
+    is_pathsep.h is_pathsep.I \
+    wstring_encode.cxx wstring_encode.h \
+    mkdir_complete.cxx mkdir_complete.h
+
   #define OSX_SYS_FRAMEWORKS Carbon
 
 #end bin_target
@@ -185,7 +191,9 @@
     is_pathsep.h is_pathsep.I \
     mkdir_complete.cxx mkdir_complete.h \
     get_twirl_data.cxx get_twirl_data.h \
-    parse_color.cxx parse_color.h
+    parse_color.cxx parse_color.h \
+    wstring_encode.cxx wstring_encode.h
+
 
 #begin static_lib_target
 //

+ 45 - 6
direct/src/plugin/fileSpec.cxx

@@ -13,6 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "fileSpec.h"
+#include "wstring_encode.h"
 #include "openssl/md5.h"
 
 #include <fstream>
@@ -26,8 +27,6 @@
 #ifdef _WIN32
 #include <sys/utime.h>
 #include <direct.h>
-#define stat _stat
-#define utime _utime
 #define utimbuf _utimbuf
 
 #else
@@ -137,7 +136,7 @@ store_xml(TiXmlElement *xelement) {
     xelement->SetAttribute("size", _size);
   }
   if (_timestamp != 0) {
-    xelement->SetAttribute("timestamp", _timestamp);
+    xelement->SetAttribute("timestamp", (int)_timestamp);
   }
   if (_got_hash) {
     char hash[hash_size * 2 + 1];
@@ -177,8 +176,19 @@ quick_verify_pathname(const string &pathname) {
     _actual_file = NULL;
   }
 
+  int result = 1;
+#ifdef _WIN32
+  struct _stat st;
+  wstring pathname_w;
+  if (string_to_wstring(pathname_w, pathname)) {
+    result = _wstat(pathname_w.c_str(), &st);
+  }
+#else // _WIN32
   struct stat st;
-  if (stat(pathname.c_str(), &st) != 0) {
+  result = stat(pathname.c_str(), &st);
+#endif  // _WIN32
+
+  if (result != 0) {
     //cerr << "file not found: " << _filename << "\n";
     return false;
   }
@@ -213,7 +223,12 @@ quick_verify_pathname(const string &pathname) {
   utimbuf utb;
   utb.actime = st.st_atime;
   utb.modtime = _timestamp;
+
+#ifdef _WIN32
+  _wutime(pathname_w.c_str(), &utb);
+#else // _WIN32
   utime(pathname.c_str(), &utb);
+#endif  // _WIN32
 
   return true;
 }
@@ -237,8 +252,19 @@ full_verify(const string &package_dir) {
   }
 
   string pathname = get_pathname(package_dir);
+  int result = 1;
+#ifdef _WIN32
+  struct _stat st;
+  wstring pathname_w;
+  if (string_to_wstring(pathname_w, pathname)) {
+    result = _wstat(pathname_w.c_str(), &st);
+  }
+#else // _WIN32
   struct stat st;
-  if (stat(pathname.c_str(), &st) != 0) {
+  result = stat(pathname.c_str(), &st);
+#endif  // _WIN32
+
+  if (result != 0) {
     //cerr << "file not found: " << _filename << "\n";
     return false;
   }
@@ -265,7 +291,11 @@ full_verify(const string &package_dir) {
     utimbuf utb;
     utb.actime = st.st_atime;
     utb.modtime = _timestamp;
+#ifdef _WIN32
+    _wutime(pathname_w.c_str(), &utb);
+#else // _WIN32
     utime(pathname.c_str(), &utb);
+#endif  // _WIN32
   }
     
   return true;
@@ -298,7 +328,16 @@ read_hash(const string &pathname) {
   memset(_hash, 0, hash_size);
   _got_hash = false;
 
-  ifstream stream(pathname.c_str(), ios::in | ios::binary);
+  ifstream stream;
+#ifdef _WIN32
+  wstring pathname_w;
+  if (string_to_wstring(pathname_w, pathname)) {
+    stream.open(pathname_w.c_str(), ios::in | ios::binary);
+  }
+#else // _WIN32
+  stream.open(pathname.c_str(), ios::in | ios::binary);
+#endif  // _WIN32
+  
   if (!stream) {
     //cerr << "unable to read " << pathname << "\n";
     return false;

+ 56 - 69
direct/src/plugin/find_root_dir.cxx

@@ -15,6 +15,7 @@
 #include "find_root_dir.h"
 #include "mkdir_complete.h"
 #include "get_tinyxml.h"
+#include "wstring_encode.h"
 
 #ifdef _WIN32
 #include <windows.h>
@@ -39,68 +40,41 @@ DEFINE_KNOWN_FOLDER(FOLDERID_InternetCache, 0x352481E8, 0x33BE, 0x4251, 0xBA, 0x
 
 #ifdef _WIN32
 ////////////////////////////////////////////////////////////////////
-//     Function: get_csidl_dir
+//     Function: get_csidl_dir_w
 //  Description: A wrapper around SHGetSpecialFolderPath(), to return
 //               the Panda3D directory under the indicated CSIDL
 //               folder.
 ////////////////////////////////////////////////////////////////////
-static string
-get_csidl_dir(int csidl) {
+static wstring
+get_csidl_dir_w(int csidl) {
   static const int buffer_size = MAX_PATH;
-  char buffer[buffer_size];
-  if (SHGetSpecialFolderPath(NULL, buffer, csidl, true)) {
-    string root = buffer;
-    root += string("/Panda3D");
+  wchar_t buffer[buffer_size];
+  if (SHGetSpecialFolderPathW(NULL, buffer, csidl, true)) {
+    wstring root = buffer;
+    root += wstring(L"/Panda3D");
     
-    if (mkdir_complete(root, cerr)) {
+    if (mkdir_complete_w(root, cerr)) {
       return root;
     }
   }
 
   // Something went wrong.
-  return string();
+  return wstring();
 }
 #endif  // _WIN32
 
 #ifdef _WIN32
 ////////////////////////////////////////////////////////////////////
-//     Function: wstr_to_string
-//  Description: Converts Windows' LPWSTR to a std::string.
+//     Function: find_root_dir_default_w
+//  Description: Wide-character implementation of
+//               find_root_dir_default(), only needed for Windows.
 ////////////////////////////////////////////////////////////////////
-static bool
-wstr_to_string(string &result, const LPWSTR wstr) {
-  bool success = false;
-  int size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1,
-                                 NULL, 0, NULL, NULL);
-  if (size > 0) {
-    char *buffer = new char[size];
-    int rc = WideCharToMultiByte(CP_UTF8, 0, wstr, -1,
-                                 buffer, size, NULL, NULL);
-    if (rc != 0) {
-      buffer[size - 1] = 0;
-      result = buffer;
-      success = true;
-    }
-    delete[] buffer;
-  }
-
-  return success;
-}
-#endif  // _WIN32
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: find_root_dir_default
-//  Description: Returns the path to the system-default for the root
-//               directory.  This is where we look first.
-////////////////////////////////////////////////////////////////////
-static string
-find_root_dir_default() {
-#ifdef _WIN32
+static wstring
+find_root_dir_default_w() {
   // First, use IEIsProtectedModeProcess() to determine if we are
   // running in IE's "protected mode" under Vista.
 
-  string root;
+  wstring root;
   bool is_protected = false;
   HMODULE ieframe = LoadLibrary("ieframe.dll");
   if (ieframe != NULL) {
@@ -139,18 +113,14 @@ find_root_dir_default() {
           HRESULT hr = (*func)(FOLDERID_LocalAppDataLow, 0, NULL, &cache_path);
           
           if (SUCCEEDED(hr)) {
-            if (!wstr_to_string(root, cache_path)) {
-              // Couldn't decode the LPWSTR.
-              CoTaskMemFree(cache_path);
-            } else {
-              CoTaskMemFree(cache_path);
+            root = cache_path;
+            CoTaskMemFree(cache_path);
               
-              root += string("/Panda3D");
-              if (mkdir_complete(root, cerr)) {
-                FreeLibrary(shell32);
-                FreeLibrary(ieframe);
-                return root;
-              }
+            root += wstring(L"/Panda3D");
+            if (mkdir_complete_w(root, cerr)) {
+              FreeLibrary(shell32);
+              FreeLibrary(ieframe);
+              return root;
             }
           }
         }
@@ -174,16 +144,12 @@ find_root_dir_default() {
         }
 
         if (SUCCEEDED(hr)) {
-          if (!wstr_to_string(root, cache_path)) {
-            // Couldn't decode the LPWSTR.
-            CoTaskMemFree(cache_path);
-          } else {
-            CoTaskMemFree(cache_path);
-            root += string("/Panda3D");
-            if (mkdir_complete(root, cerr)) {
-              FreeLibrary(ieframe);
-              return root;
-            }
+          root = cache_path;
+          CoTaskMemFree(cache_path);
+          root += wstring(L"/Panda3D");
+          if (mkdir_complete_w(root, cerr)) {
+            FreeLibrary(ieframe);
+            return root;
           }            
         }
       }
@@ -196,7 +162,7 @@ find_root_dir_default() {
   // also the normal XP codepath.
 
   // e.g., c:/Documents and Settings/<username>/Local Settings/Application Data/Panda3D
-  root = get_csidl_dir(CSIDL_LOCAL_APPDATA);
+  root = get_csidl_dir_w(CSIDL_LOCAL_APPDATA);
   if (!root.empty()) {
     return root;
   }
@@ -205,7 +171,7 @@ find_root_dir_default() {
   // back to the cache folder.
 
   // e.g. c:/Documents and Settings/<username>/Local Settings/Temporary Internet Files/Panda3D
-  root = get_csidl_dir(CSIDL_INTERNET_CACHE);
+  root = get_csidl_dir_w(CSIDL_INTERNET_CACHE);
   if (!root.empty()) {
     return root;
   }
@@ -213,11 +179,32 @@ find_root_dir_default() {
   // If we couldn't get any of those folders, huh.  Punt and try for
   // the old standby GetTempPath, for lack of anything better.
   static const int buffer_size = MAX_PATH;
-  char buffer[buffer_size];
-  if (GetTempPath(buffer_size, buffer) != 0) {
+  wchar_t buffer[buffer_size];
+  if (GetTempPathW(buffer_size, buffer) != 0) {
     root = buffer;
-    root += string("Panda3D");
-    if (mkdir_complete(root, cerr)) {
+    root += wstring(L"Panda3D");
+    if (mkdir_complete_w(root, cerr)) {
+      return root;
+    }
+  }
+
+  return wstring();
+}
+#endif  // _WIN32
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: find_root_dir_default
+//  Description: Returns the path to the system-default for the root
+//               directory.  This is where we look first.
+////////////////////////////////////////////////////////////////////
+static string
+find_root_dir_default() {
+#ifdef _WIN32
+  wstring root_w = find_root_dir_default_w();
+  if (!root_w.empty()) {
+    string root;
+    if (wstring_to_string(root, root_w)) {
       return root;
     }
   }

+ 1 - 1
direct/src/plugin/is_pathsep.I

@@ -20,7 +20,7 @@
 //               otherwise.
 ////////////////////////////////////////////////////////////////////
 inline bool
-is_pathsep(char ch) {
+is_pathsep(int ch) {
   if (ch == '/') {
     return true;
   }

+ 1 - 1
direct/src/plugin/is_pathsep.h

@@ -16,7 +16,7 @@
 #define IS_PATHSEP_H
 
 inline bool
-is_pathsep(char ch);
+is_pathsep(int ch);
 
 #include "is_pathsep.I"
 

+ 5 - 1
direct/src/plugin/load_plugin.cxx

@@ -15,6 +15,7 @@
 #include "load_plugin.h"
 #include "p3d_plugin_config.h"
 #include "is_pathsep.h"
+#include "wstring_encode.h"
 
 #include "assert.h"
 
@@ -168,7 +169,10 @@ load_plugin(const string &p3d_plugin_filename,
     }
     
     SetErrorMode(0);
-    module = LoadLibrary(filename.c_str());
+    wstring filename_w;
+    if (string_to_wstring(filename_w, filename)) {
+      module = LoadLibraryW(filename_w.c_str());
+    }
     dso_needs_unload = true;
   }
 

+ 108 - 51
direct/src/plugin/mkdir_complete.cxx

@@ -14,6 +14,7 @@
 
 #include "mkdir_complete.h"
 #include "is_pathsep.h"
+#include "wstring_encode.h"
 
 #ifdef _WIN32
 #include <windows.h>
@@ -46,6 +47,26 @@ get_dirname(const string &filename) {
   return string();
 }
 
+#ifdef _WIN32
+////////////////////////////////////////////////////////////////////
+//     Function: get_dirname_w
+//  Description: The wide-character implementation of get_dirname().
+//               Only implemented (and needed) on Windows.
+////////////////////////////////////////////////////////////////////
+static wstring
+get_dirname_w(const wstring &filename) {
+  size_t p = filename.length();
+  while (p > 0) {
+    --p;
+    if (is_pathsep(filename[p])) {
+      return filename.substr(0, p);
+    }
+  }
+
+  return wstring();
+}
+#endif  // _WIN32
+
 
 
 ////////////////////////////////////////////////////////////////////
@@ -58,32 +79,11 @@ get_dirname(const string &filename) {
 bool
 mkdir_complete(const string &dirname, ostream &logfile) {
 #ifdef _WIN32
-  if (CreateDirectory(dirname.c_str(), NULL) != 0) {
-    // Success!
-    return true;
-  }
-
-  // Failed.
-  DWORD last_error = GetLastError();
-  if (last_error == ERROR_ALREADY_EXISTS) {
-    // Not really an error: the directory is already there.
-    return true;
-  }
-
-  if (last_error == ERROR_PATH_NOT_FOUND) {
-    // We need to make the parent directory first.
-    string parent = get_dirname(dirname);
-    if (!parent.empty() && mkdir_complete(parent, logfile)) {
-      // Parent successfully created.  Try again to make the child.
-      if (CreateDirectory(dirname.c_str(), NULL) != 0) {
-        // Got it!
-        return true;
-      }
-      logfile 
-        << "Couldn't create " << dirname << "\n";
-    }
+  wstring dirname_w;
+  if (!string_to_wstring(dirname_w, dirname)) {
+    return false;
   }
-  return false;
+  return mkdir_complete_w(dirname_w, logfile);
 
 #else  //_WIN32
   if (mkdir(dirname.c_str(), 0755) == 0) {
@@ -125,52 +125,109 @@ mkdir_complete(const string &dirname, ostream &logfile) {
 ////////////////////////////////////////////////////////////////////
 bool
 mkfile_complete(const string &filename, ostream &logfile) {
-  // Make sure we delete any previously-existing file first.
 #ifdef _WIN32
-  // Windows can't delete a file if it's read-only.  Weird.
-  chmod(filename.c_str(), 0644);
-#endif
+  wstring filename_w;
+  if (!string_to_wstring(filename_w, filename)) {
+    return false;
+  }
+  return mkfile_complete_w(filename_w, logfile);
+#else  // _WIN32
+  // Make sure we delete any previously-existing file first.
   unlink(filename.c_str());
 
-#ifdef _WIN32
-  HANDLE file = CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE,
-                           FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
-                           NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-  if (file == INVALID_HANDLE_VALUE) {
+  int fd = creat(filename.c_str(), 0755);
+  if (fd == -1) {
     // Try to make the parent directory first.
     string parent = get_dirname(filename);
     if (!parent.empty() && mkdir_complete(parent, logfile)) {
       // Parent successfully created.  Try again to make the file.
-      file = CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE,
-                        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
-                        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+      fd = creat(filename.c_str(), 0755);
     }
-    if (file == INVALID_HANDLE_VALUE) {
+    if (fd == -1) {
       logfile
-        << "Couldn't create " << filename << "\n";
+        << "Couldn't create " << filename << ": " << strerror(errno) << "\n";
       return false;
     }
   }
-  CloseHandle(file);
+  close(fd);
   return true;
 
-#else  // _WIN32
-  int fd = creat(filename.c_str(), 0755);
-  if (fd == -1) {
+#endif  // _WIN32
+}
+
+
+#ifdef _WIN32
+////////////////////////////////////////////////////////////////////
+//     Function: mkdir_complete_w
+//  Description: The wide-character implementation of
+//               mkdir_complete().  Only implemented (and needed) on
+//               Windows.
+////////////////////////////////////////////////////////////////////
+bool
+mkdir_complete_w(const wstring &dirname, ostream &logfile) {
+  if (CreateDirectoryW(dirname.c_str(), NULL) != 0) {
+    // Success!
+    return true;
+  }
+
+  // Failed.
+  DWORD last_error = GetLastError();
+  if (last_error == ERROR_ALREADY_EXISTS) {
+    // Not really an error: the directory is already there.
+    return true;
+  }
+
+  if (last_error == ERROR_PATH_NOT_FOUND) {
+    // We need to make the parent directory first.
+    wstring parent = get_dirname_w(dirname);
+    if (!parent.empty() && mkdir_complete_w(parent, logfile)) {
+      // Parent successfully created.  Try again to make the child.
+      if (CreateDirectoryW(dirname.c_str(), NULL) != 0) {
+        // Got it!
+        return true;
+      }
+      logfile 
+        << "Couldn't create " << dirname << "\n";
+    }
+  }
+  return false;
+}
+#endif  // _WIN32
+
+#ifdef _WIN32
+////////////////////////////////////////////////////////////////////
+//     Function: mkfile_complete_w
+//  Description: The wide-character implementation of
+//               mkfile_complete().  Only implemented (and needed) on
+//               Windows.
+////////////////////////////////////////////////////////////////////
+bool
+mkfile_complete_w(const wstring &filename, ostream &logfile) {
+  // Make sure we delete any previously-existing file first.
+
+  // Windows can't delete a file if it's read-only.  Weird.
+  _wchmod(filename.c_str(), 0644);
+  _wunlink(filename.c_str());
+
+  HANDLE file = CreateFileW(filename.c_str(), GENERIC_READ | GENERIC_WRITE,
+                            FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+                            NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+  if (file == INVALID_HANDLE_VALUE) {
     // Try to make the parent directory first.
-    string parent = get_dirname(filename);
-    if (!parent.empty() && mkdir_complete(parent, logfile)) {
+    wstring parent = get_dirname_w(filename);
+    if (!parent.empty() && mkdir_complete_w(parent, logfile)) {
       // Parent successfully created.  Try again to make the file.
-      fd = creat(filename.c_str(), 0755);
+      file = CreateFileW(filename.c_str(), GENERIC_READ | GENERIC_WRITE,
+                         FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+                         NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
     }
-    if (fd == -1) {
+    if (file == INVALID_HANDLE_VALUE) {
       logfile
-        << "Couldn't create " << filename << ": " << strerror(errno) << "\n";
+        << "Couldn't create " << filename << "\n";
       return false;
     }
   }
-  close(fd);
+  CloseHandle(file);
   return true;
-
-#endif  // _WIN32
 }
+#endif  // _WIN32

+ 5 - 0
direct/src/plugin/mkdir_complete.h

@@ -22,6 +22,11 @@ using namespace std;
 bool mkdir_complete(const string &dirname, ostream &logfile);
 bool mkfile_complete(const string &dirname, ostream &logfile);
 
+#ifdef _WIN32
+bool mkdir_complete_w(const wstring &dirname, ostream &logfile);
+bool mkfile_complete_w(const wstring &dirname, ostream &logfile);
+#endif  // _WIN32
+
 #endif
 
 

+ 16 - 9
direct/src/plugin/p3dAuthSession.cxx

@@ -18,6 +18,7 @@
 #include "p3dMultifileReader.h"
 #include "p3d_plugin_config.h"
 #include "mkdir_complete.h"
+#include "wstring_encode.h"
 
 #include <ctype.h>
 
@@ -331,15 +332,18 @@ win_create_process() {
   // Make sure we see an error dialog if there is a missing DLL.
   SetErrorMode(0);
 
-  STARTUPINFO startup_info;
-  ZeroMemory(&startup_info, sizeof(STARTUPINFO));
+  STARTUPINFOW startup_info;
+  ZeroMemory(&startup_info, sizeof(startup_info));
   startup_info.cb = sizeof(startup_info); 
 
   // Make sure the initial window is *shown* for this graphical app.
   startup_info.wShowWindow = SW_SHOW;
   startup_info.dwFlags |= STARTF_USESHOWWINDOW;
 
-  const char *start_dir_cstr = _start_dir.c_str();
+  const wchar_t *start_dir_cstr;
+  wstring start_dir_w;
+  string_to_wstring(start_dir_w, _start_dir);
+  start_dir_cstr = start_dir_w.c_str();
 
   // Construct the command-line string, containing the quoted
   // command-line arguments.
@@ -351,14 +355,17 @@ win_create_process() {
   // I'm not sure why CreateProcess wants a non-const char pointer for
   // its command-line string, but I'm not taking chances.  It gets a
   // non-const char array that it can modify.
-  string command_line_str = stream.str();
-  nout << "command is: " << command_line_str << "\n";
-  char *command_line = new char[command_line_str.size() + 1];
-  strcpy(command_line, command_line_str.c_str());
+  wstring command_line_str;
+  string_to_wstring(command_line_str, stream.str());
+  wchar_t *command_line = new wchar_t[command_line_str.size() + 1];
+  memcpy(command_line, command_line_str.c_str(), sizeof(wchar_t) * command_line_str.size() + 1);
+
+  wstring p3dcert_exe_w;
+  string_to_wstring(p3dcert_exe_w, _p3dcert_exe);
 
   PROCESS_INFORMATION process_info; 
-  BOOL result = CreateProcess
-    (_p3dcert_exe.c_str(), command_line, NULL, NULL, TRUE, 0,
+  BOOL result = CreateProcessW
+    (p3dcert_exe_w.c_str(), command_line, NULL, NULL, TRUE, 0,
      (void *)_env.c_str(), start_dir_cstr,
      &startup_info, &process_info);
   bool started_program = (result != 0);

+ 31 - 9
direct/src/plugin/p3dCert.cxx

@@ -13,6 +13,8 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "p3dCert.h"
+#include "wstring_encode.h"
+#include "mkdir_complete.h"
 
 #include <Fl/Fl_Box.H>
 #include <Fl/Fl_Button.H>
@@ -198,21 +200,26 @@ approve_cert() {
   assert(_cert != NULL);
 
   // Make sure the directory exists.
-#ifdef _WIN32
-  mkdir(_cert_dir.c_str());
-#else
-  mkdir(_cert_dir.c_str(), 0755);
-#endif
+  mkdir_complete(_cert_dir, cerr);
 
   // Look for an unused filename.
   int i = 1;
-  char buf [PATH_MAX];
+  size_t buf_length = _cert_dir.length() + 100;
+  char *buf = new char[buf_length];
+#ifdef _WIN32
+  wstring buf_w;
+#endif // _WIN32
+
   while (true) {
     sprintf(buf, "%s/p%d.crt", _cert_dir.c_str(), i);
+    assert(strlen(buf) < buf_length);
 
     // Check if it already exists.  If not, take it.
 #ifdef _WIN32
-    DWORD results = GetFileAttributes(buf);
+    DWORD results = 0;
+    if (string_to_wstring(buf_w, buf)) {
+      results = GetFileAttributesW(buf_w.c_str());
+    }
     if (results == -1) {
       break;
     }
@@ -227,11 +234,17 @@ approve_cert() {
 
   // Sure, there's a slight race condition right now: another process
   // might attempt to create the same filename.  So what.
-  FILE *fp = fopen(buf, "w");
+  FILE *fp = NULL;
+#ifdef _WIN32
+  fp = _wfopen(buf_w.c_str(), L"w");
+#else // _WIN32
+  fp = fopen(buf, "w");
+#endif  // _WIN32
   if (fp != NULL) {
     PEM_write_X509(fp, _cert);
     fclose(fp);
   }
+
   hide();
 }
 
@@ -243,7 +256,16 @@ approve_cert() {
 ////////////////////////////////////////////////////////////////////
 void AuthDialog::
 read_cert_file(const string &cert_filename) {
-  FILE *fp = fopen(cert_filename.c_str(), "r");
+  FILE *fp = NULL;
+#ifdef _WIN32
+  wstring cert_filename_w;
+  if (string_to_wstring(cert_filename_w, cert_filename)) {
+    fp = _wfopen(cert_filename_w.c_str(), L"r");
+  }
+#else // _WIN32
+  fp = fopen(cert_filename.c_str(), "r");
+#endif  // _WIN32
+
   if (fp == NULL) {
     cerr << "Couldn't read " << cert_filename.c_str() << "\n";
     return;

+ 44 - 6
direct/src/plugin/p3dCert_wx.cxx

@@ -13,6 +13,9 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "p3dCert_wx.h"
+#include "wstring_encode.h"
+#include "mkdir_complete.h"
+
 #include "wx/cmdline.h"
 #include "wx/filename.h"
 
@@ -229,26 +232,52 @@ approve_cert() {
   assert(_cert != NULL);
 
   // Make sure the directory exists.
-  wxFileName::Mkdir(_cert_dir, 0777, wxPATH_MKDIR_FULL);
+  string cert_dir_str = (const char *)_cert_dir.mb_str();
+  mkdir_complete(cert_dir_str, cerr);
 
   // Look for an unused filename.
-  wxString pathname;
   int i = 1;
+  size_t buf_length = _cert_dir.length() + 100;
+  char *buf = new char[buf_length];
+#ifdef _WIN32
+  wstring buf_w;
+#endif // _WIN32
+
   while (true) {
-    pathname.Printf(wxT("%s/p%d.crt"), _cert_dir.c_str(), i);
-    if (!wxFileName::FileExists(pathname)) {
+    sprintf(buf, "%s/p%d.crt", _cert_dir.c_str(), i);
+    assert(strlen(buf) < buf_length);
+
+    // Check if it already exists.  If not, take it.
+#ifdef _WIN32
+    DWORD results = 0;
+    if (string_to_wstring(buf_w, buf)) {
+      results = GetFileAttributesW(buf_w.c_str());
+    }
+    if (results == -1) {
+      break;
+    }
+#else
+    struct stat statbuf;
+    if (stat(buf, &statbuf) != 0) {
       break;
     }
+#endif
     ++i;
   }
 
   // Sure, there's a slight race condition right now: another process
   // might attempt to create the same filename.  So what.
-  FILE *fp = fopen(pathname.mb_str(), "w");
+  FILE *fp = NULL;
+#ifdef _WIN32
+  fp = _wfopen(buf_w.c_str(), L"w");
+#else // _WIN32
+  fp = fopen(buf, "w");
+#endif  // _WIN32
   if (fp != NULL) {
     PEM_write_X509(fp, _cert);
     fclose(fp);
   }
+
   Destroy();
 }
 
@@ -260,7 +289,16 @@ approve_cert() {
 ////////////////////////////////////////////////////////////////////
 void AuthDialog::
 read_cert_file(const wxString &cert_filename) {
-  FILE *fp = fopen(cert_filename.mb_str(), "r");
+  FILE *fp = NULL;
+#ifdef _WIN32
+  wstring cert_filename_w;
+  if (string_to_wstring(cert_filename_w, (const char *)cert_filename.mb_str())) {
+    fp = _wfopen(cert_filename_w.c_str(), L"r");
+  }
+#else // _WIN32
+  fp = fopen(cert_filename.mb_str(), "r");
+#endif  // _WIN32
+
   if (fp == NULL) {
     cerr << "Couldn't read " << cert_filename.mb_str() << "\n";
     return;

+ 8 - 0
direct/src/plugin/p3dFileDownload.cxx

@@ -15,6 +15,7 @@
 #include "p3dFileDownload.h"
 #include "p3dInstanceManager.h"
 #include "mkdir_complete.h"
+#include "wstring_encode.h"
 
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DFileDownload::Constructor
@@ -64,7 +65,14 @@ open_file() {
   }
 
   _file.clear();
+#ifdef _WIN32
+  wstring filename_w;
+  if (string_to_wstring(filename_w, _filename)) {
+    _file.open(filename_w.c_str(), ios::out | ios::trunc | ios::binary);
+  }
+#else // _WIN32
   _file.open(_filename.c_str(), ios::out | ios::trunc | ios::binary);
+#endif  // _WIN32
   if (!_file) {
     nout << "Failed to open " << _filename << " in write mode\n";
     return false;

+ 95 - 8
direct/src/plugin/p3dHost.cxx

@@ -16,6 +16,7 @@
 #include "p3dInstanceManager.h"
 #include "p3dPackage.h"
 #include "mkdir_complete.h"
+#include "wstring_encode.h"
 #include "openssl/md5.h"
 
 #include <algorithm>
@@ -772,7 +773,12 @@ standardize_filename(const string &filename) {
 ////////////////////////////////////////////////////////////////////
 bool P3DHost::
 copy_file(const string &from_filename, const string &to_filename) {
-  ifstream in(from_filename.c_str(), ios::in | ios::binary);
+#ifdef _WIN32
+  ifstream in;
+  wstring from_filename_w;
+  if (string_to_wstring(from_filename_w, from_filename)) {
+    in.open(from_filename_w.c_str(), ios::in | ios::binary);
+  }
 
   // Copy to a temporary file first, in case (a) the filenames
   // actually refer to the same file, or (b) in case we have different
@@ -780,13 +786,66 @@ copy_file(const string &from_filename, const string &to_filename) {
   // partially overwriting the file should something go wrong.
   ostringstream strm;
   strm << to_filename << ".t";
-#ifdef _WIN32
   strm << GetCurrentProcessId() << "_" << GetCurrentThreadId();
-#else
+  string temp_filename = strm.str();
+  ofstream out;
+  wstring temp_filename_w;
+  if (string_to_wstring(temp_filename_w, temp_filename)) {
+    out.open(temp_filename_w.c_str(), ios::out | ios::binary);
+  }
+        
+  static const size_t buffer_size = 4096;
+  char buffer[buffer_size];
+  
+  in.read(buffer, buffer_size);
+  size_t count = in.gcount();
+  while (count != 0) {
+    out.write(buffer, count);
+    if (out.fail()) {
+      unlink(temp_filename.c_str());
+      return false;
+    }
+    in.read(buffer, buffer_size);
+    count = in.gcount();
+  }
+  out.close();
+
+  wstring to_filename_w;
+  string_to_wstring(to_filename_w, to_filename);
+
+  if (!in.eof()) {
+    _wunlink(temp_filename_w.c_str());
+    return false;
+  }
+
+  if (_wrename(temp_filename_w.c_str(), to_filename_w.c_str()) == 0) {
+    return true;
+  }
+
+  _wunlink(to_filename_w.c_str());
+  if (_wrename(temp_filename_w.c_str(), to_filename_w.c_str()) == 0) {
+    return true;
+  }
+
+  _wunlink(temp_filename_w.c_str());
+  return false;
+
+#else  // _WIN32
+
+  ifstream in;
+  in.open(from_filename.c_str(), ios::in | ios::binary);
+
+  // Copy to a temporary file first, in case (a) the filenames
+  // actually refer to the same file, or (b) in case we have different
+  // processes writing to the same file, and (c) to prevent
+  // partially overwriting the file should something go wrong.
+  ostringstream strm;
+  strm << to_filename << ".t";
   strm << getpid();
-#endif
+
   string temp_filename = strm.str();
-  ofstream out(temp_filename.c_str(), ios::out | ios::binary);
+  ofstream out;
+  out.open(temp_filename.c_str(), ios::out | ios::binary);
         
   static const size_t buffer_size = 4096;
   char buffer[buffer_size];
@@ -820,6 +879,7 @@ copy_file(const string &from_filename, const string &to_filename) {
 
   unlink(temp_filename.c_str());
   return false;
+#endif  // _WIN32
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -833,13 +893,39 @@ save_xml_file(TiXmlDocument *doc, const string &to_filename) {
   // Save to a temporary file first, in case (a) we have different
   // processes writing to the same file, and (b) to prevent partially
   // overwriting the file should something go wrong.
+
+#ifdef _WIN32
   ostringstream strm;
   strm << to_filename << ".t";
-#ifdef _WIN32
   strm << GetCurrentProcessId() << "_" << GetCurrentThreadId();
-#else
+  string temp_filename = strm.str();
+
+  wstring temp_filename_w;
+  string_to_wstring(temp_filename_w, temp_filename);
+  wstring to_filename_w;
+  string_to_wstring(to_filename_w, to_filename);
+
+  if (!doc->SaveFile(temp_filename.c_str())) {
+    _wunlink(temp_filename_w.c_str());
+    return false;
+  }
+
+  if (_wrename(temp_filename_w.c_str(), to_filename_w.c_str()) == 0) {
+    return true;
+  }
+
+  _wunlink(to_filename_w.c_str());
+  if (_wrename(temp_filename_w.c_str(), to_filename_w.c_str()) == 0) {
+    return true;
+  }
+
+  _wunlink(temp_filename_w.c_str());
+  return false;
+
+#else  // _WIN32
+  ostringstream strm;
+  strm << to_filename << ".t";
   strm << getpid();
-#endif
   string temp_filename = strm.str();
 
   if (!doc->SaveFile(temp_filename.c_str())) {
@@ -858,6 +944,7 @@ save_xml_file(TiXmlDocument *doc, const string &to_filename) {
 
   unlink(temp_filename.c_str());
   return false;
+#endif  // _WIN32
 }
 
 ////////////////////////////////////////////////////////////////////

+ 72 - 33
direct/src/plugin/p3dInstanceManager.cxx

@@ -28,6 +28,7 @@
 #include "get_tinyxml.h"
 #include "binaryXml.h"
 #include "mkdir_complete.h"
+#include "wstring_encode.h"
 
 // We can include this header file to get the DTOOL_PLATFORM
 // definition, even though we don't link with dtool.
@@ -1034,9 +1035,12 @@ scan_directory(const string &dirname, vector<string> &contents) {
   size_t orig_size = contents.size();
 
   string match = dirname + "\\*.*";
-  WIN32_FIND_DATA find_data;
+  WIN32_FIND_DATAW find_data;
 
-  HANDLE handle = FindFirstFile(match.c_str(), &find_data);
+  wstring match_w;
+  string_to_wstring(match_w, match);
+
+  HANDLE handle = FindFirstFileW(match_w.c_str(), &find_data);
   if (handle == INVALID_HANDLE_VALUE) {
     if (GetLastError() == ERROR_NO_MORE_FILES) {
       // No matching files is not an error.
@@ -1046,11 +1050,12 @@ scan_directory(const string &dirname, vector<string> &contents) {
   }
 
   do {
-    string filename = find_data.cFileName;
+    string filename;
+    wstring_to_string(filename, find_data.cFileName);
     if (filename != "." && filename != "..") {
       contents.push_back(filename);
     }
-  } while (FindNextFile(handle, &find_data));
+  } while (FindNextFileW(handle, &find_data));
 
   bool scan_ok = (GetLastError() == ERROR_NO_MORE_FILES);
   FindClose(handle);
@@ -1146,14 +1151,23 @@ delete_directory_recursively(const string &root_dir) {
   if (!scan_directory_recursively(root_dir, contents, dirname_contents)) {
     // Maybe it's just a single file, not a directory.  Delete it.
 #ifdef _WIN32
+    wstring root_dir_w;
+    string_to_wstring(root_dir_w, root_dir);
     // Windows can't delete a file if it's read-only.
-    chmod(root_dir.c_str(), 0644);
-#endif
+    _wchmod(root_dir_w.c_str(), 0644);
+    int result = _wunlink(root_dir_w.c_str());
+#else  // _WIN32
     int result = unlink(root_dir.c_str());
+#endif  // _WIN32
     if (result == 0) {
       nout << "Deleted " << root_dir << "\n";
     } else {
-      if (access(root_dir.c_str(), 0) == 0) {
+#ifdef _WIN32
+      result = _waccess(root_dir_w.c_str(), 0);
+#else  // _WIN32
+      result = access(root_dir.c_str(), 0);
+#endif  // _WIN32
+      if (result == 0) {
         nout << "Could not delete " << root_dir << "\n";
       }
     }
@@ -1166,10 +1180,14 @@ delete_directory_recursively(const string &root_dir) {
     string pathname = root_dir + "/" + filename;
 
 #ifdef _WIN32
+    wstring pathname_w;
+    string_to_wstring(pathname_w, pathname);
     // Windows can't delete a file if it's read-only.
-    chmod(pathname.c_str(), 0644);
-#endif
+    _wchmod(pathname_w.c_str(), 0644);
+    int result = _wunlink(pathname_w.c_str());
+#else  // _WIN32
     int result = unlink(pathname.c_str());
+#endif  // _WIN32
     if (result == 0) {
       nout << "  Deleted " << filename << "\n";
     } else {
@@ -1184,9 +1202,13 @@ delete_directory_recursively(const string &root_dir) {
     string pathname = root_dir + "/" + filename;
 
 #ifdef _WIN32
-    chmod(pathname.c_str(), 0755);
-#endif
+    wstring pathname_w;
+    string_to_wstring(pathname_w, pathname);
+    _wchmod(pathname_w.c_str(), 0755);
+    int result = _wrmdir(pathname_w.c_str());
+#else  // _WIN32
     int result = rmdir(pathname.c_str());
+#endif  // _WIN32
     if (result == 0) {
       nout << "  Removed directory " << filename << "\n";
     } else {
@@ -1197,13 +1219,22 @@ delete_directory_recursively(const string &root_dir) {
   // Finally, delete the root directory itself.
   string pathname = root_dir;
 #ifdef _WIN32
-  chmod(pathname.c_str(), 0755);
-#endif
+  wstring pathname_w;
+  string_to_wstring(pathname_w, pathname);
+  _wchmod(pathname_w.c_str(), 0755);
+  int result = _wrmdir(pathname_w.c_str());
+#else  // _WIN32
   int result = rmdir(pathname.c_str());
+#endif  // _WIN32
   if (result == 0) {
     nout << "Removed directory " << root_dir << "\n";
   } else {
-    if (access(pathname.c_str(), 0) == 0) {
+#ifdef _WIN32
+    result = _waccess(pathname_w.c_str(), 0);
+#else  // _WIN32
+    result = access(pathname.c_str(), 0);
+#endif  // _WIN32
+    if (result == 0) {
       nout << "Could not remove directory " << root_dir << "\n";
     }
   }
@@ -1295,7 +1326,13 @@ create_runtime_environment() {
 
   logfile.close();
   logfile.clear();
+#ifdef _WIN32
+  wstring log_pathname_w;
+  string_to_wstring(log_pathname_w, _log_pathname);
+  logfile.open(log_pathname_w.c_str(), ios::out | ios::trunc);
+#else
   logfile.open(_log_pathname.c_str(), ios::out | ios::trunc);
+#endif  // _WIN32
   if (logfile) {
     logfile.setf(ios::unitbuf);
     nout_stream = &logfile;
@@ -1303,7 +1340,8 @@ create_runtime_environment() {
 
   // Determine the temporary directory.
 #ifdef _WIN32
-  char buffer_1[MAX_PATH];
+  wchar_t buffer_1[MAX_PATH];
+  wstring temp_directory_w;
 
   // Figuring out the correct path for temporary files is a real mess
   // on Windows.  We should be able to use GetTempPath(), but that
@@ -1328,23 +1366,23 @@ create_runtime_environment() {
   // SHGetSpecialFolderPath().
 
   if (getenv("TEMP") != NULL || getenv("TMP") != NULL) {
-    if (GetTempPath(MAX_PATH, buffer_1) != 0) {
-      _temp_directory = buffer_1;
+    if (GetTempPathW(MAX_PATH, buffer_1) != 0) {
+      temp_directory_w = buffer_1;
     }
   }
-  if (_temp_directory.empty()) {
-    if (SHGetSpecialFolderPath(NULL, buffer_1, CSIDL_INTERNET_CACHE, true)) {
-      _temp_directory = buffer_1;
+  if (temp_directory_w.empty()) {
+    if (SHGetSpecialFolderPathW(NULL, buffer_1, CSIDL_INTERNET_CACHE, true)) {
+      temp_directory_w = buffer_1;
 
       // That just *might* return a non-writable folder, if we're in
       // Protected Mode.  We'll test this with GetTempFileName().
-      char temp_buffer[MAX_PATH];
-      if (!GetTempFileName(_temp_directory.c_str(), "p3d", 0, temp_buffer)) {
-        nout << "GetTempFileName failed on " << _temp_directory
+      wchar_t temp_buffer[MAX_PATH];
+      if (!GetTempFileNameW(temp_directory_w.c_str(), L"p3d", 0, temp_buffer)) {
+        nout << "GetTempFileName failed on " << temp_directory_w
              << ", switching to GetTempPath\n";
-        _temp_directory.clear();
+        temp_directory_w.clear();
       } else {
-        DeleteFile(temp_buffer);
+        DeleteFileW(temp_buffer);
       }
     }
   }
@@ -1352,22 +1390,23 @@ create_runtime_environment() {
   // If both of the above failed, we'll fall back to GetTempPath()
   // once again as a last resort, which is supposed to return
   // *something* that works, even if $TEMP and $TMP are undefined.
-  if (_temp_directory.empty()) {
-    if (GetTempPath(MAX_PATH, buffer_1) != 0) {
-      _temp_directory = buffer_1;
+  if (temp_directory_w.empty()) {
+    if (GetTempPathW(MAX_PATH, buffer_1) != 0) {
+      temp_directory_w = buffer_1;
     }
   }
 
   // Also insist that the temp directory is fully specified.
-  size_t needs_size_2 = GetFullPathName(_temp_directory.c_str(), 0, NULL, NULL);
-  char *buffer_2 = new char[needs_size_2];
-  if (GetFullPathName(_temp_directory.c_str(), needs_size_2, buffer_2, NULL) != 0) {
-    _temp_directory = buffer_2;
+  size_t needs_size_2 = GetFullPathNameW(temp_directory_w.c_str(), 0, NULL, NULL);
+  wchar_t *buffer_2 = new wchar_t[needs_size_2];
+  if (GetFullPathNameW(temp_directory_w.c_str(), needs_size_2, buffer_2, NULL) != 0) {
+    temp_directory_w = buffer_2;
   }
   delete[] buffer_2;
 
   // And make sure the directory actually exists.
-  mkdir_complete(_temp_directory, nout);
+  mkdir_complete_w(temp_directory_w, nout);
+  wstring_to_string(_temp_directory, temp_directory_w);
 
 #else
   _temp_directory = "/tmp/";

+ 17 - 1
direct/src/plugin/p3dMultifileReader.cxx

@@ -15,6 +15,7 @@
 #include "p3dMultifileReader.h"
 #include "p3dPackage.h"
 #include "mkdir_complete.h"
+#include "wstring_encode.h"
 
 #include <time.h>
 
@@ -108,7 +109,15 @@ extract_all(const string &to_dir, P3DPackage *package,
       return false;
     }
 
-    ofstream out(output_pathname.c_str(), ios::out | ios::binary);
+    ofstream out;
+#ifdef _WIN32
+    wstring output_pathname_w;
+    if (string_to_wstring(output_pathname_w, output_pathname)) {
+      out.open(output_pathname_w.c_str(), ios::out | ios::binary);
+    }
+#else // _WIN32
+    out.open(output_pathname.c_str(), ios::out | ios::binary);
+#endif  // _WIN32
     if (!out) {
       nout << "Unable to write to " << output_pathname << "\n";
       return false;
@@ -217,7 +226,14 @@ read_header(const string &pathname) {
   _cert_special.clear();
   _signatures.clear();
 
+#ifdef _WIN32
+  wstring pathname_w;
+  if (string_to_wstring(pathname_w, pathname)) {
+    _in.open(pathname_w.c_str(), ios::in | ios::binary);
+  }
+#else // _WIN32
   _in.open(pathname.c_str(), ios::in | ios::binary);
+#endif  // _WIN32
   if (!_in) {
     nout << "Couldn't open " << pathname << "\n";
     return false;

+ 19 - 2
direct/src/plugin/p3dPackage.cxx

@@ -19,6 +19,7 @@
 #include "p3dTemporaryFile.h"
 #include "p3dPatchFinder.h"
 #include "mkdir_complete.h"
+#include "wstring_encode.h"
 
 #include "zlib.h"
 
@@ -1851,7 +1852,15 @@ thread_step() {
   string source_pathname = _package->get_package_dir() + "/" + _source.get_filename();
   string target_pathname = _package->get_package_dir() + "/" + _target.get_filename();
 
-  ifstream source(source_pathname.c_str(), ios::in | ios::binary);
+  ifstream source;
+#ifdef _WIN32
+  wstring source_pathname_w;
+  if (string_to_wstring(source_pathname_w, source_pathname)) {
+    source.open(source_pathname_w.c_str(), ios::in | ios::binary);
+  }
+#else // _WIN32
+  source.open(source_pathname.c_str(), ios::in | ios::binary);
+#endif  // _WIN32
   if (!source) {
     nout << "Couldn't open " << source_pathname << "\n";
     return IT_step_failed;
@@ -1861,7 +1870,15 @@ thread_step() {
     return IT_step_failed;
   }
 
-  ofstream target(target_pathname.c_str(), ios::out | ios::binary);
+  ofstream target;
+#ifdef _WIN32
+  wstring target_pathname_w;
+  if (string_to_wstring(target_pathname_w, target_pathname)) {
+    target.open(target_pathname_w.c_str(), ios::out | ios::binary);
+  }
+#else // _WIN32
+  target.open(target_pathname.c_str(), ios::out | ios::binary);
+#endif  // _WIN32
   if (!target) {
     nout << "Couldn't write to " << target_pathname << "\n";
     return IT_step_failed;

+ 23 - 1
direct/src/plugin/p3dPatchfileReader.cxx

@@ -13,6 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "p3dPatchfileReader.h"
+#include "wstring_encode.h"
 
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DPatchfileReader::Constructor
@@ -62,15 +63,36 @@ open_read() {
 
   string patch_pathname = _patchfile.get_pathname(_package_dir);
   _patch_in.clear();
+#ifdef _WIN32
+  wstring patch_pathname_w;
+  if (string_to_wstring(patch_pathname_w, patch_pathname)) {
+    _patch_in.open(patch_pathname_w.c_str(), ios::in | ios::binary);
+  }
+#else // _WIN32
   _patch_in.open(patch_pathname.c_str(), ios::in | ios::binary);
+#endif  // _WIN32
 
   string source_pathname = _source.get_pathname(_package_dir);
   _source_in.clear();
+#ifdef _WIN32
+  wstring source_pathname_w;
+  if (string_to_wstring(source_pathname_w, source_pathname)) {
+    _source_in.open(source_pathname_w.c_str(), ios::in | ios::binary);
+  }
+#else // _WIN32
   _source_in.open(source_pathname.c_str(), ios::in | ios::binary);
+#endif  // _WIN32
 
   mkfile_complete(_output_pathname, nout);
   _target_out.clear();
-  _target_out.open(_output_pathname.c_str(), ios::out | ios::binary);
+#ifdef _WIN32
+  wstring output_pathname_w;
+  if (string_to_wstring(output_pathname_w, _output_pathname)) {
+    _target_out.open(output_pathname_w.c_str(), ios::in | ios::binary);
+  }
+#else // _WIN32
+  _target_out.open(_output_pathname.c_str(), ios::in | ios::binary);
+#endif  // _WIN32
 
   _is_open = true;
 

+ 21 - 12
direct/src/plugin/p3dSession.cxx

@@ -26,6 +26,7 @@
 #include "p3dConcreteStruct.h"
 #include "binaryXml.h"
 #include "mkdir_complete.h"
+#include "wstring_encode.h"
 #include "run_p3dpython.h"
 
 #include <ctype.h>
@@ -1481,8 +1482,10 @@ win_create_process() {
   HANDLE error_handle = GetStdHandle(STD_ERROR_HANDLE);
   bool got_error_handle = false;
   if (!_log_pathname.empty()) {
-    HANDLE handle = CreateFile
-      (_log_pathname.c_str(), GENERIC_WRITE, 
+    wstring log_pathname_w;
+    string_to_wstring(log_pathname_w, _log_pathname);
+    HANDLE handle = CreateFileW
+      (log_pathname_w.c_str(), GENERIC_WRITE, 
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL, CREATE_ALWAYS, 0, NULL);
     if (handle != INVALID_HANDLE_VALUE) {
@@ -1494,8 +1497,8 @@ win_create_process() {
     }
   }
 
-  STARTUPINFO startup_info;
-  ZeroMemory(&startup_info, sizeof(STARTUPINFO));
+  STARTUPINFOW startup_info;
+  ZeroMemory(&startup_info, sizeof(startup_info));
   startup_info.cb = sizeof(startup_info); 
 
   // Set up the I/O handles.  We send stderr and stdout to our
@@ -1512,13 +1515,15 @@ win_create_process() {
   // If _keep_user_env is true, meaning not to change the current
   // directory, then pass NULL in to CreateProcess().  Otherwise pass
   // in _start_dir.
-  const char *start_dir_cstr;
+  const wchar_t *start_dir_cstr;
+  wstring start_dir_w;
   if (_keep_user_env) {
     start_dir_cstr = NULL;
     nout << "Not changing working directory.\n";
   } else {
-    start_dir_cstr = _start_dir.c_str();
-    nout << "Setting working directory: " << start_dir_cstr << "\n";
+    string_to_wstring(start_dir_w, _start_dir);
+    start_dir_cstr = start_dir_w.c_str();
+    nout << "Setting working directory: " << _start_dir << "\n";
   }
 
   // Construct the command-line string, containing the quoted
@@ -1531,13 +1536,17 @@ win_create_process() {
   // I'm not sure why CreateProcess wants a non-const char pointer for
   // its command-line string, but I'm not taking chances.  It gets a
   // non-const char array that it can modify.
-  string command_line_str = stream.str();
-  char *command_line = new char[command_line_str.size() + 1];
-  strcpy(command_line, command_line_str.c_str());
+  wstring command_line_str;
+  string_to_wstring(command_line_str, stream.str());
+  wchar_t *command_line = new wchar_t[command_line_str.size() + 1];
+  memcpy(command_line, command_line_str.c_str(), sizeof(wchar_t) * command_line_str.size() + 1);
+
+  wstring p3dpython_exe_w;
+  string_to_wstring(p3dpython_exe_w, _p3dpython_exe);
 
   PROCESS_INFORMATION process_info; 
-  BOOL result = CreateProcess
-    (_p3dpython_exe.c_str(), command_line, NULL, NULL, TRUE, 0,
+  BOOL result = CreateProcessW
+    (p3dpython_exe_w.c_str(), command_line, NULL, NULL, TRUE, 0,
      (void *)_env.c_str(), start_dir_cstr,
      &startup_info, &process_info);
   bool started_program = (result != 0);

+ 11 - 1
direct/src/plugin/p3dSplashWindow.cxx

@@ -13,6 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "p3dSplashWindow.h"
+#include "wstring_encode.h"
 
 // Stuff to use libpng.
 #include <png.h>
@@ -259,7 +260,16 @@ read_image_data(ImageData &image, string &data,
   }
 
   // We only support JPEG or PNG images.
-  FILE *fp = fopen(image_filename.c_str(), "rb");
+  FILE *fp = NULL;
+#ifdef _WIN32
+  wstring image_filename_w;
+  if (string_to_wstring(image_filename_w, image_filename)) {
+    fp = _wfopen(image_filename_w.c_str(), L"rb");
+  }
+#else // _WIN32
+  fp = fopen(image_filename.c_str(), "rb");
+#endif  // _WIN32
+
   if (fp == NULL) {
     nout << "Couldn't open splash file image: " << image_filename << "\n";
     return false;

+ 4 - 1
direct/src/plugin_activex/PPDownloadRequest.cpp

@@ -16,6 +16,7 @@
 
 #include "PPDownloadRequest.h"
 #include "PPInstance.h"
+#include "wstring_encode.h"
 
 bool PPDownloadRequest::Begin( ) 
 {
@@ -54,7 +55,9 @@ bool PPDownloadRequest::DataNotify( size_t expectedDataSize, const void* data, s
         {
             if ( m_hFile == INVALID_HANDLE_VALUE )
             {
-                m_hFile = ::CreateFile( m_fileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
+                wstring filename_w;
+                string_to_wstring(filename_w, m_fileName);
+                m_hFile = ::CreateFileW( filename_w.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
                 if ( m_hFile == INVALID_HANDLE_VALUE )
                 {
                     return ret;

+ 9 - 6
direct/src/plugin_activex/PPInstance.cpp

@@ -40,6 +40,7 @@
 #include "find_root_dir.h"
 #include "mkdir_complete.h"
 #include "parse_color.h"
+#include "wstring_encode.h"
 
 // We can include this header file to get the DTOOL_PLATFORM
 // definition, even though we don't link with dtool.
@@ -79,6 +80,7 @@ PPInstance::PPInstance( CP3DActiveXCtrl& parentCtrl ) :
 {
   // We need the root dir first.
   m_rootDir = find_root_dir( );
+  string_to_wstring(m_rootDir_w, m_rootDir);
 
   // Then open the logfile.
   m_logger.Open( m_rootDir );
@@ -452,13 +454,14 @@ int PPInstance::DownloadP3DComponents( std::string& p3dDllFilename )
     if (!already_got) {
       // OK, we need to download a new contents.xml file.  Start off
       // by downloading it into a local temporary file.
-      TCHAR tempFileName[ MAX_PATH ];
-      if (!::GetTempFileName( m_rootDir.c_str(), "p3d", 0, tempFileName )) {
+      WCHAR local_filename_w[ MAX_PATH ];
+      if (!::GetTempFileNameW( m_rootDir_w.c_str(), L"p3d", 0, local_filename_w )) {
         nout << "GetTempFileName failed (folder is " << m_rootDir << ")\n";
         return 1;
       }
       
-      std::string localContentsFileName( tempFileName );
+      std::string local_filename;
+      wstring_to_string(local_filename, local_filename_w);
 
       std::string hostUrl( PANDA_PACKAGE_HOST_URL );
       if (!hostUrl.empty() && hostUrl[hostUrl.size() - 1] != '/') {
@@ -471,9 +474,9 @@ int PPInstance::DownloadP3DComponents( std::string& p3dDllFilename )
       strm << hostUrl << P3D_CONTENTS_FILENAME << "?" << time(NULL);
       std::string remoteContentsUrl( strm.str() );
       
-      error = DownloadFile( remoteContentsUrl, localContentsFileName );
+      error = DownloadFile( remoteContentsUrl, local_filename );
       if ( !error ) {
-        if ( !read_contents_file( localContentsFileName, true ) )
+        if ( !read_contents_file( local_filename, true ) )
           error = 1;
       }
 
@@ -485,7 +488,7 @@ int PPInstance::DownloadP3DComponents( std::string& p3dDllFilename )
       }
 
       // We don't need the temporary file any more.
-      ::DeleteFile( localContentsFileName.c_str() );
+      ::DeleteFileW( local_filename_w );
     }
       
     if (!error) {

+ 1 - 0
direct/src/plugin_activex/PPInstance.h

@@ -110,6 +110,7 @@ protected:
     int _num_tokens;
 
     std::string m_rootDir;
+    std::wstring m_rootDir_w;
 
     class ThreadedRequestData {
     public:

+ 4 - 62
direct/src/plugin_activex/PPLogger.cpp

@@ -17,6 +17,7 @@
 #include "windows.h"
 #include "PPLogger.h"
 #include "mkdir_complete.h"
+#include "wstring_encode.h"
 
 std::ofstream PPLogger::m_logfile;
 bool PPLogger::m_isOpen = false;
@@ -29,67 +30,6 @@ PPLogger::~PPLogger( )
 {
 }
 
-int PPLogger::CreateNewFolder( const std::string& dirname ) 
-{
-    int error( 0 );
-    if ( CreateDirectory( dirname.c_str( ), NULL ) != 0 ) 
-    {
-        // Success!
-        return error;
-    }
-    // Failed.
-    DWORD lastError = GetLastError( );
-    if ( lastError == ERROR_ALREADY_EXISTS ) 
-    {
-        // Not really an error: the directory is already there.
-        return error;
-    }
-    if ( lastError == ERROR_PATH_NOT_FOUND ) 
-    {
-        // We need to make the parent directory first.
-        std::string parent = dirname;
-        if ( !parent.empty() && CreateNewFolder( parent ) ) 
-        {
-            // Parent successfully created.  Try again to make the child.
-            if ( CreateDirectory( dirname.c_str(), NULL ) != 0) 
-            {
-                // Got it!
-                return error;
-            }
-            m_logfile << "Couldn't create " << dirname << "\n";
-        }
-    }
-    return ( error = 1 );
-}
-
-int PPLogger::CreateNewFile(const std::string& dirname, const std::string& filename) 
-{
-    int error( 0 );
-    std::string logfilename = dirname + filename;
-    HANDLE file = CreateFile( logfilename.c_str(), GENERIC_READ | GENERIC_WRITE,
-        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
-        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
-    if ( file == INVALID_HANDLE_VALUE ) 
-    {
-        // Try to make the parent directory first.
-        std::string parent = dirname;
-        if ( !parent.empty( ) && CreateNewFolder( parent ) ) 
-        {
-            // Parent successfully created.  Try again to make the file.
-            file = CreateFile( logfilename.c_str(), GENERIC_READ | GENERIC_WRITE,
-                FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
-                NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
-        }
-        if ( file == INVALID_HANDLE_VALUE ) 
-        {
-            m_logfile << "Couldn't create " << filename << "\n";
-            return ( error = 1 );
-        }
-    }
-    CloseHandle( file );
-    return error;
-}
-
 void PPLogger::Open( const std::string &rootDir ) 
 {
   if (!m_isOpen) {
@@ -137,7 +77,9 @@ void PPLogger::Open( const std::string &rootDir )
 
       m_logfile.close();
       m_logfile.clear();
-      m_logfile.open(log_pathname.c_str(), std::ios::out | std::ios::trunc);
+      wstring log_pathname_w;
+      string_to_wstring(log_pathname_w, log_pathname);
+      m_logfile.open(log_pathname_w.c_str(), std::ios::out | std::ios::trunc);
       m_logfile.setf(std::ios::unitbuf);
     }
 

+ 0 - 3
direct/src/plugin_activex/PPLogger.h

@@ -30,9 +30,6 @@ public:
     static std::ofstream& Log( ) { return m_logfile; }
 
 protected:
-  int CreateNewFile(const std::string& dirname, const std::string& filename );
-  int CreateNewFolder( const std::string& dirname );
-
   static bool m_isOpen;
   static std::ofstream m_logfile;
 };

+ 7 - 0
direct/src/plugin_npapi/startup.cxx

@@ -16,6 +16,7 @@
 #include "p3d_plugin_config.h"
 #include "p3d_lock.h"
 #include "ppBrowserObject.h"
+#include "wstring_encode.h"
 
 #ifdef _WIN32
 #include <shlobj.h>
@@ -90,7 +91,13 @@ open_logfile() {
 
       logfile.close();
       logfile.clear();
+#ifdef _WIN32
+      wstring log_pathname_w;
+      string_to_wstring(log_pathname_w, log_pathname);
+      logfile.open(log_pathname_w.c_str(), ios::out | ios::trunc);
+#else
       logfile.open(log_pathname.c_str(), ios::out | ios::trunc);
+#endif  // _WIN32
       logfile.setf(ios::unitbuf);
     }