获取 Windows 上的分区列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4042212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Obtain a list of partitions on Windows
提问by Matt Joiner
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.
我正在将一个文件系统移植到 Windows,并且正在为安装程序可执行文件编写一个更像 Windows 的界面。这个过程的一部分是让用户定位一个分区并选择一个驱动器号。最终分区的选择已经导致一些我可以使用打开CreateFile()
,open()
,fopen()
或类似的。
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.
Windows 似乎围绕着卷的概念,这似乎与磁盘不太相似,并且只出现在已安装的文件系统中。
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.
然而,这些都以卷或其偏移量结束,而不是/dev/sda1
我所追求的特定于分区的句柄。
This questionis after a very similar thing, I considered a bounty until I observed the OP is after physical disk names, not partitions. This answercontains a method to brute force partition names, I'd like to avoid that (or see documentation containing bounds for the possible paths).
这个问题是在一个非常相似的事情之后,我认为是一个赏金,直到我观察到 OP 在物理磁盘名称之后,而不是分区之后。这个答案包含一种强力分区名称的方法,我想避免这种情况(或查看包含可能路径边界的文档)。
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.
- Windows 中卸载分区的正确术语和文档。
- 一种可靠地检索所有可用分区的有效且记录在案的方法。
- 最接近 Linux 中可用的分区文件抽象,其中所有 IO 都绑定到打开的分区的磁盘的适当区域。
Update0
更新0
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.
虽然主要目标仍然是打开原始分区,但似乎解决方案可能涉及首先获取每个磁盘驱动器的句柄,然后依次使用它来获取每个分区。需要如何枚举所有磁盘驱动器(即使是那些尚未安装卷的磁盘驱动器)。
采纳答案by Steve Townsend
As you noted, you can use IOCTL_DISK_GET_DRIVE_LAYOUT_EXto get a list of partitions.
正如您所指出的,您可以使用IOCTL_DISK_GET_DRIVE_LAYOUT_EX来获取分区列表。
There's a good overview of the related concepts here. I wonder if the missing link for you is
此处对相关概念进行了很好的概述。我想知道你缺少的链接是否是
Detecting the Type of Disk
There is no specific function to programmatically detect the type of disk a particular file or directory is located on. There is an indirect method.
First, call
GetVolumePathName
. Then, callCreateFile
to open the volume using the path. Next, useIOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
with the volume handle to obtain the disk number and use the disk number to construct the disk path, such as "\?\PhysicalDriveX". Finally, useIOCTL_DISK_GET_DRIVE_LAYOUT_EX
to obtain the partition list, and check the PartitionType for each entry in the partition list.
检测磁盘类型
没有特定的函数可以以编程方式检测特定文件或目录所在的磁盘类型。有一种间接的方法。
首先,调用
GetVolumePathName
。然后,调用CreateFile
使用路径打开卷。接下来,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
与卷句柄一起使用获取磁盘编号,并使用磁盘编号构造磁盘路径,例如“\?\PhysicalDriveX”。最后,使用IOCTL_DISK_GET_DRIVE_LAYOUT_EX
获取分区列表,并检查分区列表中每个条目的 PartitionType。
The full list of disk management control codesmay 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.
磁盘管理控制代码的完整列表可能有更多有用的。老实说,我不确定 Unix 分区名称如何映射到 Windows,也许它只是不直接。
回答by Prof. Falken contract breached
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 IoReadPartitionTableExor some other low level diskfunction.
如果您可以想象从用户空间和Windows API(win32) 的安全港转移到使用 NTTDK 编写设备驱动程序,您可以尝试IoReadPartitionTableEx或其他一些低级磁盘函数。
回答by chacham15
To be blunt, the best way to reliably get all mounted/unmounted disk partitions is to parse the mbr/gpt yourself.
坦率地说,可靠地获取所有已挂载/未挂载的磁盘分区的最佳方法是自己解析 mbr/gpt。
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).
IOCTL_DISK_GET_DRIVE_LAYOUT_EX
是您无需手动执行即可获得的最接近的解决方案。这样做的问题是它依赖于 Windows,它可能会错误地解析 MBR,因为天知道是什么原因。我目前的工作理论是,如果 Windows 是通过 EFI 安装的,但通过 MBR 启动,你会看到这类问题。Windows 设法摆脱了这一点,因为大多数分区管理器将重要的分区信息与 GPT 一起复制到 MBR。但这意味着您不会获得分区 UUID(仅存储在 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 usuallybe 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.
旁注:卷 ID通常采用\\.\Volume{PARTITION_UUID}
. 这不成立的情况:如果驱动器是用 MBR 而不是 GPT 分区的(MBR 没有分区 UUID,因此 Windows 组成一个),如果你有一个 raid 驱动器,或者如果你有一个由以下分区组成的卷多个磁盘(与raid 有点相同)。这些只是我想到的案例,不要拘泥于它们。
回答by MSalters
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.
我认为你在早期阶段有点错误。例如,您似乎认为“挂载”在 Windows 中的工作方式与在 Unix 中的工作方式相同。它有点不同。
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 namelike \\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\
. You can use this volume name in calls to CreateFile()
etc. I'm not sure if fopen()
likes them, though.
让我们从最熟悉的一端开始。路径如C:\
使用驱动器号。现在,这些基本上只是一组符号链接(在 Windows 上,它们更正式地称为“连接”)。所有用户都有一个基本集,每个用户都可以添加自己的。即使有一个卷没有驱动器盘符,仍然会有一个卷名状\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\
。您可以在对CreateFile()
等的调用中使用此卷名称。不过,我不确定是否fopen()
喜欢它们。
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 to CreateFile
该函数QueryDosDevice
将为您提供驱动器号或卷名的 Windows 设备名称。设备名称看起来像“\Device\HarddiskVolume1”,但您不能将其传递给CreateFile
Microsoft has example codeto enumerate all partitions.
Microsoft 有示例代码来枚举所有分区。
On Windows, like on Linux, you can open the partition itself as if it were a file. This is quite well documented under CreateFile
.
在 Windows 上,就像在 Linux 上一样,您可以像打开文件一样打开分区本身。这在CreateFile
.