硬盘信息查询(Win32, C++)

CDiskUtils.h

#pragma once

#include <wtypesbase.h>
#include <string>
#include <tchar.h>
#include <vector>

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

typedef struct _PARTION_INFO
{
    _tstring m_PathName;
    _tstring m_VolumeName;
    DWORD m_PartitionNumber;
    unsigned long long m_StartingOffset;
    unsigned long long m_PartitionLength;

    _PARTION_INFO() :
        m_PartitionNumber(0),
        m_PartitionLength(0),
        m_StartingOffset(0)
    {

    }

}PARTION_INFO;

typedef struct _VOLUME_INFO
{
    _tstring m_PathName;
    _tstring m_VolumeName;
    _tstring m_FileSystemName;
    DWORD m_DiskNumber;
    unsigned long long m_StartingOffset;
    unsigned long long m_Length;
    _VOLUME_INFO() :
        m_DiskNumber(0),
        m_StartingOffset(0),
        m_Length(0)
    {

    }

}VOLUME_INFO;

typedef struct _DISK_INFO
{
    _tstring m_ProductId;
    _tstring m_SerialNumber;
    _tstring m_AdapterSerialNumber;
    _tstring m_ProductRevision;
    _tstring m_BusTypeName;
    int m_Temperature;
    int m_BusType;
    unsigned long long m_DiskSize;
    DWORDLONG m_Attributes;
    std::vector<PARTION_INFO> m_Partitions;

    _DISK_INFO() :
        m_Temperature(0),
        m_BusType(0),
        m_DiskSize(0),
        m_Attributes(0)
    {

    }

    void clear()
    {
        m_Partitions.clear();
        m_ProductId.clear();
        m_SerialNumber.clear();
        m_AdapterSerialNumber.clear();
        m_ProductRevision.clear();
        m_BusTypeName.clear();
        m_Temperature = 0;
        m_BusType = 0;
        m_DiskSize = 0;
        m_Attributes = 0;
    }

}DISK_INFO;

class CDiskUtils
{
public:

    static bool GetDiskInfo(DWORD nIndex, DISK_INFO& info);
    static bool GetVolumeInfo(std::vector<VOLUME_INFO>& vVolumeInfo);
};

CDiskUtils.cpp

#include "CDiskUtils.h"
#include "CStrUtils.h"
#include <strsafe.h>

static LPCTSTR s_szBusTypes[] = {
    _T("Unknown"),
    _T("SCSI"),
    _T("ATAPI"),
    _T("ATA"),
    _T("IEEE 1394"),
    _T("SSA"),
    _T("FIBRE"),
    _T("USB"),
    _T("RAID"),
    _T("ISCSI"),
    _T("SAS"),
    _T("SATA"),
    _T("SD"),
    _T("MMC"),
    _T("VIRTUAL"),
    _T("FILEBACKEDVIRTUAL"),
    _T("SPACES"),
    _T("NVMe"),
    _T("SCM"),
    _T("UFS"),
    _T("MAX"),
    _T("MAXRESERVED")
};

