本文主要是介绍Win32下C++实现快速获取硬盘分区信息,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《Win32下C++实现快速获取硬盘分区信息》这篇文章主要为大家详细介绍了Win32下C++如何实现快速获取硬盘分区信息,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...
实现代码
CDiskDriveUtils.h
#pragma once #include <wtypesbase.h> #include <string> #include <tchar.h> #include <vector> #include <map> #ifdef _UNICODE using _tstring = std::wstring; #else using _tstring = std::string; #endif namespace CDiskDriveUtils { enum ePartitionStyle { ePartitionMBR, ePartitionGPT, ePartitionRAW }; enum eDriveType { eDriveUnknown, eDriveNoRootDir, eDriveRemovable, eDriveFixed, eDriveRemote, eDriveCDROM, eDriveRAMdisk }; enum eStorageBusType { eBusUnknown, eBusScsi, eBusAtapi, eBusAta, eBus1394, eBusSsa, eBusFibre, eBusUsb, eBusRAID, eBusiScsi, eBusSas, eBusSata, eBusSd, eBusMmc, eBusVirtual, eBusFileBackedVirtual, eBusSpaces, eBusNvme, eBusSCM, eBusUfs, eBusMax, eBusMaxReserved = 0x7F }; typedef struct _DISK_PARTION_INFO { _tstring PathName; _tstring VolumeName; uint64_t StartingOffset; uint64_t PartitionLength; uint64_t FreeBytes; uint32_t PartitionNumber; ePartitionStyle PartitionStyle; eDriveType DriveType; _DISK_PARTION_INFO() : PartitionNumber(0), PartitionLength(0), StartingOffset(0), FreeBytes(0), PartitionStyle(ePartitionStyle::ePartitionRAW), DriveType(eDriveType::eDriveUnknown) { } }DISK_PARTION_INFO; typedef struct _LOGICAL_VOLUME_INFO { _tstring PathName; _tstring VolumeName; _tstring FileSystemName; uint64_t StartingOffset; uint64_t ExtentLength; uint64_t FreeBytes; uint32_t DiskNumber; eDriveType DriveType; _LOGICAL_VOLUME_INFO() : DiskNumber(0), StartingOffset(0), ExtentLength(0), FreeBytes(0), DriveType(eDriveType::eDriveUnknown) { } }LOGICAL_VOLUME_INFO; typedef struct _DISK_INFO { _tstring DevicePath; _tstring ProductId; _tstring SerialNumber; _tstring AdapterSerialNumber; _tstring ProductRevision; _tstring BusTypeName; uint64_t DiskSize; uint64_t Attributes; eStorageBusType BusType; int16_t Temperature; bool fRemovableMedia; std::vector<DISK_PARTION_INFO> Partitions; _DISK_INFO() : Temperature(0), BusType(eStorageBusType::eBusUnknown), DiskSize(0), Attributes(0), fRemovableMedia(false) { } }DISK_DRIVE_INFO; std::map<uint32_t, DISK_DRIVE_INFO> GetDiskDriveInfos(); bool GetDiskDriveInfo(dwORD nIndex, DISK_DRIVE_INFO& info); bool GetLogicalVolumeInfo(std::vector<LOGICAL_VOLUME_INFO>& vVolumeInfo); }
CDiskDriveUtils.cpp
#include "CDiskDriveUtils.h" #include <winioctl.h> #include <strsafe.h> #include <cstdint> namespace CDiskDriveUtils { std::string _WStrToMultiStr(UINT CodePage, const std::wstring& str) { int cbMultiByte = ::WideCharToMultiByte(CodePage, 0, str.c_str(), -1, NULL, 0, NULL, NULL); std::string strResult(cbMultiByte, 0); size_t nConverted = ::WideCharToMultiByte(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size(), NULL, NULL); strResult.resize(nConverted); return strResult; } std::wstring _MultiStrToWStr(UINT CodePage, const std::string& str) { int cchWideChar = ::MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, 0); std::wstring strResult(cchWideChar, 0); size_t nConverted = ::MultiByteToWideChar(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size()); strResult.resize(nConverted); return strResult; } _tstring WStrToTStr(const std::wstring& str) { #ifdef _UNICODE android return str; #else return _WStrToMultiStr(CP_ACP, str); #endif } _tstring AStrToTStr(const std::string& str) { #ifdef _UNICODE return _MultiStrToWStr(CP_ACP, str); #else return str; #endif } std::map<uint32_t, DISK_DRIVE_INFO> GetDiskDriveInfos() { std::map<uint32_t, DISK_DRIVE_INFO> result; for (int i = 0; i < 1000; i++) { DISK_DRIVE_INFO info; if (GetDiskDriveInfo(i, info)) { result.emplace(i, info); } } return result; } void RemoveBackSpace(_tstring& strName) { size_t nLength = strName.size(); for (auto it = strName.crbegin(); it != strName.crend(); it++) { if (_T(' ') == *it) { nLength--; } else { break; } } strName.resize(nLength); } bool GetDiskDriveInfo(DWORD nIndex, DISK_DRIVE_INFO& info) { TCHAR szFileName[MAX_PATH] = { 0 }; HANDLE hFile = INVALID_HANDLE_VALUE; DWORD dwBytesReturned = 0; bool bSuccess = false; do { (void)::StringCchPrintf(szFileName, _countof(szFileNameChina编程), _T(R"(\\.\PhysicalDrive%d)"), nIndex); DWORD dwDesiredAccess = GENERIC_READ | GENERICwww.chinasem.cn_WRITE; DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; hFile = ::CreateFile(szFileName, dwDesiredAccess, dwShareMode, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == hFile) { break; } STORAGE_PROPERTY_QUERY StorageQuery = { }; StorageQuery.PropertyId = StorageDeviceProperty; StorageQuery.QueryType = PropertyStandardQuery; std::vector<uint8_t> OutBuffer(1024 * 64); info.DevicePath = szFileName; if (::DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, &StorageQuery, sizeof(StorageQuery), OutBuffer.data(), OutBuffer.size(), &dwBytesReturned, NULL)) { PSTORAGE_DEVICE_DESCRIPTOR pDesc = (PSTORAGE_DEVICE_DESCRIPTOR)OutBuffer.data(); info.ProductId = AStrToTStr((LPCSTR)((LPBYTE)pDesc + pDesc->ProductIdOffset)); info.ProductRevision = AStrToTStr((LPCSTR)((LPBYTE)pDesc + pDesc->ProductRevisionOffset)); info.SerialNumber = AStrToTStr((LPCSTR)((LPBYTE)pDesc + pDesc->SerialNumberOffset)); info.BusType = (eStorageBusType)pDesc->BusType; info.fRemovableMedia = pDesc->RemovableMedia; RemoveBackSpace(info.ProductId); } StorandroidageQuery.PropertyId = StorageDeviceTemperatureProperty; if (::DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, &StorageQuery, sizeof(StorageQuery), OutBuffer.data(), OutBuffer.size(), &dwBytesReturned, NULL)) { PSTORAGE_TEMPERATURE_DATA_DESCRIPTOR pDesc = (PSTORAGE_TEMPERATURE_DATA_DESCRIPTOR)OutBuffer.data(); info.Temperatujsre = pDesc->TemperatureInfo->Temperature; } StorageQuery.PropertyId = StorageAdapterSerialNumberProperty; if (::DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, &StorageQuery, sizeof(StorageQuery), OutBuffer.data(), OutBuffer.size(), &dwBytesReturned, NULL)) { PSTORAGE_ADAPTER_SERIAL_NUMBER pDesc = (PSTORAGE_ADAPTER_SERIAL_NUMBER)OutBuffer.data(); info.AdapterSerialNumber = WStrToTStr(pDesc->SerialNumber); } if (::DeviceIoControl(hFile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, OutBuffer.data(), OutBuffer.size(), &dwBytesReturned, NULL)) { PDISK_GEOMETRY_EX pDesc = (PDISK_GEOMETRY_EX)OutBuffer.data(); info.DiskSize = *(unsigned long long*) & pDesc->DiskSize; } if (::DeviceIoControl(hFile, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, OutBuffer.data(), OutBuffer.size(), &dwBytesReturned, NULL)) { PDRIVE_LAYOUT_INFORMATION_EX pDesc = (PDRIVE_LAYOUT_INFORMATION_EX)OutBuffer.data(); for (DWORD i = 0; i < pDesc->PartitionCount; i++) { PPARTITION_INFORMATION_EX pPartInfo = &pDesc->PartitionEntry[i]; if (0 == pPartInfo->PartitionNumber) { continue; } DISK_PARTION_INFO partionInfo; partionInfo.PartitionStyle = (ePartitionStyle)pPartInfo->PartitionStyle; partionInfo.PartitionLength = pPartInfo->PartitionLength.QuadPart; partionInfo.PartitionNumber = pPartInfo->PartitionNumber; partionInfo.StartingOffset = pPartInfo->StartingOffset.QuadPart; info.Partitions.push_back(partionInfo); } } if (::DeviceIoControl(hFile, IOCTL_DISK_GET_DISK_ATTRIBUTES, NULL, 0, OutBuffer.data(), OutBuffer.size(), &dwBytesReturned, NULL)) { PGET_DISK_ATTRIBUTES pDesc = (PGET_DISK_ATTRIBUTES)OutBuffer.data(); info.Attributes = pDesc->Attributes; } if (::DeviceIoControl(hFile, IOCTL_DISK_GET_CACHE_INFORMATION, NULL, 0, OutBuffer.data(), OutBuffer.size(), &dwBytesReturned, NULL)) { PDISK_CACHE_INFORMATION pDesc = (PDISK_CACHE_INFORMATION)OutBuffer.data(); pDesc = (PDISK_CACHE_INFORMATION)OutBuffer.data(); } // 从卷信息设置分区信息 std::vector<LOGICAL_VOLUME_INFO> vVolumeInfo; (void)GetLogicalVolumeInfo(vVolumeInfo); for (auto& Partition : info.Partitions) { for (const auto& volume : vVolumeInfo) { if (nIndex == volume.DiskNumber && Partition.StartingOffset == volume.StartingOffset) { Partition.PathName = volume.PathName; Partition.VolumeName = volume.VolumeName; Partition.FreeBytes = volume.FreeBytes; Partition.DriveType = volume.DriveType; break; } } } bSuccess = true; } while (false); if (INVALID_HANDLE_VALUE != hFile) { ::CloseHandle(hFile); } return bSuccess; } bool GetLogicalVolumeInfo(std::vector<LOGICAL_VOLUME_INFO>& vVolumeInfo) { CHAR szOutBuffer[1024] = { 0 }; TCHAR szBuf[MAX_PATH] = { 0 }; DWORD dwBytesReturned = 0; if (0 == GetLogicalDriveStrings(_countof(szBuf), szBuf)) { return false; } LPCTSTR lpDriveString = szBuf; while (_T('\0') != *lpDriveString) { TCHAR szDeviceBuf[MAX_PATH] = { 0 }; HANDLE hDevice = INVALID_HANDLE_VALUE; ::StringCchCopy(szDeviceBuf, _countof(szDeviceBuf), _T(R"(\\.\)")); ::StringCchCatN(szDeviceBuf, _countof(szDeviceBuf), lpDriveString, 2); hDevice = ::CreateFile(szDeviceBuf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (INVALID_HANDLE_VALUE == hDevice) { lpDriveString += 4; continue; } if (::DeviceIoControl(hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &szOutBuffer, sizeof(szOutBuffer), &dwBytesReturned, NULL)) { PVOLUME_DISK_EXTENTS pDesc = (PVOLUME_DISK_EXTENTS)szOutBuffer; //当用户尝试获取有关没有软盘的软盘驱动器或没有光盘的 CD-ROM 驱动器的信息时, //系统会显示一个消息框, 防止系统显示此消息框 (void)::SetErrorMode(SEM_FAILCRITICALERRORS); //获取卷信息 (卷中的磁盘数可以跨多个磁盘) 。 for (DWORD i = 0; i < pDesc->NumberOfDiskExtents; i++) { PDISK_EXTENT pDiskExtent = &pDesc->Extents[i]; TCHAR szVolumeName[MAX_PATH] = { 0 }; DWORD dwVolumeSerialNumber = 0; DWORD dwMaximumComponentLength = 0; DWORD dwFileSystemFlags = 0; TCHAR szFileSystemName[MAX_PATH] = { 0 }; ::GetVolumeInformation(lpDriveString, szVolumeName, _countof(szVolumeName), &dwVolumeSerialNumber, &dwMaximumComponentLength, &dwFileSystemFlags, szFileSystemName, _countof(szFileSystemName) ); ULARGE_INTEGER FreeBytesAvailableToCaller = { 0 }; ULARGE_INTEGER TotalNumberOfBytes = { 0 }; ULARGE_INTEGER TotalNumberOfFreeBytes = { 0 }; GetDiskFreeSpaceEx(lpDriveString, &FreeBytesAvailableToCaller, &TotalNumberOfBytes, &TotalNumberOfFreeBytes); LOGICAL_VOLUME_INFO info; info.PathName = _tstring(lpDriveString).substr(0, 2); info.VolumeName = szVolumeName; info.FileSystemName = szFileSystemName; info.DiskNumber = pDiskExtent->DiskNumber; info.StartingOffset = *(unsigned long long*) & pDiskExtent->StartingOffset; info.ExtentLength = *(unsigned long long*) & pDiskExtent->ExtentLength; info.FreeBytes = TotalNumberOfFreeBytes.QuadPart; info.DriveType = (eDriveType)::GetDriveType(lpDriveString); vVolumeInfo.push_back(info); } } ::CloseHandle(hDevice); lpDriveString += 4; } return true; } }
main.cpp
#include <locale.h> #include <tchar.h> #include "Win32Utils/CDiskDriveUtils.h" int _tmain(int argc, LPCTSTR argv[]) { setlocale(LC_ALL, ""); std::map<uint32_t, CDiskDriveUtils::DISK_DRIVE_INFO> diskInfoList = CDiskDriveUtils::GetDiskDriveInfos(); return 0; }
结果如下
以上就是Win32下C++实现快速获取硬盘分区信息的详细内容,更多关于C++获取硬盘分区信息的资料请关注China编程(www.chinasem.cn)其它相关文章!
这篇关于Win32下C++实现快速获取硬盘分区信息的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!