X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Fcross_windows.cc;h=0549615787214dbd0ce4ef18b31ced6b5df78aca;hp=2072ffd4c63ab47ed8cb3fb81e4bccf790eeb64d;hb=b17c280ea98f89fe141e9ef2a8372316c44e0155;hpb=a1d3a73736ff2a171ab1160dedf4faea40454bea diff --git a/src/lib/cross_windows.cc b/src/lib/cross_windows.cc index 2072ffd4c..054961578 100644 --- a/src/lib/cross_windows.cc +++ b/src/lib/cross_windows.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,9 @@ */ + +#define UNICODE 1 + #include "cross.h" #include "compose.hpp" #include "log.h" @@ -25,13 +28,14 @@ #include "config.h" #include "exceptions.h" #include "dcpomatic_assert.h" +#include "util.h" +#include #include #include extern "C" { #include } #include -#include #include #include #include @@ -41,28 +45,33 @@ extern "C" { #include #undef DATADIR #include +#include #include +#include #include #include #include #include "i18n.h" + using std::pair; -using std::list; -using std::ifstream; -using std::string; -using std::wstring; -using std::make_pair; -using std::vector; using std::cerr; using std::cout; -using std::runtime_error; +using std::ifstream; +using std::list; +using std::make_pair; using std::map; -using boost::shared_ptr; +using std::runtime_error; +using std::shared_ptr; +using std::string; +using std::vector; +using std::wstring; using boost::optional; -static std::vector > locked_volumes; + +static std::vector> locked_volumes; + /** @param s Number of seconds to sleep for */ void @@ -71,12 +80,14 @@ dcpomatic_sleep_seconds (int s) Sleep (s * 1000); } + void dcpomatic_sleep_milliseconds (int ms) { Sleep (ms); } + /** @return A string of CPU information (model name etc.) */ string cpu_info () @@ -111,6 +122,7 @@ cpu_info () return info; } + void run_ffprobe (boost::filesystem::path content, boost::filesystem::path out) { @@ -151,7 +163,7 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out) return; } - FILE* o = fopen_boost (out, "w"); + dcp::File o(out, "w"); if (!o) { LOG_ERROR_NC (N_("ffprobe call failed (could not create output file)")); return; @@ -165,10 +177,10 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out) if (!ReadFile(child_stderr_read, buffer, sizeof(buffer), &read, 0) || read == 0) { break; } - fwrite (buffer, read, 1, o); + o.write(buffer, read, 1); } - fclose (o); + o.close(); WaitForSingleObject (process_info.hProcess, INFINITE); CloseHandle (process_info.hProcess); @@ -176,11 +188,11 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out) CloseHandle (child_stderr_read); } -list > + +list> mount_info () { - list > m; - return m; + return {}; } @@ -199,16 +211,9 @@ resources_path () boost::filesystem::path -xsd_path () +libdcp_resources_path () { - return directory_containing_executable().parent_path() / "xsd"; -} - - -boost::filesystem::path -tags_path () -{ - return directory_containing_executable().parent_path() / "tags"; + return resources_path (); } @@ -228,24 +233,6 @@ disk_writer_path () #endif -/* 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. -*/ -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 ()); -} - -int -dcpomatic_fseek (FILE* stream, int64_t offset, int whence) -{ - return _fseeki64 (stream, offset, whence); -} - void Waker::nudge () { @@ -253,11 +240,13 @@ Waker::nudge () SetThreadExecutionState (ES_SYSTEM_REQUIRED); } + Waker::Waker () { } + Waker::~Waker () { @@ -267,7 +256,7 @@ Waker::~Waker () void start_tool (string executable) { - boost::filesystem::path batch = directory_containing_executable() / executable; + auto batch = directory_containing_executable() / executable; STARTUPINFO startup_info; ZeroMemory (&startup_info, sizeof (startup_info)); @@ -302,55 +291,63 @@ thread_id () return (uint64_t) GetCurrentThreadId (); } + 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; } + int avio_open_boost (AVIOContext** s, boost::filesystem::path file, int flags) { return avio_open (s, wchar_to_utf8(file.c_str()).c_str(), flags); } + void maybe_open_console () { if (Config::instance()->win32_console ()) { AllocConsole(); - HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); + auto handle_out = GetStdHandle(STD_OUTPUT_HANDLE); int hCrt = _open_osfhandle((intptr_t) handle_out, _O_TEXT); - FILE* hf_out = _fdopen(hCrt, "w"); + auto hf_out = _fdopen(hCrt, "w"); setvbuf(hf_out, NULL, _IONBF, 1); *stdout = *hf_out; - HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE); + auto handle_in = GetStdHandle(STD_INPUT_HANDLE); hCrt = _open_osfhandle((intptr_t) handle_in, _O_TEXT); - FILE* hf_in = _fdopen(hCrt, "r"); + auto hf_in = _fdopen(hCrt, "r"); setvbuf(hf_in, NULL, _IONBF, 128); *stdin = *hf_in; } } + boost::filesystem::path home_directory () { - return boost::filesystem::path(getenv("HOMEDRIVE")) / boost::filesystem::path(getenv("HOMEPATH")); -} + PWSTR wide_path; + auto result = SHGetKnownFolderPath(FOLDERID_Documents, 0, nullptr, &wide_path); -string -command_and_read (string) -{ - return ""; + if (result != S_OK) { + CoTaskMemFree(wide_path); + return boost::filesystem::path("c:\\"); + } + + auto path = wchar_to_utf8(wide_path); + CoTaskMemFree(wide_path); + return path; } + /** @return true if this process is a 32-bit one running on a 64-bit-capable OS */ bool running_32_on_64 () @@ -360,6 +357,7 @@ running_32_on_64 () return p; } + static optional get_friendly_name (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) { @@ -374,10 +372,12 @@ get_friendly_name (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) return wchar_to_utf8 (buffer); } + static const GUID GUID_DEVICE_INTERFACE_DISK = { 0x53F56307L, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } }; + static optional get_device_number (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) { @@ -386,7 +386,7 @@ get_device_number (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) SP_DEVICE_INTERFACE_DATA device_interface_data; device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - BOOL r = SetupDiEnumDeviceInterfaces (device_info, device_info_data, &GUID_DEVICE_INTERFACE_DISK, 0, &device_interface_data); + auto r = SetupDiEnumDeviceInterfaces (device_info, device_info_data, &GUID_DEVICE_INTERFACE_DISK, 0, &device_interface_data); if (!r) { LOG_DISK("SetupDiEnumDeviceInterfaces failed (%1)", GetLastError()); return optional(); @@ -414,7 +414,7 @@ get_device_number (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) /* Open it. We would not be allowed GENERIC_READ access here but specifying 0 for dwDesiredAccess allows us to query some metadata. */ - HANDLE device = CreateFileW ( + auto device = CreateFileW ( device_detail_data->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 @@ -437,13 +437,15 @@ get_device_number (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) CloseHandle (device); if (!r) { - return optional(); + return {}; } return device_number.DeviceNumber; } -typedef map > MountPoints; + +typedef map> MountPoints; + /** Take a volume path (with a trailing \) and add any disk numbers related to that volume * to @ref disks. @@ -470,7 +472,7 @@ add_volume_mount_points (wchar_t* volume, MountPoints& mount_points) DCPOMATIC_ASSERT (len > 0); volume[len - 1] = L'\0'; - HANDLE handle = CreateFileW ( + auto handle = CreateFileW ( volume, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 @@ -490,13 +492,14 @@ add_volume_mount_points (wchar_t* volume, MountPoints& mount_points) mount_points[extents.Extents[0].DiskNumber] = mp; } + MountPoints find_mount_points () { MountPoints mount_points; wchar_t volume_name[512]; - HANDLE volume = FindFirstVolumeW (volume_name, sizeof(volume_name) / sizeof(wchar_t)); + auto volume = FindFirstVolumeW (volume_name, sizeof(volume_name) / sizeof(wchar_t)); if (volume == INVALID_HANDLE_VALUE) { return MountPoints(); } @@ -513,15 +516,16 @@ find_mount_points () return mount_points; } + vector Drive::get () { vector drives; - MountPoints mount_points = find_mount_points (); + auto mount_points = find_mount_points (); /* Get a `device information set' containing information about all disks */ - HDEVINFO device_info = SetupDiGetClassDevsA (&GUID_DEVICE_INTERFACE_DISK, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + auto device_info = SetupDiGetClassDevsA (&GUID_DEVICE_INTERFACE_DISK, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (device_info == INVALID_HANDLE_VALUE) { LOG_DISK_NC ("SetupDiClassDevsA failed"); return drives; @@ -541,8 +545,8 @@ Drive::get () } ++i; - optional const friendly_name = get_friendly_name (device_info, &device_info_data); - optional device_number = get_device_number (device_info, &device_info_data); + auto const friendly_name = get_friendly_name (device_info, &device_info_data); + auto device_number = get_device_number (device_info, &device_info_data); if (!device_number) { continue; } @@ -569,8 +573,8 @@ Drive::get () LOG_DISK("Having a look through %1 locked volumes", locked_volumes.size()); bool locked = false; - for (vector >::const_iterator i = locked_volumes.begin(); i != locked_volumes.end(); ++i) { - if (i->second == physical_drive) { + for (auto const& i: locked_volumes) { + if (i.second == physical_drive) { locked = true; } } @@ -595,8 +599,6 @@ Drive::unmount () DCPOMATIC_ASSERT (_mount_points.size() == 1); string const device_name = String::compose ("\\\\.\\%1", _mount_points.front()); string const truncated = device_name.substr (0, device_name.length() - 1); - //LOG_DISK("Actually opening %1", _device); - //HANDLE device = CreateFileA (_device.c_str(), (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); LOG_DISK("Actually opening %1", truncated); HANDLE device = CreateFileA (truncated.c_str(), (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if (device == INVALID_HANDLE_VALUE) { @@ -618,20 +620,40 @@ 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; } + void disk_write_finished () { - for (vector >::const_iterator i = locked_volumes.begin(); i != locked_volumes.end(); ++i) { - CloseHandle (i->first); + for (auto const& i: locked_volumes) { + CloseHandle (i.first); } } +string +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); +} +