X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fcross_windows.cc;h=49eec3c28ff01b19a18c427f16521eea869a67e8;hb=f0d7300770806592e7fe7a494e66a96ab48463cf;hp=04ee26271b7a5c80595c1ce87e38b87a2de5fad1;hpb=3339d3bce70afe9ae2ca10e9fcfc4b54b748fbf4;p=dcpomatic.git diff --git a/src/lib/cross_windows.cc b/src/lib/cross_windows.cc index 04ee26271..49eec3c28 100644 --- a/src/lib/cross_windows.cc +++ b/src/lib/cross_windows.cc @@ -19,6 +19,8 @@ */ +#define UNICODE 1 + #include "cross.h" #include "compose.hpp" #include "log.h" @@ -26,6 +28,7 @@ #include "config.h" #include "exceptions.h" #include "dcpomatic_assert.h" +#include "util.h" #include #include extern "C" { @@ -234,6 +237,44 @@ disk_writer_path () #endif +/** Windows can't "by default" cope with paths longer than 260 characters, so if you pass such a path to + * any boost::filesystem method it will fail. There is a "fix" for this, which is to prepend + * the string \\?\ to the path. This will make it work, so long as: + * - the path is absolute. + * - the path only uses backslashes. + * - individual path components are "short enough" (probably less than 255 characters) + * + * See https://www.boost.org/doc/libs/1_57_0/libs/filesystem/doc/reference.html under + * "Warning: Long paths on Windows" for some details. + * + * Our fopen_boost uses this method to get this fix, but any other calls to boost::filesystem + * will not unless this method is explicitly called to pre-process the pathname. + */ +boost::filesystem::path +fix_long_path (boost::filesystem::path long_path) +{ + using namespace boost::filesystem; + + if (boost::algorithm::starts_with(long_path.string(), "\\\\")) { + /* This could mean it starts with \\ (i.e. a SMB path) or \\?\ (a long path) + * or a variety of other things... anyway, we'll leave it alone. + */ + return long_path; + } + + /* We have to make the path canonical but we can't call canonical() on the long path + * as it will fail. So we'll sort of do it ourselves (possibly badly). + */ + path fixed = "\\\\?\\"; + if (long_path.is_absolute()) { + fixed += long_path.make_preferred(); + } else { + fixed += boost::filesystem::current_path() / long_path.make_preferred(); + } + return fixed; +} + + /* Apparently there is no way to create an ofstream using a UTF-8 filename under Windows. We are hence reduced to using fopen with this wrapper. @@ -242,8 +283,8 @@ FILE * fopen_boost (boost::filesystem::path p, string t) { wstring w (t.begin(), t.end()); - /* c_str() here should give a UTF-16 string */ - return _wfopen (p.c_str(), w.c_str ()); + /* c_str() on fixed here should give a UTF-16 string */ + return _wfopen (fix_long_path(p).c_str(), w.c_str()); } @@ -317,10 +358,9 @@ static string wchar_to_utf8 (wchar_t const * s) { int const length = (wcslen(s) + 1) * 2; - char* utf8 = new char[length]; - WideCharToMultiByte (CP_UTF8, 0, s, -1, utf8, length, 0, 0); - string u (utf8); - delete[] utf8; + std::vector utf8(length); + WideCharToMultiByte (CP_UTF8, 0, s, -1, utf8.data(), length, 0, 0); + string u (utf8.data()); return u; } @@ -356,7 +396,7 @@ maybe_open_console () boost::filesystem::path home_directory () { - return boost::filesystem::path(getenv("HOMEDRIVE")) / boost::filesystem::path(getenv("HOMEPATH")); + return boost::filesystem::path(getenv("userprofile")); } @@ -634,11 +674,14 @@ Drive::unmount () boost::filesystem::path -config_path () +config_path (optional version) { boost::filesystem::path p; p /= g_get_user_config_dir (); p /= "dcpomatic2"; + if (version) { + p /= *version; + } return p; } @@ -658,3 +701,13 @@ dcpomatic::get_process_id () return dcp::raw_convert(GetCurrentProcessId()); } + +bool +show_in_file_manager (boost::filesystem::path, boost::filesystem::path select) +{ + std::wstringstream args; + args << "/select," << select; + auto const r = ShellExecute (0, L"open", L"explorer.exe", args.str().c_str(), 0, SW_SHOWDEFAULT); + return (reinterpret_cast(r) <= 32); +} +