summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authorJames Ross-Gowan <rossymiles@gmail.com>2014-04-09 18:14:18 +1000
committerwm4 <wm4@nowhere>2014-04-09 20:41:51 +0200
commit17d0609d1e8c36d70b5994e779a364f6df429937 (patch)
tree78928bcbbef2ce9e660d8f2a1f4df4d0ce77c994 /stream
parent217008be4a821d91f2651f9506321327d8f551bf (diff)
downloadmpv-17d0609d1e8c36d70b5994e779a364f6df429937.tar.bz2
mpv-17d0609d1e8c36d70b5994e779a364f6df429937.tar.xz
stream_file: Check the handle for network streams
Use NtQueryVolumeInformationFile instead of GetDriveType for detecting remote filesystems on Windows. This has the advantage of working directly on the file handle instead of needing a path and it works unmodified in Cygwin where the previous code wouldn't understand Cygwin paths or symlinks. There is some risk in using NtQueryVolumeInformationFile, since it's an internal function and its behaviour could change at any time or it could be removed in a future version of Windows, however it's documented[1] in the WDK and it's used successfully by Cygwin, so it should be fine. If it's removed, the code should fail gracefully by treating all files as local. [1]: http://msdn.microsoft.com/en-us/library/windows/hardware/ff567070.aspx Signed-off-by: wm4 <wm4@nowhere>
Diffstat (limited to 'stream')
-rw-r--r--stream/stream_file.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/stream/stream_file.c b/stream/stream_file.c
index c62249bf76..c714f5739d 100644
--- a/stream/stream_file.c
+++ b/stream/stream_file.c
@@ -43,8 +43,14 @@
#include <sys/vfs.h>
#endif
-#ifdef __MINGW32__
+#ifdef _WIN32
#include <windows.h>
+#include <winternl.h>
+#include <io.h>
+
+#ifndef FILE_REMOTE_DEVICE
+#define FILE_REMOTE_DEVICE (0x10)
+#endif
#endif
struct priv {
@@ -158,18 +164,37 @@ static bool check_stream_network(stream_t *stream)
return false;
}
-#elif defined(__MINGW32__)
+#elif defined(_WIN32)
static bool check_stream_network(stream_t *stream)
{
- wchar_t volume[MAX_PATH];
- wchar_t *path = mp_from_utf8(NULL, stream->path);
- bool remote = false;
+ NTSTATUS (NTAPI *pNtQueryVolumeInformationFile)(HANDLE,
+ PIO_STATUS_BLOCK, PVOID, ULONG, FS_INFORMATION_CLASS) = NULL;
+
+ // NtQueryVolumeInformationFile is an internal Windows function. It has
+ // been present since Windows XP, however this code should fail gracefully
+ // if it's removed from a future version of Windows.
+ HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
+ pNtQueryVolumeInformationFile = (NTSTATUS (NTAPI*)(HANDLE,
+ PIO_STATUS_BLOCK, PVOID, ULONG, FS_INFORMATION_CLASS))
+ GetProcAddress(ntdll, "NtQueryVolumeInformationFile");
+
+ if (!pNtQueryVolumeInformationFile)
+ return false;
+
+ struct priv *priv = stream->priv;
+ HANDLE h = (HANDLE)_get_osfhandle(priv->fd);
+ if (h == INVALID_HANDLE_VALUE)
+ return false;
- if (GetVolumePathNameW(path, volume, MAX_PATH))
- remote = GetDriveTypeW(volume) == DRIVE_REMOTE;
+ FILE_FS_DEVICE_INFORMATION info = { 0 };
+ IO_STATUS_BLOCK io;
+ NTSTATUS status = pNtQueryVolumeInformationFile(h, &io, &info,
+ sizeof(info), FileFsDeviceInformation);
+ if (!NT_SUCCESS(status))
+ return false;
- talloc_free(path);
- return remote;
+ return info.DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM ||
+ (info.Characteristics & FILE_REMOTE_DEVICE);
}
#else
static bool check_stream_network(stream_t *stream)