summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorcah <cah@ableton.com>2020-03-22 20:50:11 +0100
committerCarl Hetherington <cth@carlh.net>2020-03-28 19:47:28 +0100
commitc3663fa9de96b99eac21f3aa736bd6f2e9bbc3c0 (patch)
tree80ccf0f7314aeb594ac99f5a677d228abbc8b9db /src/lib
parent148f17cc145ff4f6b8a6ff0af71998a5c87cd968 (diff)
Various windows hacks.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/cross_windows.cc64
1 files changed, 61 insertions, 3 deletions
diff --git a/src/lib/cross_windows.cc b/src/lib/cross_windows.cc
index 5d2cf5372..b97e2bbd0 100644
--- a/src/lib/cross_windows.cc
+++ b/src/lib/cross_windows.cc
@@ -24,6 +24,7 @@
#include "dcpomatic_log.h"
#include "config.h"
#include "exceptions.h"
+#include "dcpomatic_assert.h"
#include <dcp/raw_convert.h>
#include <glib.h>
extern "C" {
@@ -412,11 +413,69 @@ get_device_number (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data)
return device_number.DeviceNumber;
}
+/** Take a volume path (with a trailing \) and add any disk numbers related to that volume
+ * to @ref disks.
+ */
+static void
+add_volume_disk_number (wchar_t* volume, vector<int>& disks)
+{
+ /* Strip trailing \ */
+ size_t const len = wcslen (volume);
+ DCPOMATIC_ASSERT (len > 0);
+ volume[len - 1] = L'\0';
+
+ HANDLE handle = CreateFileW (
+ volume, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
+ OPEN_EXISTING, 0, 0
+ );
+
+ DCPOMATIC_ASSERT (handle != INVALID_HANDLE_VALUE);
+
+ VOLUME_DISK_EXTENTS extents;
+ DWORD size;
+ BOOL r = DeviceIoControl (handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 0, 0, &extents, sizeof(extents), &size, 0);
+ CloseHandle (handle);
+ if (!r) {
+ return;
+ }
+ DCPOMATIC_ASSERT (extents.NumberOfDiskExtents == 1);
+ return disks.push_back (extents.Extents[0].DiskNumber);
+}
+
+/* Return a list of disk numbers that contain volumes; i.e. a list of disk numbers that should
+ * not be offered as targets to write to as they are "mounted" (whatever that means on Windows).
+ */
+vector<int>
+disk_numbers_with_volumes ()
+{
+ vector<int> disks;
+
+ wchar_t volume_name[512];
+ HANDLE volume = FindFirstVolumeW (volume_name, sizeof(volume_name) / sizeof(wchar_t));
+ if (volume == INVALID_HANDLE_VALUE) {
+ return disks;
+ }
+
+ add_volume_disk_number (volume_name, disks);
+ while (true) {
+ if (!FindNextVolumeW(volume, volume_name, sizeof(volume_name) / sizeof(wchar_t))) {
+ break;
+ }
+ add_volume_disk_number (volume_name, disks);
+ }
+ FindVolumeClose (volume);
+
+ return disks;
+}
+
vector<Drive>
get_drives ()
{
vector<Drive> drives;
+ vector<int> disks_to_ignore = disk_numbers_with_volumes ();
+
/* Get a `device information set' containing information about all disks */
HDEVINFO device_info = SetupDiGetClassDevsA (&GUID_DEVICE_INTERFACE_DISK, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (device_info == INVALID_HANDLE_VALUE) {
@@ -454,6 +513,7 @@ get_drives ()
if (device == INVALID_HANDLE_VALUE) {
LOG_DIST_NC("Could not open PHYSICALDRIVE");
+ continue;
}
DISK_GEOMETRY geom;
@@ -463,11 +523,9 @@ get_drives ()
&geom, sizeof(geom), &returned, 0
);
- if (r) {
+ if (r && find(disks_to_ignore.begin(), disks_to_ignore.end(), *device_number) == disks_to_ignore.end()) {
uint64_t const disk_size = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;
drives.push_back (Drive(physical_drive, disk_size, false, friendly_name, optional<string>()));
- } else {
- LOG_DIST("Error %1", GetLastError());
}
CloseHandle (device);