From 9150bd2f6c0977b6861d1cb570afdcf140ece4d2 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 30 Aug 2011 02:54:01 +0000 Subject: [PATCH] wip: support windows unicode filenames in plugin --- direct/src/plugin/Sources.pp | 10 +- direct/src/plugin/fileSpec.cxx | 51 +++++- direct/src/plugin/find_root_dir.cxx | 125 ++++++-------- direct/src/plugin/is_pathsep.I | 2 +- direct/src/plugin/is_pathsep.h | 2 +- direct/src/plugin/load_plugin.cxx | 6 +- direct/src/plugin/mkdir_complete.cxx | 161 ++++++++++++------ direct/src/plugin/mkdir_complete.h | 5 + direct/src/plugin/p3dAuthSession.cxx | 25 ++- direct/src/plugin/p3dCert.cxx | 40 ++++- direct/src/plugin/p3dCert_wx.cxx | 50 +++++- direct/src/plugin/p3dFileDownload.cxx | 8 + direct/src/plugin/p3dHost.cxx | 105 +++++++++++- direct/src/plugin/p3dInstanceManager.cxx | 105 ++++++++---- direct/src/plugin/p3dMultifileReader.cxx | 18 +- direct/src/plugin/p3dPackage.cxx | 21 ++- direct/src/plugin/p3dPatchfileReader.cxx | 24 ++- direct/src/plugin/p3dSession.cxx | 33 ++-- direct/src/plugin/p3dSplashWindow.cxx | 12 +- .../src/plugin_activex/PPDownloadRequest.cpp | 5 +- direct/src/plugin_activex/PPInstance.cpp | 15 +- direct/src/plugin_activex/PPInstance.h | 1 + direct/src/plugin_activex/PPLogger.cpp | 66 +------ direct/src/plugin_activex/PPLogger.h | 3 - direct/src/plugin_npapi/startup.cxx | 7 + 25 files changed, 614 insertions(+), 286 deletions(-) diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp index d30c4e007e..1fe7376699 100644 --- a/direct/src/plugin/Sources.pp +++ b/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 // diff --git a/direct/src/plugin/fileSpec.cxx b/direct/src/plugin/fileSpec.cxx index f542a52546..5c4f9816c3 100755 --- a/direct/src/plugin/fileSpec.cxx +++ b/direct/src/plugin/fileSpec.cxx @@ -13,6 +13,7 @@ //////////////////////////////////////////////////////////////////// #include "fileSpec.h" +#include "wstring_encode.h" #include "openssl/md5.h" #include @@ -26,8 +27,6 @@ #ifdef _WIN32 #include #include -#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; diff --git a/direct/src/plugin/find_root_dir.cxx b/direct/src/plugin/find_root_dir.cxx index 0f9ad070ca..a0756e7d5f 100755 --- a/direct/src/plugin/find_root_dir.cxx +++ b/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 @@ -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//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//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; } } diff --git a/direct/src/plugin/is_pathsep.I b/direct/src/plugin/is_pathsep.I index 5c54341cdf..129ee105ed 100644 --- a/direct/src/plugin/is_pathsep.I +++ b/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; } diff --git a/direct/src/plugin/is_pathsep.h b/direct/src/plugin/is_pathsep.h index 6308c3383e..920426f3d3 100644 --- a/direct/src/plugin/is_pathsep.h +++ b/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" diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx index 04a8ac2370..a9276b9e99 100755 --- a/direct/src/plugin/load_plugin.cxx +++ b/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; } diff --git a/direct/src/plugin/mkdir_complete.cxx b/direct/src/plugin/mkdir_complete.cxx index 44d4a54e26..c8b051a7fc 100755 --- a/direct/src/plugin/mkdir_complete.cxx +++ b/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 @@ -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; + wstring dirname_w; + if (!string_to_wstring(dirname_w, dirname)) { + return false; } - - // 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"; - } - } - return false; + return mkdir_complete_w(dirname_w, logfile); #else //_WIN32 if (mkdir(dirname.c_str(), 0755) == 0) { @@ -125,36 +125,16 @@ 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) { - // 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); - } - if (file == INVALID_HANDLE_VALUE) { - logfile - << "Couldn't create " << filename << "\n"; - return false; - } - } - CloseHandle(file); - return true; - -#else // _WIN32 int fd = creat(filename.c_str(), 0755); if (fd == -1) { // Try to make the parent directory first. @@ -174,3 +154,80 @@ mkfile_complete(const string &filename, ostream &logfile) { #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. + wstring parent = get_dirname_w(filename); + if (!parent.empty() && mkdir_complete_w(parent, logfile)) { + // Parent successfully created. Try again to make the file. + 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) { + logfile + << "Couldn't create " << filename << "\n"; + return false; + } + } + CloseHandle(file); + return true; +} +#endif // _WIN32 diff --git a/direct/src/plugin/mkdir_complete.h b/direct/src/plugin/mkdir_complete.h index e55c29f7ec..e9d9d80871 100755 --- a/direct/src/plugin/mkdir_complete.h +++ b/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 diff --git a/direct/src/plugin/p3dAuthSession.cxx b/direct/src/plugin/p3dAuthSession.cxx index ee1c79e0d3..df0372efa7 100644 --- a/direct/src/plugin/p3dAuthSession.cxx +++ b/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 @@ -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); diff --git a/direct/src/plugin/p3dCert.cxx b/direct/src/plugin/p3dCert.cxx index 1161f2a7e5..5284499e8f 100644 --- a/direct/src/plugin/p3dCert.cxx +++ b/direct/src/plugin/p3dCert.cxx @@ -13,6 +13,8 @@ //////////////////////////////////////////////////////////////////// #include "p3dCert.h" +#include "wstring_encode.h" +#include "mkdir_complete.h" #include #include @@ -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; diff --git a/direct/src/plugin/p3dCert_wx.cxx b/direct/src/plugin/p3dCert_wx.cxx index e9e7e3c699..c765ef5514 100644 --- a/direct/src/plugin/p3dCert_wx.cxx +++ b/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; diff --git a/direct/src/plugin/p3dFileDownload.cxx b/direct/src/plugin/p3dFileDownload.cxx index b4390a11a0..68631f5e3c 100755 --- a/direct/src/plugin/p3dFileDownload.cxx +++ b/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; diff --git a/direct/src/plugin/p3dHost.cxx b/direct/src/plugin/p3dHost.cxx index c04c9b57a5..5bab667004 100644 --- a/direct/src/plugin/p3dHost.cxx +++ b/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 @@ -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 - strm << getpid(); -#endif string temp_filename = strm.str(); - ofstream out(temp_filename.c_str(), ios::out | ios::binary); + 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(); + + string temp_filename = strm.str(); + 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 } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index bc91ff4787..97c2c456d0 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/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 &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 &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/"; diff --git a/direct/src/plugin/p3dMultifileReader.cxx b/direct/src/plugin/p3dMultifileReader.cxx index 52dc4bdc30..8c38b3d041 100644 --- a/direct/src/plugin/p3dMultifileReader.cxx +++ b/direct/src/plugin/p3dMultifileReader.cxx @@ -15,6 +15,7 @@ #include "p3dMultifileReader.h" #include "p3dPackage.h" #include "mkdir_complete.h" +#include "wstring_encode.h" #include @@ -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; diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx index 541c259217..2d74eded59 100755 --- a/direct/src/plugin/p3dPackage.cxx +++ b/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; diff --git a/direct/src/plugin/p3dPatchfileReader.cxx b/direct/src/plugin/p3dPatchfileReader.cxx index 10854d13f1..f3e0313abc 100644 --- a/direct/src/plugin/p3dPatchfileReader.cxx +++ b/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; diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index 96662277f9..c5b639236e 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/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 @@ -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); diff --git a/direct/src/plugin/p3dSplashWindow.cxx b/direct/src/plugin/p3dSplashWindow.cxx index 1060d095c9..07c6b89ae1 100755 --- a/direct/src/plugin/p3dSplashWindow.cxx +++ b/direct/src/plugin/p3dSplashWindow.cxx @@ -13,6 +13,7 @@ //////////////////////////////////////////////////////////////////// #include "p3dSplashWindow.h" +#include "wstring_encode.h" // Stuff to use libpng. #include @@ -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; diff --git a/direct/src/plugin_activex/PPDownloadRequest.cpp b/direct/src/plugin_activex/PPDownloadRequest.cpp index 3e53fce359..961ae07d89 100644 --- a/direct/src/plugin_activex/PPDownloadRequest.cpp +++ b/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; diff --git a/direct/src/plugin_activex/PPInstance.cpp b/direct/src/plugin_activex/PPInstance.cpp index 994f82df40..a0984a27f6 100644 --- a/direct/src/plugin_activex/PPInstance.cpp +++ b/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) { diff --git a/direct/src/plugin_activex/PPInstance.h b/direct/src/plugin_activex/PPInstance.h index 61904e1932..9468f1070f 100644 --- a/direct/src/plugin_activex/PPInstance.h +++ b/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: diff --git a/direct/src/plugin_activex/PPLogger.cpp b/direct/src/plugin_activex/PPLogger.cpp index 25d6c79603..5eb6a85a01 100644 --- a/direct/src/plugin_activex/PPLogger.cpp +++ b/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); } diff --git a/direct/src/plugin_activex/PPLogger.h b/direct/src/plugin_activex/PPLogger.h index 34cb810096..79514872ac 100644 --- a/direct/src/plugin_activex/PPLogger.h +++ b/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; }; diff --git a/direct/src/plugin_npapi/startup.cxx b/direct/src/plugin_npapi/startup.cxx index c80bf9fdcf..41dc9e6753 100644 --- a/direct/src/plugin_npapi/startup.cxx +++ b/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 @@ -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); }