diff --git a/dtool/src/dtoolutil/executionEnvironment.cxx b/dtool/src/dtoolutil/executionEnvironment.cxx index 7c9df49a68..4006b5ac20 100644 --- a/dtool/src/dtoolutil/executionEnvironment.cxx +++ b/dtool/src/dtoolutil/executionEnvironment.cxx @@ -161,6 +161,31 @@ expand_string(const string &str) { //////////////////////////////////////////////////////////////////// Filename ExecutionEnvironment:: get_cwd() { +#ifdef WIN32_VC + // getcwd() requires us to allocate a dynamic buffer and grow it on + // demand. + static size_t bufsize = 1024; + static wchar_t *buffer = NULL; + + if (buffer == (wchar_t *)NULL) { + buffer = new wchar_t[bufsize]; + } + + while (_wgetcwd(buffer, bufsize) == (wchar_t *)NULL) { + if (errno != ERANGE) { + perror("getcwd"); + return string(); + } + delete[] buffer; + bufsize = bufsize * 2; + buffer = new wchar_t[bufsize]; + assert(buffer != (wchar_t *)NULL); + } + + Filename cwd = Filename::from_os_specific_w(buffer); + cwd.make_true_case(); + return cwd; +#else // WIN32_VC // getcwd() requires us to allocate a dynamic buffer and grow it on // demand. static size_t bufsize = 1024; @@ -184,6 +209,7 @@ get_cwd() { Filename cwd = Filename::from_os_specific(buffer); cwd.make_true_case(); return cwd; +#endif // WIN32_VC } //////////////////////////////////////////////////////////////////// @@ -233,6 +259,7 @@ ns_get_environment_variable(const string &var) const { if (!ns_has_environment_variable("PANDA_INCOMPATIBLE_PYTHON") && Py_IsInitialized()) { PyObject* obj = PySys_GetObject((char*) "argv"); if (obj) { + // Hmm, could this ever be a Unicode object? Filename main_dir = Filename::from_os_specific(PyString_AsString(PyList_GetItem(obj, 0))); if (main_dir.empty()) { // We must be running in the Python interpreter directly, so return the CWD. @@ -479,10 +506,10 @@ read_args() { #endif if (dllhandle != 0) { static const DWORD buffer_size = 1024; - char buffer[buffer_size]; - DWORD size = GetModuleFileName(dllhandle, buffer, buffer_size); + wchar_t buffer[buffer_size]; + DWORD size = GetModuleFileNameW(dllhandle, buffer, buffer_size); if (size != 0) { - Filename tmp = Filename::from_os_specific(string(buffer, size)); + Filename tmp = Filename::from_os_specific_w(wstring(buffer, size)); tmp.make_true_case(); _dtool_name = tmp; } @@ -557,10 +584,10 @@ read_args() { #ifdef WIN32_VC if (_binary_name.empty()) { static const DWORD buffer_size = 1024; - char buffer[buffer_size]; - DWORD size = GetModuleFileName(NULL, buffer, buffer_size); + wchar_t buffer[buffer_size]; + DWORD size = GetModuleFileNameW(NULL, buffer, buffer_size); if (size != 0) { - Filename tmp = Filename::from_os_specific(string(buffer, size)); + Filename tmp = Filename::from_os_specific_w(wstring(buffer, size)); tmp.make_true_case(); _binary_name = tmp; } diff --git a/dtool/src/dtoolutil/filename.cxx b/dtool/src/dtoolutil/filename.cxx index e85fa13d1a..53b291e8d8 100644 --- a/dtool/src/dtoolutil/filename.cxx +++ b/dtool/src/dtoolutil/filename.cxx @@ -522,11 +522,11 @@ get_home_directory() { if (home_directory.empty()) { #ifdef WIN32 - char buffer[MAX_PATH]; + wchar_t buffer[MAX_PATH]; // On Windows, fall back to the "My Documents" folder. - if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_PERSONAL, true)) { - Filename dirname = from_os_specific(buffer); + if (SHGetSpecialFolderPathW(NULL, buffer, CSIDL_PERSONAL, true)) { + Filename dirname = from_os_specific_w(buffer); if (dirname.is_directory()) { if (dirname.make_canonical()) { home_directory = dirname; @@ -572,9 +572,9 @@ get_temp_directory() { #ifdef WIN32 static const size_t buffer_size = 4096; - char buffer[buffer_size]; - if (GetTempPath(buffer_size, buffer) != 0) { - Filename dirname = from_os_specific(buffer); + wchar_t buffer[buffer_size]; + if (GetTempPathW(buffer_size, buffer) != 0) { + Filename dirname = from_os_specific_w(buffer); if (dirname.is_directory()) { if (dirname.make_canonical()) { temp_directory = dirname; @@ -620,10 +620,10 @@ get_user_appdata_directory() { Filename user_appdata_directory; #ifdef WIN32 - char buffer[MAX_PATH]; + wchar_t buffer[MAX_PATH]; - if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_LOCAL_APPDATA, true)) { - Filename dirname = from_os_specific(buffer); + if (SHGetSpecialFolderPathW(NULL, buffer, CSIDL_LOCAL_APPDATA, true)) { + Filename dirname = from_os_specific_w(buffer); if (dirname.is_directory()) { if (dirname.make_canonical()) { user_appdata_directory = dirname; @@ -669,10 +669,10 @@ get_common_appdata_directory() { Filename common_appdata_directory; #ifdef WIN32 - char buffer[MAX_PATH]; + wchar_t buffer[MAX_PATH]; - if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_COMMON_APPDATA, true)) { - Filename dirname = from_os_specific(buffer); + if (SHGetSpecialFolderPathW(NULL, buffer, CSIDL_COMMON_APPDATA, true)) { + Filename dirname = from_os_specific_w(buffer); if (dirname.is_directory()) { if (dirname.make_canonical()) { common_appdata_directory = dirname; @@ -1126,14 +1126,14 @@ make_true_case() { } #ifdef WIN32 - string os_specific = to_os_specific(); + wstring os_specific = to_os_specific_w(); // First, we have to convert it to its short name, then back to its // long name--that seems to be the trick to force Windows to throw // away the case we give it and get the actual file case. - char short_name[MAX_PATH + 1]; - DWORD l = GetShortPathName(os_specific.c_str(), short_name, MAX_PATH + 1); + wchar_t short_name[MAX_PATH + 1]; + DWORD l = GetShortPathNameW(os_specific.c_str(), short_name, MAX_PATH + 1); if (l == 0) { // Couldn't query the path name for some reason. Probably the // file didn't exist. @@ -1144,8 +1144,8 @@ make_true_case() { // according to the Windows docs, MAX_PATH will always be enough. assert(l < MAX_PATH + 1); - char long_name[MAX_PATH + 1]; - l = GetLongPathName(short_name, long_name, MAX_PATH + 1); + wchar_t long_name[MAX_PATH + 1]; + l = GetLongPathNameW(short_name, long_name, MAX_PATH + 1); if (l == 0) { // Couldn't query the path name for some reason. Probably the // file didn't exist. @@ -1153,15 +1153,15 @@ make_true_case() { } assert(l < MAX_PATH + 1); - Filename true_case = Filename::from_os_specific(long_name); + Filename true_case = Filename::from_os_specific_w(long_name); // Now sanity-check the true-case filename. If it's not the same as // the source file, except for case, reject it. - string orig_filename = get_fullpath(); - string new_filename = true_case.get_fullpath(); + wstring orig_filename = get_fullpath_w(); + wstring new_filename = true_case.get_fullpath_w(); bool match = (orig_filename.length() == new_filename.length()); for (size_t i = 0; i < orig_filename.length() && match; ++i) { - match = (tolower(orig_filename[i]) == tolower(new_filename[i])); + match = (TextEncoder::unicode_tolower(orig_filename[i]) == TextEncoder::unicode_tolower(new_filename[i])); } if (!match) { // Something went wrong. Keep the original filename, assume it @@ -1287,21 +1287,24 @@ to_os_short_name() const { assert(!get_pattern()); #ifdef WIN32 - string os_specific = to_os_specific(); + wstring os_specific = to_os_specific_w(); - char short_name[MAX_PATH + 1]; - DWORD l = GetShortPathName(os_specific.c_str(), short_name, MAX_PATH + 1); + wchar_t short_name[MAX_PATH + 1]; + DWORD l = GetShortPathNameW(os_specific.c_str(), short_name, MAX_PATH + 1); if (l == 0) { // Couldn't query the path name for some reason. Probably the // file didn't exist. - return os_specific; + return to_os_specific(); } // According to the Windows docs, l will return a value greater than // the specified length if the short_name length wasn't enough--but also // according to the Windows docs, MAX_PATH will always be enough. assert(l < MAX_PATH + 1); - return string(short_name); + TextEncoder encoder; + encoder.set_encoding(get_filesystem_encoding()); + encoder.set_wtext(short_name); + return encoder.get_text(); #else // WIN32 return to_os_specific(); @@ -1321,18 +1324,21 @@ to_os_long_name() const { assert(!get_pattern()); #ifdef WIN32 - string os_specific = to_os_specific(); + wstring os_specific = to_os_specific_w(); - char long_name[MAX_PATH + 1]; - DWORD l = GetLongPathName(os_specific.c_str(), long_name, MAX_PATH + 1); + wchar_t long_name[MAX_PATH + 1]; + DWORD l = GetLongPathNameW(os_specific.c_str(), long_name, MAX_PATH + 1); if (l == 0) { // Couldn't query the path name for some reason. Probably the // file didn't exist. - return os_specific; + return to_os_specific(); } assert(l < MAX_PATH + 1); - return string(long_name); + TextEncoder encoder; + encoder.set_encoding(get_filesystem_encoding()); + encoder.set_wtext(long_name); + return encoder.get_text(); #else // WIN32 return to_os_specific(); @@ -1349,17 +1355,19 @@ to_os_long_name() const { //////////////////////////////////////////////////////////////////// bool Filename:: exists() const { - string os_specific = get_filename_index(0).to_os_specific(); - #ifdef WIN32_VC + wstring os_specific = get_filename_index(0).to_os_specific_w(); + bool exists = false; - DWORD results = GetFileAttributes(os_specific.c_str()); + DWORD results = GetFileAttributesW(os_specific.c_str()); if (results != -1) { exists = true; } #else // WIN32_VC + string os_specific = get_filename_index(0).to_os_specific(); + struct stat this_buf; bool exists = false; @@ -1380,17 +1388,19 @@ exists() const { //////////////////////////////////////////////////////////////////// bool Filename:: is_regular_file() const { - string os_specific = get_filename_index(0).to_os_specific(); - #ifdef WIN32_VC + wstring os_specific = get_filename_index(0).to_os_specific_w(); + bool isreg = false; - DWORD results = GetFileAttributes(os_specific.c_str()); + DWORD results = GetFileAttributesW(os_specific.c_str()); if (results != -1) { isreg = ((results & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0); } #else // WIN32_VC + string os_specific = get_filename_index(0).to_os_specific(); + struct stat this_buf; bool isreg = false; @@ -1410,16 +1420,18 @@ is_regular_file() const { //////////////////////////////////////////////////////////////////// bool Filename:: is_directory() const { - string os_specific = get_filename_index(0).to_os_specific(); - #ifdef WIN32_VC + wstring os_specific = get_filename_index(0).to_os_specific_w(); + bool isdir = false; - DWORD results = GetFileAttributes(os_specific.c_str()); + DWORD results = GetFileAttributesW(os_specific.c_str()); if (results != -1) { isdir = (results & FILE_ATTRIBUTE_DIRECTORY) != 0; } #else // WIN32_VC + string os_specific = get_filename_index(0).to_os_specific(); + struct stat this_buf; bool isdir = false; @@ -1475,24 +1487,27 @@ int Filename:: compare_timestamps(const Filename &other, bool this_missing_is_old, bool other_missing_is_old) const { - string os_specific = get_filename_index(0).to_os_specific(); - string other_os_specific = other.get_filename_index(0).to_os_specific(); - #ifdef WIN32_VC + wstring os_specific = get_filename_index(0).to_os_specific_w(); + wstring other_os_specific = other.get_filename_index(0).to_os_specific_w(); + struct _stat this_buf; bool this_exists = false; - if (_stat(os_specific.c_str(), &this_buf) == 0) { + if (_wstat(os_specific.c_str(), &this_buf) == 0) { this_exists = true; } struct _stat other_buf; bool other_exists = false; - if (_stat(other_os_specific.c_str(), &other_buf) == 0) { + if (_wstat(other_os_specific.c_str(), &other_buf) == 0) { other_exists = true; } #else // WIN32_VC + string os_specific = get_filename_index(0).to_os_specific(); + string other_os_specific = other.get_filename_index(0).to_os_specific(); + struct stat this_buf; bool this_exists = false; @@ -1554,15 +1569,17 @@ compare_timestamps(const Filename &other, //////////////////////////////////////////////////////////////////// time_t Filename:: get_timestamp() const { - string os_specific = get_filename_index(0).to_os_specific(); - #ifdef WIN32_VC + wstring os_specific = get_filename_index(0).to_os_specific_w(); + struct _stat this_buf; - if (_stat(os_specific.c_str(), &this_buf) == 0) { + if (_wstat(os_specific.c_str(), &this_buf) == 0) { return this_buf.st_mtime; } #else // WIN32_VC + string os_specific = get_filename_index(0).to_os_specific(); + struct stat this_buf; if (stat(os_specific.c_str(), &this_buf) == 0) { @@ -1583,15 +1600,17 @@ get_timestamp() const { //////////////////////////////////////////////////////////////////// time_t Filename:: get_access_timestamp() const { - string os_specific = get_filename_index(0).to_os_specific(); - #ifdef WIN32_VC + wstring os_specific = get_filename_index(0).to_os_specific_w(); + struct _stat this_buf; - if (_stat(os_specific.c_str(), &this_buf) == 0) { + if (_wstat(os_specific.c_str(), &this_buf) == 0) { return this_buf.st_atime; } #else // WIN32_VC + string os_specific = get_filename_index(0).to_os_specific(); + struct stat this_buf; if (stat(os_specific.c_str(), &this_buf) == 0) { @@ -1610,15 +1629,17 @@ get_access_timestamp() const { //////////////////////////////////////////////////////////////////// off_t Filename:: get_file_size() const { - string os_specific = get_filename_index(0).to_os_specific(); - #ifdef WIN32_VC + wstring os_specific = get_filename_index(0).to_os_specific_w(); + struct _stat this_buf; - if (_stat(os_specific.c_str(), &this_buf) == 0) { + if (_wstat(os_specific.c_str(), &this_buf) == 0) { return this_buf.st_size; } #else // WIN32_VC + string os_specific = get_filename_index(0).to_os_specific(); + struct stat this_buf; if (stat(os_specific.c_str(), &this_buf) == 0) { @@ -1801,15 +1822,15 @@ scan_directory(vector_string &contents) const { // list of files in a directory. size_t orig_size = contents.size(); - string match; + wstring match; if (empty()) { - match = "*.*"; + match = L"*.*"; } else { - match = to_os_specific() + "\\*.*"; + match = to_os_specific_w() + L"\\*.*"; } - WIN32_FIND_DATA find_data; + WIN32_FIND_DATAW find_data; - HANDLE handle = FindFirstFile(match.c_str(), &find_data); + HANDLE handle = FindFirstFileW(match.c_str(), &find_data); if (handle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_NO_MORE_FILES) { // No matching files is not an error. @@ -1818,13 +1839,16 @@ scan_directory(vector_string &contents) const { return false; } + TextEncoder encoder; + encoder.set_encoding(get_filesystem_encoding()); do { thread_consider_yield(); - string filename = find_data.cFileName; - if (filename != "." && filename != "..") { - contents.push_back(filename); + wstring filename = find_data.cFileName; + if (filename != L"." && filename != L"..") { + encoder.set_wtext(filename); + contents.push_back(encoder.get_text()); } - } while (FindNextFile(handle, &find_data)); + } while (FindNextFileW(handle, &find_data)); bool scan_ok = (GetLastError() == ERROR_NO_MORE_FILES); FindClose(handle); @@ -1980,9 +2004,15 @@ open_read(ifstream &stream) const { } #endif - string os_specific = to_os_specific(); stream.clear(); +#ifdef WIN32_VC + wstring os_specific = to_os_specific_w(); stream.open(os_specific.c_str(), open_mode); +#else + string os_specific = to_os_specific(); + stream.open(os_specific.c_str(), open_mode); +#endif // WIN32_VC + return (!stream.fail()); } @@ -2031,12 +2061,17 @@ open_write(ofstream &stream, bool truncate) const { #endif stream.clear(); +#ifdef WIN32_VC + wstring os_specific = to_os_specific_w(); + stream.open(os_specific.c_str(), open_mode); +#else string os_specific = to_os_specific(); #ifdef HAVE_OPEN_MASK stream.open(os_specific.c_str(), open_mode, 0666); #else stream.open(os_specific.c_str(), open_mode); #endif +#endif // WIN32_VC return (!stream.fail()); } @@ -2068,12 +2103,17 @@ open_append(ofstream &stream) const { #endif stream.clear(); +#ifdef WIN32_VC + wstring os_specific = to_os_specific_w(); + stream.open(os_specific.c_str(), open_mode); +#else string os_specific = to_os_specific(); #ifdef HAVE_OPEN_MASK stream.open(os_specific.c_str(), open_mode, 0666); #else stream.open(os_specific.c_str(), open_mode); #endif +#endif // WIN32_VC return (!stream.fail()); } @@ -2115,12 +2155,17 @@ open_read_write(fstream &stream, bool truncate) const { #endif stream.clear(); +#ifdef WIN32_VC + wstring os_specific = to_os_specific_w(); + stream.open(os_specific.c_str(), open_mode); +#else string os_specific = to_os_specific(); #ifdef HAVE_OPEN_MASK stream.open(os_specific.c_str(), open_mode, 0666); #else stream.open(os_specific.c_str(), open_mode); #endif +#endif // WIN32_VC return (!stream.fail()); } @@ -2153,12 +2198,17 @@ open_read_append(fstream &stream) const { #endif stream.clear(); +#ifdef WIN32_VC + wstring os_specific = to_os_specific_w(); + stream.open(os_specific.c_str(), open_mode); +#else string os_specific = to_os_specific(); #ifdef HAVE_OPEN_MASK stream.open(os_specific.c_str(), open_mode, 0666); #else stream.open(os_specific.c_str(), open_mode); #endif +#endif // WIN32_VC return (!stream.fail()); } @@ -2397,10 +2447,10 @@ touch() const { // In Windows, we have to use the Windows API to do this reliably. // First, guarantee the file exists (and also get its handle). - string os_specific = to_os_specific(); + wstring os_specific = to_os_specific_w(); HANDLE fhandle; - fhandle = CreateFile(os_specific.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + fhandle = CreateFileW(os_specific.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, + NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (fhandle == INVALID_HANDLE_VALUE) { return false; } @@ -2473,8 +2523,13 @@ touch() const { //////////////////////////////////////////////////////////////////// bool Filename:: chdir() const { +#ifdef WIN32_VC + wstring os_specific = to_os_specific_w(); + return (_wchdir(os_specific.c_str()) >= 0); +#else string os_specific = to_os_specific(); return (::chdir(os_specific.c_str()) >= 0); +#endif // WIN32_VC } //////////////////////////////////////////////////////////////////// @@ -2488,12 +2543,15 @@ chdir() const { bool Filename:: unlink() const { assert(!get_pattern()); - string os_specific = to_os_specific(); -#ifdef _WIN32 +#ifdef WIN32_VC // Windows can't delete a file if it's read-only. Weird. - chmod(os_specific.c_str(), 0644); -#endif + wstring os_specific = to_os_specific_w(); + _wchmod(os_specific.c_str(), 0644); + return (_wunlink(os_specific.c_str()) == 0); +#else + string os_specific = to_os_specific(); return (::unlink(os_specific.c_str()) == 0); +#endif // WIN32_VC } @@ -2514,6 +2572,46 @@ rename_to(const Filename &other) const { return true; } +#ifdef WIN32_VC + wstring os_specific = to_os_specific_w(); + wstring other_os_specific = other.to_os_specific_w(); + + if (_wrename(os_specific.c_str(), + other_os_specific.c_str()) == 0) { + // Successfully renamed. + return true; + } + + // The above might fail if we have tried to move a file to a + // different filesystem. In this case, copy the file into the same + // directory first, and then rename it. + string dirname = other.get_dirname(); + if (dirname.empty()) { + dirname = "."; + } + Filename temp = Filename::temporary(dirname, ""); + temp.set_binary(); + if (!Filename::binary_filename(*this).copy_to(temp)) { + return false; + } + + wstring temp_os_specific = temp.to_os_specific_w(); + if (_wrename(temp_os_specific.c_str(), + other_os_specific.c_str()) == 0) { + // Successfully renamed. + unlink(); + return true; + } + + // Try unlinking the target first. + other.unlink(); + if (_wrename(temp_os_specific.c_str(), + other_os_specific.c_str()) == 0) { + // Successfully renamed. + unlink(); + return true; + } +#else // WIN32_VC string os_specific = to_os_specific(); string other_os_specific = other.to_os_specific(); @@ -2552,6 +2650,7 @@ rename_to(const Filename &other) const { unlink(); return true; } +#endif // WIN32_VC // Failed. temp.unlink(); @@ -2644,23 +2743,25 @@ make_dir() const { size_t slash = dirname.find('/'); while (slash != string::npos) { Filename component(dirname.substr(0, slash)); - string os_specific = component.to_os_specific(); -#ifndef WIN32_VC - ::mkdir(os_specific.c_str(), 0777); +#ifdef WIN32_VC + wstring os_specific = component.to_os_specific_w(); + _wmkdir(os_specific.c_str()); #else - ::mkdir(os_specific.c_str()); -#endif + string os_specific = component.to_os_specific(); + ::mkdir(os_specific.c_str(), 0777); +#endif // WIN32_VC slash = dirname.find('/', slash + 1); } // Now make the last one, and check the return value. Filename component(dirname); - string os_specific = component.to_os_specific(); -#ifndef WIN32_VC - int result = ::mkdir(os_specific.c_str(), 0777); +#ifdef WIN32_VC + wstring os_specific = component.to_os_specific_w(); + int result = _wmkdir(os_specific.c_str()); #else - int result = ::mkdir(os_specific.c_str()); -#endif + string os_specific = component.to_os_specific(); + int resutl = ::mkdir(os_specific.c_str(), 0777); +#endif // WIN32_VC return (result == 0); } @@ -2676,12 +2777,13 @@ make_dir() const { //////////////////////////////////////////////////////////////////// bool Filename:: mkdir() const { - string os_specific = to_os_specific(); -#ifndef WIN32_VC - int result = ::mkdir(os_specific.c_str(), 0777); +#ifdef WIN32_VC + wstring os_specific = to_os_specific_w(); + int result = _wmkdir(os_specific.c_str()); #else - int result = ::mkdir(os_specific.c_str()); -#endif + string os_specific = to_os_specific(); + int result = ::mkdir(os_specific.c_str(), 0777); +#endif // WIN32_VC return (result == 0); } @@ -2694,18 +2796,21 @@ mkdir() const { //////////////////////////////////////////////////////////////////// bool Filename:: rmdir() const { - string os_specific = to_os_specific(); +#ifdef WIN32_VC + wstring os_specific = to_os_specific_w(); - int result = ::rmdir(os_specific.c_str()); - -#ifdef WIN32 + int result = _wrmdir(os_specific.c_str()); if (result != 0) { // Windows may require the directory to be writable before we can // remove it. - chmod(os_specific.c_str(), 0777); - result = ::rmdir(os_specific.c_str()); + _wchmod(os_specific.c_str(), 0777); + result = _wrmdir(os_specific.c_str()); } -#endif + +#else // WIN32_VC + string os_specific = to_os_specific(); + int result = ::rmdir(os_specific.c_str()); +#endif // WIN32_VC return (result == 0); } @@ -2792,18 +2897,18 @@ atomic_compare_and_exchange_contents(string &orig_contents, const string &old_contents, const string &new_contents) const { #ifdef WIN32_VC - string os_specific = to_os_specific(); - HANDLE hfile = CreateFile(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); + wstring os_specific = to_os_specific_w(); + HANDLE hfile = CreateFileW(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); while (hfile == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); if (error == ERROR_SHARING_VIOLATION) { // If the file is locked by another process, yield and try again. Sleep(0); - hfile = CreateFile(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); + hfile = CreateFileW(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); } else { cerr << "Couldn't open file: " << os_specific << ", error " << error << "\n"; @@ -2929,18 +3034,18 @@ atomic_compare_and_exchange_contents(string &orig_contents, bool Filename:: atomic_read_contents(string &contents) const { #ifdef WIN32_VC - string os_specific = to_os_specific(); - HANDLE hfile = CreateFile(os_specific.c_str(), GENERIC_READ, - FILE_SHARE_READ, NULL, OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); + wstring os_specific = to_os_specific_w(); + HANDLE hfile = CreateFileW(os_specific.c_str(), GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); while (hfile == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); if (error == ERROR_SHARING_VIOLATION) { // If the file is locked by another process, yield and try again. Sleep(0); - hfile = CreateFile(os_specific.c_str(), GENERIC_READ, - FILE_SHARE_READ, NULL, OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); + hfile = CreateFileW(os_specific.c_str(), GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); } else { cerr << "Couldn't open file: " << os_specific << ", error " << error << "\n"; @@ -3210,9 +3315,23 @@ r_make_canonical(const Filename &cwd) { return false; } +#ifdef WIN32_VC + // First, try to cd to the filename directly. + wstring os_specific = to_os_specific_w(); + if (_wchdir(os_specific.c_str()) >= 0) { + // That worked, save the full path string. + (*this) = ExecutionEnvironment::get_cwd(); + + // And restore the current working directory. + wstring osdir = cwd.to_os_specific_w(); + if (_wchdir(osdir.c_str()) < 0) { + cerr << "Error! Cannot change back to " << osdir << "\n"; + } + return true; + } +#else // WIN32_VC // First, try to cd to the filename directly. string os_specific = to_os_specific(); - if (::chdir(os_specific.c_str()) >= 0) { // That worked, save the full path string. (*this) = ExecutionEnvironment::get_cwd(); @@ -3224,6 +3343,7 @@ r_make_canonical(const Filename &cwd) { } return true; } +#endif // WIN32_VC // That didn't work; maybe it's not a directory. Recursively go to // the directory above. diff --git a/dtool/src/dtoolutil/pandaFileStreamBuf.cxx b/dtool/src/dtoolutil/pandaFileStreamBuf.cxx index 5f662b84d0..19b8e33760 100644 --- a/dtool/src/dtoolutil/pandaFileStreamBuf.cxx +++ b/dtool/src/dtoolutil/pandaFileStreamBuf.cxx @@ -14,6 +14,8 @@ #include "pandaFileStreamBuf.h" #include "memoryHook.h" +#include "filename.h" +#include "textEncoder.h" #ifdef USE_PANDAFILESTREAM @@ -133,8 +135,12 @@ open(const char *filename, ios::openmode mode) { flags |= FILE_FLAG_OVERLAPPED; #endif - _handle = CreateFile(_filename.c_str(), access, share_mode, - NULL, creation_disposition, flags, NULL); + TextEncoder encoder; + encoder.set_encoding(Filename::get_filesystem_encoding()); + encoder.set_text(_filename); + wstring wfilename = encoder.get_wtext(); + _handle = CreateFileW(wfilename.c_str(), access, share_mode, + NULL, creation_disposition, flags, NULL); if (_handle != INVALID_HANDLE_VALUE) { // The file was successfully opened and locked. _is_open = true;