I'm using:
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)
{
...
}
}
}
to enumerate all NTFS partitions of a computer.
It works on my Windows 7, on a Windows 8.1 I tried it on, and on a Windows 10 computer.
But it fails on another Windows 10 computer: on this one, the volume C: has a diskInfo.PartitionType value equal to 0x00, instead of 0x07 (PARTITION_IFS).
This value is (see the doc here):
PARTITION_ENTRY_UNUSED : 0x00 : An unused entry partition.
This is strange, since, I can confirm, the partition is really NTFS.
Questions:
Is it well-known that
IOCTL_DISK_GET_PARTITION_INFOis not 100% reliable to get the partition type?What would be a more reliable way to enumerate all NTFS volumes?
Note: I also looked at using IOCTL_DISK_GET_PARTITION_INFO_EX instead of IOCTL_DISK_GET_PARTITION_INFO but then the structure PARTITION_INFORMATION_EX does not seem to give informations about PartitionType, whereas the structure PARTITION_INFORMATION does give access to PartitionType.
I did further investigation thanks to @RemyLebeau's comments with:
on the computer where it failed (computer with Windows 10). I found that
CreateFilesucceeded but thenDeviceIoControlfailed withGetLastErrorbeing1i.e.ERROR_INVALID_FUNCTION(see System Error Codes (0-499)).Conclusion (I quote Remy's comment):
I then tried with
IOCTL_DISK_GET_PARTITION_INFO_EX:and then it worked. I could see that
diskInfo.PartitionStylewasPARTITION_STYLE_GPT(=1), and this was the reason whyIOCTL_DISK_GET_PARTITION_INFOfailed. I quote Remy's comment again:So here's the conclusion:
use
IOCTL_DISK_GET_PARTITION_INFO_EXinstead ofIOCTL_DISK_GET_PARTITION_INFOif
diskInfo.PartitionStyleis 0 (PARTITION_STYLE_MBR) then diskInfo.Mbr.PartitionType can be tested. If it's 0x07, it's NTFS.if
diskInfo.PartitionStyleis 1 (PARTITION_STYLE_GPT) then diskInfo.Gpt.PartitionType can be tested, see here: https://learn.microsoft.com/en-us/windows/desktop/api/winioctl/ns-winioctl-_partition_information_gpt. Even if the NTFS Wikipedia page mentions the GUIDEBD0A0A2-B9E5-4433-87C0-68B6B72699C7for NTFS in the GPT case, this GUID is in fact unrelated to file system (see comment below about this).it's probably easier to use
GetVolumeInformation()instead and just compare if the result is the"NTFS"string, as in the other answerin my particular case, I initially wanted to test if a volume is NTFS or not before attempting an indexing with
DeviceIoControl(hVol, FSCTL_ENUM_USN_DATA, ...)because I thought such MFT querying would be limited to NTFS volumes. In fact, an easier solution would be to NOT TEST if it's NTFS or not, and just do theFSCTL_ENUM_USN_DATA. The worst that can happen is thatFSCTL_ENUM_USN_DATAfails withERROR_INVALID_FUNCTIONerror, per the documentation: