1 磁盘的一些信息
1.1 引导项简单描述
MBR分区表的硬盘最多只能划分4个主分区磁盘,并且MBR最大仅支持2TB的硬盘,但拥有很好的兼容性,如果需要分区的硬盘容量超过2TB了,则需要使用GPT分区表类型,此分区表类型不受分区个数,硬盘大小的限制,最大支持18EB(1EB=1024PB=1,048,576TB),且是一种新的硬盘分区标准。
GPT是一个正逐渐取代MBR的新标准,它由UEFI而形成的,有了UEFI用于取代老旧的BIOS,而GPT则取代老旧的MBR,磁盘驱动器容量可以大得多。Windows最大仅支持128个GPT分区,不过NTFS格式最大仅支持256TB,大到操作系统和文件系统都没法支持。
1.2 windows系统的磁盘格式说明
(1)FAT模式;
FAT即FAT16,最大支持分区大小是4GB,一般用在MS-DOS,WIN95等系统。FAT32的最大分区是2TB,但是不支持小于512MB的分区。
(2)FAT32模式;
(3)NTFS模式;
没有直接列出磁盘的uuid信息。
(4)工具里面显示的磁盘格式。
2 获取硬盘的uuid代码实现
注意NTFS格式磁盘的uuid,通过CreateFile打开磁盘时,磁盘的路径是\\\\.\\c:的。\\\\.\\c:\\这样会提示打开失败。
QString formatFat32UUID(LARGE_INTEGER uuid)
{
BYTE b[4];
DWORD uuidHigh = uuid.HighPart;
memcpy(b, &uuidHigh, 4);
QString uuidstr = QString("%1%2-%3%4").
arg(int(b[3]), 2, 16, QLatin1Char('0')).
arg(int(b[2]), 2, 16, QLatin1Char('0')).
arg(int(b[1]), 2, 16, QLatin1Char('0')).
arg(int(b[0]), 2, 16, QLatin1Char('0'));
return uuidstr.toUpper();
}
QString formatNTFSUUID(LARGE_INTEGER uuid)
{
BYTE b[8];
memcpy(b, &uuid, 8);
QString uuidstr = QString("%1%2%3%4%5%6%7%8").
arg(int(b[7]), 2, 16, QLatin1Char('0')).
arg(int(b[6]), 2, 16, QLatin1Char('0')).
arg(int(b[5]), 2, 16, QLatin1Char('0')).
arg(int(b[4]), 2, 16, QLatin1Char('0')).
arg(int(b[3]), 2, 16, QLatin1Char('0')).
arg(int(b[2]), 2, 16, QLatin1Char('0')).
arg(int(b[1]), 2, 16, QLatin1Char('0')).
arg(int(b[0]), 2, 16, QLatin1Char('0'));
return uuidstr.toUpper();
}
bool getNTFSUUID(const QString& strDrive, LARGE_INTEGER& uuid)
{
HANDLE fileHandle = CreateFile(strDrive.toStdWString().c_str(), // \\\\.\\c: or use syntax "\\?\Volume{GUID}"
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == fileHandle) {
int nErrorCode = GetLastError();
qDebug() << "getNTFSUUID fail;errorCode=" << nErrorCode;
return false;
}
DWORD i;
NTFS_VOLUME_DATA_BUFFER ntfsInfo;
DeviceIoControl(fileHandle,
FSCTL_GET_NTFS_VOLUME_DATA,
NULL,
0,
&ntfsInfo,
sizeof(ntfsInfo),
&i,
NULL);
CloseHandle(fileHandle);
uuid = ntfsInfo.VolumeSerialNumber;
return true;
}
void testGetDiskUUID(const QString& lpRootPathName)
{
// QString lpRootPathName = "C:\\";
LPTSTR lpVolumeNameBuffer = new TCHAR[12]; //磁盘卷标
DWORD nVolumeNameSize = 12; // 卷标的字符串长度
DWORD VolumeSerialNumber;//硬盘序列号 ==》
DWORD MaximumComponentLength;// 最大的文件长度
LPTSTR lpFileSystemNameBuffer = new TCHAR[10]; // 存储所在盘符的分区类型的长指针变量
DWORD nFileSystemNameSize = 10; // 分区类型的长指针变量所指向的字符串长度
DWORD FileSystemFlags;// 文件系统的一此标志
GetVolumeInformation((LPTSTR)lpRootPathName.utf16(),
lpVolumeNameBuffer, nVolumeNameSize,
&VolumeSerialNumber, &MaximumComponentLength,
&FileSystemFlags,
lpFileSystemNameBuffer, nFileSystemNameSize);
qDebug() << VolumeSerialNumber;
QString strXuuid = "";
QStorageInfo storage(lpRootPathName);
QString fileType = storage.fileSystemType();
LARGE_INTEGER uUUID;
uUUID.HighPart = VolumeSerialNumber;
if (fileType.compare("NTFS", Qt::CaseInsensitive) == 0) {
// QString strVol = "\\\\.\\i:"; // ok; CreateFile打开磁盘驱动器,\\\\.\\c:;
QString strVol = "\\\\.\\" + lpRootPathName.left(2); // \\\\.\\c:\\不支持这种情况;
// QString strVol = "\\Device\\HarddiskVolume10\\"; // xx;
// QString strVol = "\\?\Volume{73534fd4-d231-11eb-9a29-0800272918b7}"; // xx;
getNTFSUUID(strVol, uUUID);
strXuuid = formatNTFSUUID(uUUID); // getNTFSUUID失败,则只有后面一半的guid;
} else if ((fileType.compare("FAT", Qt::CaseInsensitive) == 0)
|| (fileType.compare("FAT32", Qt::CaseInsensitive)) == 0) {
strXuuid = formatFat32UUID(uUUID); // ok;
}
qDebug() << "rootPath:" << lpRootPathName << "; fileType=" << fileType << "; uuid=" << strXuuid;
}
3 调用方式
// testGetDiskUUID("G:\\");
// testGetDiskUUID("h:\\");
testGetDiskUUID("I:\\");
// testGetDiskUUID("c:\\");