bool CDiskUtils::GetDiskInfo(DWORD nIndex, DISK_INFO& info)
{
    TCHAR szBuf[MAX_PATH] = { 0 };
    CHAR szOut[1024] = { 0 };
    HANDLE hDevice = INVALID_HANDLE_VALUE;
    STORAGE_PROPERTY_QUERY spq;
    std::vector<VOLUME_INFO> vVolumeInfo;
    DWORD dwBytesReturned = 0;
    bool bSuccess = false;

    ZeroMemory(&spq, sizeof(spq));
    (void)GetVolumeInfo(vVolumeInfo);

    info.clear();

    (void)::StringCchPrintf(szBuf, _countof(szBuf), _T(R"(\\.\PhysicalDrive%d)"), nIndex);
    hDevice = ::CreateFile(szBuf,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL, OPEN_EXISTING, 0, NULL);
    if (INVALID_HANDLE_VALUE == hDevice)
    {
        goto L_CleanUp;
    }

    spq.PropertyId = StorageDeviceProperty;
    spq.QueryType = PropertyStandardQuery;
    if (::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &spq, sizeof(spq), szOut, sizeof(szOut), &dwBytesReturned, NULL))
    {
        PSTORAGE_DEVICE_DESCRIPTOR pDesc = (PSTORAGE_DEVICE_DESCRIPTOR)szOut;
        info.m_ProductId = CStrUtils::AStrToTStr((LPCSTR)((LPBYTE)pDesc + pDesc->ProductIdOffset));
        info.m_ProductRevision = CStrUtils::AStrToTStr((LPCSTR)((LPBYTE)pDesc + pDesc->ProductRevisionOffset));
        info.m_SerialNumber = CStrUtils::AStrToTStr((LPCSTR)((LPBYTE)pDesc + pDesc->SerialNumberOffset));
        info.m_BusType = pDesc->BusType;
        info.m_BusTypeName = s_szBusTypes[pDesc->BusType];
    }

    spq.PropertyId = StorageDeviceTemperatureProperty;
    if (::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &spq, sizeof(spq), szOut, sizeof(szOut), &dwBytesReturned, NULL))
    {
        PSTORAGE_TEMPERATURE_DATA_DESCRIPTOR pDesc = (PSTORAGE_TEMPERATURE_DATA_DESCRIPTOR)szOut;
        info.m_Temperature = pDesc->TemperatureInfo->Temperature;
    }

    spq.PropertyId = StorageAdapterSerialNumberProperty;
    if (::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &spq, sizeof(spq), szOut, sizeof(szOut), &dwBytesReturned, NULL))
    {
        PSTORAGE_ADAPTER_SERIAL_NUMBER pDesc = (PSTORAGE_ADAPTER_SERIAL_NUMBER)szOut;
        info.m_AdapterSerialNumber = CStrUtils::WStrToTStr(pDesc->SerialNumber);
    }

    if (::DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &szOut, sizeof(szOut), &dwBytesReturned, NULL))
    {
        PDISK_GEOMETRY_EX pDesc = (PDISK_GEOMETRY_EX)szOut;
        info.m_DiskSize = *(unsigned long long*)& pDesc->DiskSize;
    }

    if (::DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, &szOut, sizeof(szOut), &dwBytesReturned, NULL))
    {
        PDRIVE_LAYOUT_INFORMATION_EX pDesc = (PDRIVE_LAYOUT_INFORMATION_EX)szOut;
        for (DWORD i = 0; i < pDesc->PartitionCount; i++)
        {
            PPARTITION_INFORMATION_EX pPartInfo = &pDesc->PartitionEntry[i];
            if (0 == pPartInfo->PartitionNumber)
            {
                continue;
            }

            PARTION_INFO partionInfo;
            partionInfo.m_PartitionLength = *(unsigned long long*) &pPartInfo->PartitionLength;
            partionInfo.m_PartitionNumber = pPartInfo->PartitionNumber;
            partionInfo.m_StartingOffset = *(unsigned long long*) & pPartInfo->StartingOffset;
            info.m_Partitions.push_back(partionInfo);
        }
    }

    if (::DeviceIoControl(hDevice, IOCTL_DISK_GET_DISK_ATTRIBUTES, NULL, 0, &szOut, sizeof(szOut), &dwBytesReturned, NULL))
    {
        PGET_DISK_ATTRIBUTES pDesc = (PGET_DISK_ATTRIBUTES)szOut;
        info.m_Attributes = pDesc->Attributes;
    }

    if (::DeviceIoControl(hDevice, IOCTL_DISK_GET_CACHE_INFORMATION, NULL, 0, &szOut, sizeof(szOut), &dwBytesReturned, NULL))
    {
        PDISK_CACHE_INFORMATION pDesc = (PDISK_CACHE_INFORMATION)szOut;
        pDesc = (PDISK_CACHE_INFORMATION)szOut;
    }

    // 从卷信息设置分区信息
    for (auto& item : info.m_Partitions)
    {
        for (const auto& volume : vVolumeInfo)
        {
            if (nIndex == volume.m_DiskNumber &&
                item.m_StartingOffset == volume.m_StartingOffset
                )
            {
                item.m_PathName = volume.m_PathName;
                item.m_VolumeName = volume.m_VolumeName;
                break;
            }
        }
    }

    bSuccess = true;

L_CleanUp:

    if (INVALID_HANDLE_VALUE != hDevice)
    {
        ::CloseHandle(hDevice);
    }

    return bSuccess;
}

