应先用getdrivetype提取盘符并判断驱动器类型:若返回drive_cdrom则大概率是光盘,drive_ramdisk表示内存虚拟盘,drive_remote可能为网络或虚拟光驱挂载,而drive_fixed和drive_removable需结合后续验证;对无盘符路径须先归一化。

如何用 GetDriveType 快速排除非光盘/虚拟盘路径
直接调用 GetDriveType 是最轻量的前置判断。它不依赖文件是否存在,只看路径所在驱动器类型。对 "D:\file.txt" 这类带盘符路径,提取盘符后传入即可;对相对路径或 UNC 路径需先用 GetFullPathName 或 PathGetDriveNumber 归一化。
返回值为 DRIVE_CDROM 表示物理光盘驱动器(含 DVD/BD),DRIVE_RAMDISK 表示内存虚拟盘(如 ImDisk、RAMDisk 创建的盘),DRIVE_REMOTE 则可能是网络映射盘或某些虚拟光驱(如 Daemon Tools 挂载的 ISO)——但后者不可靠,需进一步验证。
-
DRIVE_FIXED和DRIVE_REMOVABLE通常不是目标,但 USB 光驱可能被识别为DRIVE_REMOVABLE,不能直接排除 - 若路径无盘符(如
"..\data.bin"),必须先解析出实际所在驱动器,否则GetDriveType返回DRIVE_NO_ROOT_DIR - Windows 10 1903+ 对 WSL2 挂载的 Linux 文件系统返回
DRIVE_UNKNOWN,需单独处理
用 GetVolumeInformation 检查卷标和文件系统特征
GetVolumeInformation 能读取卷序列号、最大组件长度、文件系统名称等。只读光盘介质(如 ISO9660、UDF)通常返回空或固定卷标(如 "CDROM"),且 lpFileSystemNameBuffer 为 "CDFS"、"UDF" 或 "ISO9660";虚拟光驱挂载的 ISO 多数也呈现相同文件系统名。
关键点在于:即使驱动器类型是 DRIVE_CDROM,也可能插入空白盘或可擦写 DVD+RW,此时文件系统可能是 "UDF" 但卷实际可写。因此需结合 dwFlags 输出参数中的 FILE_READ_ONLY_VOLUME 标志位——该标志由底层存储驱动设置,比检查文件权限更可靠。
- 调用前确保路径指向根目录或有效卷(如
"D:\"),传入文件路径会失败并返回ERROR_INVALID_PARAMETER -
FILE_SUPPORTS_HARD_LINKS在光盘上几乎总为 false,可作为辅助线索,但不具决定性 - 某些虚拟光驱(如 WinCDEmu)在挂载时未设置
FILE_READ_ONLY_VOLUME,需 fallback 到后续权限检查
通过 GetFileAttributes 和 SetFileAttributes 验证实际写权限
最终确认是否只读,必须尝试“最小写操作”:用 GetFileAttributes 获取目标路径属性,若含 FILE_ATTRIBUTE_READONLY,再尝试用 SetFileAttributes 清除该标志。失败且 GetLastError() 返回 ERROR_ACCESS_DENIED 或 ERROR_WRITE_PROTECT,基本可断定介质只读。
注意:此方法检测的是“当前路径是否可写”,而非“整个卷只读”。例如光盘根目录只读,但某子目录下存在可写临时文件(极少见),或 NTFS 卷上某文件被 ACL 显式拒绝写入——这些情况应与介质级只读区分。
- 务必对路径本身(而非父目录)调用
GetFileAttributes,避免误判目录继承权限 - 若路径不存在,
GetFileAttributes返回INVALID_FILE_ATTRIBUTES,需先用CreateFilewithGENERIC_READ打开验证存在性 - 对虚拟磁盘驱动器(如 VHD/VHDX 挂载为物理盘),即使格式为 NTFS,若挂载时指定只读(
diskpart attach vdisk readonly),此处也会失败
为什么不能只依赖 GetVolumeInformation 的 FILE_READ_ONLY_VOLUME
这个标志看似完美,但实际覆盖不全:Windows 对大多数真实光驱和主流虚拟光驱(MagicISO、PowerISO)能正确设置,可一旦遇到老旧驱动、第三方过滤驱动或某些企业级虚拟化平台(如 VMware 虚拟光驱在特定 guest OS 下),该标志可能始终为 0,导致误判为可写。
更麻烦的是,部分 RAM 磁盘工具(如 SoftPerfect RAM Disk)允许运行时切换读写模式,但 FILE_READ_ONLY_VOLUME 在挂载后即固化,不再更新。此时仅靠该标志会给出过期结论。
- 真正可靠的判断链是:
GetDriveType→GetVolumeInformation(含FILE_READ_ONLY_VOLUME)→SetFileAttributes实测 - 对性能敏感场景(如批量扫描),可先缓存已知光盘驱动器的卷信息,避免重复调用
SetFileAttributes - 没有单一 API 能 100% 区分“只读介质”和“只读挂载”,必须组合行为验证
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











