获取 Windows 上的分区列表
目标
我正在将文件系统移植到 Windows,并为挂载器可执行文件编写一个更像 Windows 的界面。此过程的一部分是让用户找到分区并选择驱动器号。最终,分区的选择必须导致我可以使用 CreateFile()、open()、fopen() 或类似方法打开某些内容。
Windows 似乎围绕卷的概念展开
,卷似乎与磁盘不太相似,并且仅出现在已安装的文件系统中。
我拥有的有前途的线索包括:
然而,这些都以卷或其偏移量结束,而不是我所追求的 /dev/sda1 分区特定样式句柄。
这个问题是在一件非常类似的事情之后发生的,我考虑过赏金,直到我观察到OP位于物理磁盘名称之后,而不是分区名称之后。 这个答案包含一种暴力破解分区名称的方法,我会希望避免这种情况(或参阅包含可能路径边界的文档)。
问题
我想要的
- : Windows 中未安装分区的正确术语和文档。
- 一种有效且记录在案的方法,可以可靠地检索所有可用分区。
- 最接近 Linux 中可用的分区文件抽象,其中所有 IO 都绑定到打开的分区的磁盘适当区域。
Update0
虽然主要目标仍然是打开原始分区,但解决方案似乎可能涉及首先获取每个磁盘驱动器的句柄,然后依次使用它来获取每个分区。需要如何枚举所有磁盘驱动器(即使是那些尚未安装卷的磁盘驱动器)。
Goal
I'm porting a filesystem to Windows, and am writing a more Windows-like interface for the mounter executable. Part of this process is letting the user locate a partition and pick a drive letter. Ultimately the choice of partition has to result in something I can open using CreateFile()
, open()
, fopen()
or similar.
Leads
Windows seems to revolve around the concept of volumes, which don't seem quite analogous to disks, and only occur for already mounted filesystems.
Promising leads I've had include:
However these all end in volumes or offsets thereof, not the /dev/sda1
partition-specific-style handle I'm after.
This question is after a very similar thing, I considered a bounty until I observed the OP is after physical disk names, not partitions. This answer contains a method to brute force partition names, I'd like to avoid that (or see documentation containing bounds for the possible paths).
Question
I'd like:
- Correct terminology and documentation for unmounted partitions in Windows.
- An effective and documented method to reliably retrieve all available partitions.
- The closest fit to the partition file abstraction as available in Linux, wherein all IO is bound to the appropriate area of the disk for the partition opened.
Update0
While the main goal is still opening raw partitions, it appears the solution may involve first acquiring a handle to each disk drive, and then using that in turn to acquire each partition. How to enumerate all the disk drives (even those without mounted volumes on them already) is required.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
正如您所指出的,您可以使用 IOCTL_DISK_GET_DRIVE_LAYOUT_EX 获取分区列表。
此处对相关概念进行了很好的概述。我想知道您缺少的链接是否是
磁盘管理控制代码的完整列表 可能还有更多有用的内容。老实说,我不确定 Unix 分区名称如何映射到 Windows,也许只是不直接映射。
As you noted, you can use IOCTL_DISK_GET_DRIVE_LAYOUT_EX to get a list of partitions.
There's a good overview of the related concepts here. I wonder if the missing link for you is
The full list of disk management control codes may have more that would be useful. To be honest I'm not sure how the Unix partition name maps onto Windows, maybe it just doesn't directly.
如果您可以想象从用户空间和 Windows API (win32) 的安全港转移到对设备进行编码NTTDK 驱动程序,您可以尝试 IoReadPartitionTableEx 或其他一些低级磁盘功能。
If you can imagine moving from safe haven of userspace and the Windows API (win32) to coding a device driver with NTTDK, you could try IoReadPartitionTableEx or some other low level disk function.
说白了,可靠地获取所有已挂载/未挂载的磁盘分区的最佳方法是自己解析 mbr/gpt。
首先要澄清一些事情:磁盘包含分区,分区组合起来创建卷。因此,您可以拥有一个由来自两个不同磁盘的两个分区组成的卷。
IOCTL_DISK_GET_DRIVE_LAYOUT_EX
是您无需手动操作即可获得的最接近的解决方案。问题是它依赖于 Windows,Windows 可能会错误地解析 MBR,天知道是什么原因。我目前的工作理论是,如果 Windows 是通过 EFI 安装但通过 MBR 启动的,您会看到此类问题。 Windows 设法摆脱了这一点,因为大多数分区管理器将重要的分区信息与 GPT 一起复制到 MBR。但这意味着您将无法获得分区 UUID(仅存储在 GPT 中)等重要信息。所有其他解决方案都涉及获取与分区信息完全不同的卷信息。
附注:卷 ID 通常采用
\\.\Volume{PARTITION_UUID}
形式。这种情况不成立:如果驱动器使用 MBR 而不是 GPT 进行分区(MBR 没有分区 UUID,因此 Windows 制作了一个),如果您有一个 raid 驱动器,或者如果您有一个由以下分区组成的卷多个磁盘(与 raid 类似)。这些只是我想到的情况,不要强迫我。To be blunt, the best way to reliably get all mounted/unmounted disk partitions is to parse the mbr/gpt yourself.
First to clear a few things up: Disks contain partitions and partitions combine to create volumes. Therefore, you can have one volume which consists of two partitions from two different disks.
IOCTL_DISK_GET_DRIVE_LAYOUT_EX
is the closest solution you're going to get without doing it manually. The problem with this is that it relies on windows which can incorrectly parse the MBR for god knows what reason. My current working theory is that if Windows was installed via EFI but is being booted via MBR, youll see this sort of issue. Windows manages to get away with this because most partition managers copy the important partition information to the MBR alongside the GPT. But this means that you wont get important information like the partition UUID (which is only stored in the GPT).All of the other solutions involve getting the Volume information which is completely different from the partition information.
Side Note: a Volume id will usually be of the form
\\.\Volume{PARTITION_UUID}
. Cases where this would not hold: if the drive is partitioned with MBR and not GPT (MBR does not have a partition UUID, therefore windows makes one up), if you have a raid drive, or if you have a volume consisting of partitions from multiple disks (kinda the same thing as raid). Those are just the cases that come to my mind, dont hold me to them.我认为你在早期阶段犯了一些错误。例如,您似乎认为“安装”在 Windows 中的工作方式就像在 Unix 中一样。有点不同。
让我们从最熟悉的结尾开始。
C:\
等路径使用驱动器号。如今,这些本质上只是一组符号链接(在 Windows 上,它们更正式地称为“连接点”)。所有用户都有一个基本集,每个用户都可以添加自己的基本集。即使卷没有驱动器号,仍然会有一个卷名称,例如\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\
。您可以在调用CreateFile()
等时使用此卷名称。不过,我不确定fopen()
是否喜欢它们。函数
QueryDosDevice
将为您提供 Windows驱动器号或卷名称的设备名称。设备名称类似于“\Device\HarddiskVolume1”,但您无法将其传递给CreateFile
Microsoft 有 示例代码枚举所有分区。
在 Windows 上,就像在 Linux 上一样,您可以像打开文件一样打开分区本身。
CreateFile
下对此进行了详细记录。I think you're slightly mistaken in an earlier phase. For instance, you seem to assume that "mounting" works in Windows like it works in Unix. It's a bit different.
Let's start at the most familiar end. Paths like
C:\
use drive letters. Those are essentially just a set of symbolic links nowadays (On Windows, they're more formally known as "junctions"). There's a base set for all users, and each user can add their own. Even if there is no drive letter for a volume, there will still be a volume name like\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\
. You can use this volume name in calls toCreateFile()
etc. I'm not sure iffopen()
likes them, though.The function
QueryDosDevice
will get you the Windows device name for a drive letter or a volume name. A device name looks like "\Device\HarddiskVolume1", but you can't pass it toCreateFile
Microsoft has example code to enumerate all partitions.
On Windows, like on Linux, you can open the partition itself as if it were a file. This is quite well documented under
CreateFile
.