科技 > 操作系统 > Windows

Win32下C++实现快速获取硬盘分区信息

60人参与 2025-03-14 Windows

实现代码

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++获取硬盘分区信息的资料请关注代码网其它相关文章!

(0)

您想发表意见!!点此发布评论

推荐阅读

华南金牌NAS升级版上市:N150处理器+万兆三网口

03-14

Win11 Canary 27813 预览版今日发布:移除Cortana位置历史功能

03-13

微软发布临时解决方案! 解决Win10/Win11一月可选更新导致打印机乱码问题

03-13

intel酷睿Ultra7 265K打造七彩虹iGame全家桶攻略

03-13

可能与英伟达显卡有关! Win11 Canary版被曝D3D9崩溃导致应用无法启动

03-13

Win11 RP 22631.5116 预览版发布:附KB5053657完整更新日志

03-14

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论