-1

私は使用しています:

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) 
        {
            ...
        }
    }
}

コンピューターのすべての NTFS パーティションを列挙します。

Windows 7、試用した Windows 8.1、および Windows 10 コンピューターで動作します。

しかし、別の Windows 10 コンピューターでは失敗します。このコンピューターでは、ボリュームC:の値が( )ではなく にdiskInfo.PartitionType等しくなります。0x000x07PARTITION_IFS

この値は次のとおりです (こちらのドキュメントを参照してください):

PARTITION_ENTRY_UNUSED : 0x00 : 未使用のエントリ パーティション。

パーティションが実際には NTFS であることを確認できるため、これは奇妙です。

質問:

  • IOCTL_DISK_GET_PARTITION_INFOパーティションの種類を取得するのに 100% 信頼できないことはよく知られていますか?

  • すべての NTFS ボリュームを列挙するより信頼性の高い方法は何ですか?


注:IOCTL_DISK_GET_PARTITION_INFO_EX代わりにの使用も調べましIOCTL_DISK_GET_PARTITION_INFOたが、構造PARTITION_INFORMATION_EXは に関する情報を提供していないようですがPartitionType、構造は へのPARTITION_INFORMATIONアクセスを提供しPartitionTypeます。

4

2 に答える 2

1

@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成功したが、ieDeviceIoControlで失敗したGetLastErrorことがわかりました(システムエラーコード (0-499)を参照)。1ERROR_INVALID_FUNCTION

結論(レミーのコメントを引用):

つまり、DeviceIoControl() に渡したデバイスでは IOCTL_DISK_GET_PARTITION_INFO がサポートされていません。

私はそれから試しましたIOCTL_DISK_GET_PARTITION_INFO_EX

PARTITION_INFORMATION_EX diskInfo;
BOOL ret = DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &diskInfo, sizeof(diskInfo), &lpBytesReturned, NULL);

そしてそれはうまくいきました。diskInfo.PartitionStyleそれが(=1) であることがわかりPARTITION_STYLE_GPT、これが失敗の理由IOCTL_DISK_GET_PARTITION_INFOでした。レミーのコメントをもう一度引用します。

IOCTL_DISK_GET_PARTITION_INFO は、GPT パーティション ドライブではサポートされていません。

だからここに結論があります:

  • IOCTL_DISK_GET_PARTITION_INFO_EXの代わりに使用IOCTL_DISK_GET_PARTITION_INFO

  • GetVolumeInformation()代わりに使用する方がおそらく簡単で、結果が"NTFS"文字列であるかどうかを比較するだけです。他の回答のように

  • 私の特定のケースでは、そのような MFT クエリは NTFS ボリュームに限定されると思っていたので、インデックス作成を試みる前にボリュームが NTFS であるかどうかを最初にテストしたかったのです。DeviceIoControl(hVol, FSCTL_ENUM_USN_DATA, ...)実際、より簡単な解決策は、NTFS であるかどうかをテストせず、単にFSCTL_ENUM_USN_DATA. ドキュメントによると、起こりうる最悪の事態は、エラーでFSCTL_ENUM_USN_DATA失敗することです。ERROR_INVALID_FUNCTION

    「ERROR_INVALID_FUNCTION 指定されたボリュームのファイル システムは、この制御コードをサポートしていません。」

于 2019-03-20T22:20:42.467 に答える