获取Windows上的分区列表

时间:2010-10-28 11:01:18

标签: c++ c windows winapi disk-partitioning

目标

我正在将文件系统移植到Windows,并且正在为mounter可执行文件编写更像Windows的界面。此过程的一部分是让用户找到分区并选择驱动器号。最终,分区的选择必须导致我可以使用CreateFile()open()fopen()或类似内容打开。

信息

Windows似乎围绕卷的概念展开,这些概念似乎与磁盘不太相似,而且仅适用于已安装的文件系统。

有前途的潜在客户包括:

然而,这些都以卷或其偏移结束,而不是我所追求的/dev/sda1特定于分区的句柄。

This question是一个非常类似的事情,我认为是赏金,直到我发现OP是在物理磁盘名称之后,而不是分区。 This answer包含一个强制分区名称的方法,我想避免这种情况(或者查看包含可能路径边界的文档)。

问题

我想:

  • 更正Windows中未安装分区的术语和文档。
  • 可靠且有文档记录的方法,可靠地检索所有可用分区。
  • 最接近Linux中可用的分区文件抽象,其中所有IO都绑定到打开分区的磁盘的适当区域。

Update0

虽然主要目标仍然是打开原始分区,但似乎解决方案可能涉及首先获取每个磁盘驱动器的句柄,然后依次使用它来获取每个分区。如何枚举所有磁盘驱动器(即使那些已经没有安装卷的磁盘驱动器)也是必需的。

4 个答案:

答案 0 :(得分:4)

如您所述,您可以使用IOCTL_DISK_GET_DRIVE_LAYOUT_EX获取分区列表。

对相关概念here有一个很好的概述。我想知道你缺少的链接是否

  

检测磁盘类型

     

没有具体的功能   以编程方式检测其类型   磁盘特定的文件或目录   位于。有间接的   方法

     

首先,致电GetVolumePathName。然后,   致电CreateFile打开音量   使用路径。接下来,使用   IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS   用卷句柄来获取   磁盘编号并使用磁盘编号   构造磁盘路径,例如   “\?\ PhysicalDriveX”。最后,使用   IOCTL_DISK_GET_DRIVE_LAYOUT_EX来   获取分区列表,然后检查   中的每个条目的PartitionType   分区列表。

disk management control codes的完整列表可能包含更多有用的内容。说实话,我不确定Unix分区名称是如何映射到Windows的,也许它不是直接的。

答案 1 :(得分:3)

如果您可以想象从用户空间的安全港和Windows API(win32)转移到使用NTTDK编码设备驱动程序,您可以尝试使用IoReadPartitionTableEx或其他low level disk功能。< / p>

答案 2 :(得分:1)

说实话,可靠地获取所有已安装/未安装的磁盘分区的最佳方法是自己解析mbr / gpt。

首先要清除一些内容:磁盘包含分区和分区组合以创建卷。因此,您可以拥有一个卷,该卷由两个不同磁盘的两个分区组成。

IOCTL_DISK_GET_DRIVE_LAYOUT_EX是您手动完成的最接近的解决方案。这个问题是它依赖于可以错误地解析MBR的窗口,因为上帝知道是什么原因。我目前的工作理论是,如果Windows是通过EFI安装的,但是通过MBR启动,你会看到这种问题。 Windows设法逃脱了这一点,因为大多数分区管理器将重要的分区信息与GPT一起复制到MBR。但这意味着您不会获得分区UUID(仅存储在GPT中)等重要信息。

所有其他解决方案都涉及获取与分区信息完全不同的卷信息。

备注:卷ID 通常的格式为\\.\Volume{PARTITION_UUID}。这种情况不成立的情况:如果驱动器使用MBR进行分区而不是GPT(MBR没有分区UUID,因此Windows会启动一个),如果你有一个raid驱动器,或者你有一个包含来自分区的卷多个磁盘(有点像raid一样)。这些只是我想到的情况,不要诱使我。

答案 3 :(得分:0)

我认为你在早期阶段有点误会。例如,您似乎认为“挂载”在Windows中可以像在Unix中一样工作。它有点不同。

让我们从最熟悉的一端开始吧。 C:\之类的路径使用驱动器号。这些现在基本上只是一组符号链接(在Windows上,它们更正式地称为“联结”)。所有用户都有一个基础集,每个用户都可以添加自己的基础集。即使卷没有驱动器号,仍然会有{em>卷名,如\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\。您可以在调用CreateFile()等时使用此卷名。但我不确定fopen()是否喜欢它们。

函数QueryDosDevice将为您提供驱动器号或卷名的Windows设备名称。设备名称类似于“\ Device \ HarddiskVolume1”,但您无法将其传递给CreateFile

Microsoft example code枚举所有分区。

在Windows上,就像在Linux上一样,您可以打开分区本身,就好像它是一个文件一样。这在CreateFile下有很好的记录。