bool CDiskUtils::GetVolumeInfo(std::vector<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)
                );

                VOLUME_INFO info;
                info.m_PathName = _tstring(lpDriveString).substr(0, 2);
                info.m_VolumeName = szVolumeName;
                info.m_FileSystemName = szFileSystemName;
                info.m_DiskNumber = pDiskExtent->DiskNumber;
                info.m_StartingOffset = *(unsigned long long*) & pDiskExtent->StartingOffset;
                info.m_Length = *(unsigned long long*) & pDiskExtent->ExtentLength;
                vVolumeInfo.push_back(info);
            }
        }

        ::CloseHandle(hDevice);
        lpDriveString += 4;
    }

    return true;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AccessChk: 显示指定用户或组对 注册表 文件 或服务的访问 AccessEnum: 简单强大的安全工具,显示哪些用户访问了哪些目录、文件及注册键。帮助找出权限策略中的漏洞。 AdExplorer: 活动目录浏览器. AdInsight: LDAP 实时监控工具 AdRestore: Server 2003 活动目录对象反删除. Autologon: 登录时跳过密码认证. Autoruns: 显示开机自启动项的配置,比较实用。 显示包括注册键和文件位置在内的全面列表。 BgInfo: 可配置的桌面背景自动生成程序,可以生成含有重要系统信息的桌面背景,其中包括 IP 地址, 计算机名, 网络适配器, 等信息. BlueScreen: 不但能精确模拟蓝屏还能重启 (完全借助 CHKDSK) DebugView: Sysinternals 的又一首创: 该程序可以拦截设备驱动对 DbgPrint 的调用和Win32程序对OutputDebugString 的调用. 程序可以浏览或记录本机或远程计算机上调试会话的输出,而无须激活调试器. Desktops:创建虚拟桌面,使用任务栏界面或热键预览每个桌面上的内容并在这些桌面之间轻松地进行切换。 DiskExt: 显示卷分区与磁盘的映射关系。(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS) DiskView: 图形化磁盘扇区工具 Diskmon: 捕获硬盘的所有活动,或以硬盘活动指示灯的形式出现在托盘中。 Du: 按目录浏览磁盘使用情况 EFSDump: 显示有关已加密文件的信息 Filemon: 即时监视文件系统的活动 (监视文件读写,常配合RegMon判断某软件对电脑做了什么手脚) Handle: 小巧的命令行工具,显示呢哪些文件被哪些进程打开,及相关更多信息。 Hex2dec: 16进制-10进制互换. Junction: 创建 NTFS卷上的符号链接(类似Linux的符号链接,灵活运用的话相当实用) LDMDump: 可以转储 Logical Disk Manager 在磁盘中的数据库.(LDMDump) ListDLLs: 列出当前载入的所有 DLLs 及他们的位置和版本。2.0 版可以显示已载入模组的完整路径名. LiveKd: 在live(CD) 系统中使用 Microsoft 内核调试器或MS 内核调试工具Windbg . LoadOrder: 查看 WinNT/2K 中设备的载入顺序 MoveFile: 为下次启动前安排文件的移动和删除操作 LogonSessions: 列出系统中活动的登陆会话 NewSID: 了解有关计算机SID的问题,这是一个 SID 更改程序,为你换一个新的SID. NTFSInfo: 使用 NTFSInfo 查看有关 NTFS 卷的详细信息, 包括 主文件表 (MFT) 的大小位置和 MFT-zone, 以及 NTFS 元数据文件的大小. PageDefrag: (启动时)为页面文件和注册表HIVE文件进行碎片整理. PendMoves: 列出延迟到下次启动前执行的文件移动、删除操作 Portmon: 监视串/并口的数据活动支持所有标准的串并口 IOCTLs 甚至可以显示一部分交换的数据. Process Explorer: 能找出进程打开的文件,注册键,以及其他对象,载入的 DLLs和进程所有者等信息。 Process Monitor: 实时监视文件系统,注册表,进程,线程以及DLL的活动. ProcFeatures: 报告进程或窗口对PAE与NX缓冲区溢出保护的支持情况. PsTools: 该命令行工具包提供列出本地/远程计算机进程、远程运行进程、重启、转储事件日志、及更多功能. PsExec: 在远程系统执行进程. PsFile: 查看本地被远程打开的文件. PsGetSid: 显示计算机或用户的 SID . PsInfo: 获取系统信息. PsKill: 终止本地或远程进程. PsList: 显示进程和线程有关的信息. PsLoggedOn: 显示已登陆系统的用户 PsLogList: 转储事件日志记录. PsPasswd: 更改账户密码. PsService: 查看设置服务. PsShutdown: 关闭或重启电脑. PsSuspend: 冻结或恢复进程. RegDelNull: 扫描并删除包含标准注册表编辑器无法删除的内嵌空字符的注册表键. RegHide: 使用内置 API 创建名为 "HKEY_LOCAL_MACHINESoftwareSysinternalsCan't touch me!0" 的注册键及在其中创建键值. Regjump: 在Regedit中跳转至指定的注册键路径. Regmon: 实时监视所有注册表活动 (监视注册表变化,可以配合FileMon来判断某软件在电脑上做了什么手脚) RootkitRevealer: 扫描系统中基于RootKit的恶意程序. SDelete: 兼容发国防部标准的安全删除程序,安全覆盖您的敏感文件并清理已删除文件留下的空闲空间. ShareEnum: 扫描网络上的文件共享并浏览其安全设置,来发现漏洞. Sigcheck: 转储文件版本信息并校验系统中的映像是否经过数字签名. Streams: 显示 NTFS 交换数据流 Strings: 在二进制映像内搜索 ANSI / UNICODE 字串. Sync: (释放磁盘写缓存),发送缓存中的数据至硬盘/移动磁盘。 TCPView: 活动 socket 的观察器. (可以方便查看什么软件占用了什么端口之类的) VolumeId: 设置 FAT 或 NTFS 驱动器的卷ID Whois: 查看网址的所有者. Winobj: 对象管理器命名空间的查看利器. ZoomIt: 辅助演示工具支持屏幕上进行和画图.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值