mirror of
https://github.com/mpv-player/mpv
synced 2024-12-22 14:52:43 +00:00
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>
This commit is contained in:
parent
217008be4a
commit
17d0609d1e
@ -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;
|
||||
|
||||
if (GetVolumePathNameW(path, volume, MAX_PATH))
|
||||
remote = GetDriveTypeW(volume) == DRIVE_REMOTE;
|
||||
// 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");
|
||||
|
||||
talloc_free(path);
|
||||
return remote;
|
||||
if (!pNtQueryVolumeInformationFile)
|
||||
return false;
|
||||
|
||||
struct priv *priv = stream->priv;
|
||||
HANDLE h = (HANDLE)_get_osfhandle(priv->fd);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
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;
|
||||
|
||||
return info.DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM ||
|
||||
(info.Characteristics & FILE_REMOTE_DEVICE);
|
||||
}
|
||||
#else
|
||||
static bool check_stream_network(stream_t *stream)
|
||||
|
Loading…
Reference in New Issue
Block a user