Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 枚举所有分区并测试它们是否为NTFS_C++_Windows_Winapi_Ntfs_Ntfs Mft - Fatal编程技术网

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的GUID
      EBD0A0A2-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枚举所有分区,类似于下面的PowerShell
Get 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
或任何意义相同的细微变化?(您在聊天中给出了更好的解决方案,但这个问题