实现代码
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
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(szfilename), _t(r"(\\.\physicaldrive%d)"), nindex);
dword dwdesiredaccess = generic_read | generic_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);
}
storagequery.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.temperature = 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++获取硬盘分区信息的资料请关注代码网其它相关文章!
发表评论