C++ 枚举所有分区并测试它们是否为NTFS
我正在使用:C++ 枚举所有分区并测试它们是否为NTFS,c++,windows,winapi,ntfs,ntfs-mft,C++,Windows,Winapi,Ntfs,Ntfs Mft,我正在使用: DWORD d = GetLogicalDrives(); for (int i = 0; i < 26; i++) { if ((1 << i) & d) // drive letter 'A' + i present on computer { wstring s = std::wstring(L"\\\\.\\") + wchar_t('A' + i) + L":"; PARTITION_INFORM
DWORD d = GetLogicalDrives();
for (int i = 0; i < 26; i++)
{
if ((1 << i) & d) // drive letter 'A' + i present on computer
{
wstring s = std::wstring(L"\\\\.\\") + wchar_t('A' + i) + L":";
PARTITION_INFORMATION diskInfo;
DWORD dwResult;
HANDLE dev = CreateFile(LPWSTR(s.c_str()), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &diskInfo, sizeof(diskInfo), &dwResult, NULL);
CloseHandle(dev);
if (diskInfo.PartitionType == PARTITION_IFS)
{
...
}
}
}
DWORD d=GetLogicalDrives();
对于(int i=0;i<26;i++)
{
如果((1)如@RemyLebeau所说,您没有检查每个调用的返回值
PARTITION\u ENTRY\u UNUSED
通常意味着DeviceIoControl()
调用失败。这取决于用户的权限。您应该检查用户的访问权限,查看其是否具有文件读取数据
权限(包含在通用读取
中)在卷C:
上。在我的测试环境中,如果您无法使用GENERIC\u READ
打开卷C:
,CreateFile()
返回无效的句柄值
,然后设备控制()
也会失败
编辑:
我建议使用GetVolumeInformation()
,例如:
wchar_t fs[MAX_PATH + 1] = { 0 };
GetVolumeInformationW(L"C:\\", NULL, 0, NULL, NULL, NULL, fs, MAX_PATH + 1);
您将在fs
缓冲区中看到类型信息。多亏@RemyLebeau的评论,我做了进一步的调查:
HANDLE dev = CreateFile(..., GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if (dev == INVALID_HANDLE_VALUE)
{
DWORD err = GetLastError(); // then MessageBox
}
else
{
BOOL ret = DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &diskInfo, sizeof(diskInfo), &dwResult, NULL);
if (ret == FALSE)
{
DWORD err = GetLastError(); // then MessageBox
}
CloseHandle(dev);
}
在发生故障的计算机上(使用Windows 10的计算机)。我发现CreateFile
成功,但DeviceIoControl
失败,原因是GetLastError
为1
,即错误\u无效\u函数
(请参阅)
结论(我引用雷米的评论):
这意味着传递给DeviceIoControl()的设备不支持IOCTL\u DISK\u GET\u PARTITION\u INFO
然后我尝试使用IOCTL\u DISK\u GET\u PARTITION\u INFO\u EX
:
PARTITION_INFORMATION_EX diskInfo;
BOOL ret = DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &diskInfo, sizeof(diskInfo), &lpBytesReturned, NULL);
然后它工作了。我可以看到diskInfo.PartitionStyle
是PARTITION\u STYLE\u GPT
(=1),这就是IOCTL\u DISK\u GET\u PARTITION\u INFO
失败的原因。我再次引用雷米的评论:
GPT分区驱动器不支持IOCTL_DISK_GET_PARTITION_INFO
结论如下:
- 使用
IOCTL\u DISK\u GET\u PARTITION\u INFO\u EX
而不是IOCTL\u DISK\u GET\u PARTITION\u INFO
- 如果
diskInfo.PartitionStyle
为0(PARTITION\u STYLE\u MBR),则可以测试diskInfo.MBR.PartitionType
- 如果
diskInfo.PartitionStyle
为1(PARTITION\u STYLE\u GPT),则可以测试diskInfo.GPT.PartitionType,请参见此处:。即使在GPT的情况下提及NTFS的GUIDEBD0A0A2-B9E5-4433-87C0-68B6B72699C7
,此GUID实际上与文件系统无关(请参见下面的注释)
- 使用
GetVolumeInformation()
可能更容易,只需比较结果是否为“NTFS”
字符串,如
- 在我的特殊情况下,在尝试使用
DeviceIoControl(hVol、FSCTL_ENUM_USN_DATA,…)进行索引之前,我最初希望测试卷是否为NTFS
因为我认为这样的MFT查询将局限于NTFS卷。事实上,一个更简单的解决方案是不测试它是否是NTFS,只需执行FSCTL_ENUM_USN_DATA
。最糟糕的情况是,FSCTL_ENUM_USN_DATA
失败,根据文档显示ERROR\u INVALID_函数
错误齿形:
“错误\u无效\u函数指定卷上的文件系统不支持此控制代码。”
您没有进行任何错误处理。在评估diskInfo.PartitionType
之前,您没有检查CreateFile()
和DeviceIoControl()
是否确实成功。查找NTFS分区的另一种方法是使用GetLogicalDrive/Strings()
和GetVolumeInformation()
,则lpFileSystemNameBuffer
参数将返回您查询的每个驱动器上的文件系统名称……至少,您应该使用GetLogicalDrives/Strings()
。这将减少您尝试查询的驱动器数量,即使您坚持使用CreateFile()
/DeviceIoControl()
。与其盲目尝试字母表中的所有26个字母,您只需查询实际分配给驱动器的字母。@RemyLebeau事实上,在我的原始代码中,我确实使用了GetLogicalDrives
,我没有将其包括在这里,因为我认为这与问题无关,但您是对的:这是一个重要部分,所以我对问题进行了编辑以将其包括在内。(抱歉,我以前应该包括在内)。对于当前代码,您会做哪些更改?如果有可能,您可以在回答中发布一个示例代码吗?提前谢谢。使用a枚举所有分区,类似于下面的PowerShellGet WMIOObject-Class“Win32\u Volume”-命名空间“ROOT\CIMV2”|选择对象-属性DriveLetter、标签、文件系统、设备ID
(从Windows 8开始,使用-命名空间“ROOT\Microsoft\Windows\Storage”-类名“MSFT\u Volume”
和-属性DriveLetter、文件系统标签、文件系统、UniqueId
)@JosefZ-wmi不是很有效的方法,这只是远程调用。对于枚举磁盘,卷需要通过配置APIconfig枚举接口。谢谢您的回答@DrakeWu MSFT。您建议哪种解决方案可以可靠地枚举NTFS分区?注意:我正在使用的软件始终以管理员身份运行(所以用户权限应该不是问题)。那么,你能确保调用成功吗。我建议使用getvolumeiformation()
。请参阅我的编辑。它与getvolumeiformation w
@DrakeWu MSFT一起工作,我找到了”NTFS“fs
中的
。测试fs
是否等于NTFS
,是否可靠?或者在某些版本的Windows上它是否也可以是“NTFS”
?@Basj这真的很重要吗?只需使用不区分大小写的比较。@RemyLebeau我的意思是,一般来说,它是否被记录为总是“NTFS”
或者是否有Windows版本可以是NTFS something
或IFS
或任何意义相同的细微变化?(您在聊天中给出了更好的解决方案,但这个问题