【问题标题】:Obtain a list of partitions on Windows获取 Windows 上的分区列表
【发布时间】:2011-05-01 19:54:49
【问题描述】:

目标

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

潜在客户

Windows 似乎围绕着卷的概念展开,它似乎与磁盘不太相似,并且只发生在已经挂载的文件系统中。

我所拥有的有希望的潜在客户包括:

但是,这些都以卷或偏移量结尾,而不是我所追求的 /dev/sda1 分区特定样式句柄。

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

问题

我想要:

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

更新0

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

【问题讨论】:

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


【解决方案1】:

如您所述,您可以使用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。
  • 如何将分区映射到路径?
  • @Matt Joiner - 此信息可通过GetVolumePathName 获得,基于文件名输入。仍在寻找枚举驱动器的方法。
  • @Matt Joiner - 您可以使用FindFirstVolume/FindNextVolume 枚举卷。鉴于此,您可以如上所述枚举分区,并隐含地为您提供所有磁盘。请参阅此处的示例 - msdn.microsoft.com/en-us/library/cc542456(v=VS.85).aspx
  • @Steve:我认为您可能仍然会错过没有关联卷的 PhysicalDisk 对象(因为分区表不存在、为空或仅包含类型不受支持的分区)跨度>
【解决方案2】:

如果您能想象从安全的用户空间和Windows API (win32) 转移到使用 NTTDK 编写设备驱动程序,您可以尝试IoReadPartitionTableEx 或其他一些low level disk 函数。

【讨论】:

  • 看起来与 win32 提供的非常相似,但它首先缺乏查找可用磁盘的能力。还有一个注意事项:IoReadPartitionTableEx 只能由磁盘驱动程序使用。
  • 我对此表示赞同,因为它在问题的(晦涩)区域中是有用的信息,即使不是 @Matt 的完整答案。
【解决方案3】:

坦率地说,可靠地获取所有已挂载/未挂载的磁盘分区的最佳方法是自己解析 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)。这些只是我想到的案例,不要束缚我。

【讨论】:

    【解决方案4】:

    我认为您在早期阶段有点错误。例如,您似乎认为“挂载”在 Windows 中的工作方式与在 Unix 中的工作方式相同。有点不一样。

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

    函数QueryDosDevice 将为您获取驱动器号或卷名的Windows 设备名称。设备名称看起来像“\Device\HarddiskVolume1”,但您不能将其传递给CreateFile

    微软有example code 枚举所有分区。

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

    【讨论】:

    • 您链接到的示例代码已经在我的潜在客户列表中,并且似乎仅适用于已安装的卷。此外,它并不特定于分区。我需要访问未安装的东西。
    • 嗯,这些概念并没有真正翻译。 Windows 没有“挂载”概念,因此未挂载分区的概念也没有任何意义。您是在谈论磁盘上的扇区集合,这些扇区是 Windows 没有驱动程序的文件系统的一部分? Windows 中没有代表这些部门的对象,AFAIK。
    • 注意:卷和分区(在 Windows 中)不是一回事。磁盘有分区,分区组成卷。您可以将来自不同磁盘的 2 个分区组成同一个卷。
    • @chacham15:虽然“volume == partition”确实存在例外情况,例如 RAID 条带集,但我认为这些例外情况在这里不适用。
    • @BenVoigt:正确。由于我们谈论的是尚未识别的磁盘位,因此谈论跨越多个磁盘的卷是没有意义的。这将要求 Windows 了解构成该卷的分区。
    猜你喜欢
    • 2022-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 2023-01-24
    相关资源
    最近更新 更多