当前位置:网站首页>Obtain information about hard disk and volume or partition (capacity, ID, volume label name, etc.)

Obtain information about hard disk and volume or partition (capacity, ID, volume label name, etc.)

2022-06-26 14:09:00 lengye7

1、 Enumerate all hard disks

Here mainly with the help of setup API, these API Mainly NT4.0 Some for operating the equipment are provided later API.

Enumerate all hard disks with the help of SetupDiGetClassDevs And SetupDiEnumDeviceInterfaces and SetupDiGetDeviceInterfaceDetail These three API.

#pragma once


#ifndef DEVICE_DISK_H
#define DEVICE_DISK_H
#include <Windows.h>
#include <Setupapi.h>
#pragma comment( lib, "setupapi.lib" )
#define DevCount 1024
struct DevInterfaceDetaillArray {
    DWORD szCount;
    PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData_[DevCount];
};

int GetALLDISK(struct DevInterfaceDetaillArray* DevInterfaceDetailArr_);

int FreeALLDISK(struct DevInterfaceDetaillArray* DevInterfaceDetailArr_);

#endif
 

#include "DeviceDisk.h"

#include <iostream>
#include <string>
using namespace std;


// When a function call goes wrong, you must remember to reclaim memory , Otherwise, there will be a memory leak .
// Remember to communicate with FreeALLDISK Use in pairs .

int GetALLDISK(struct DevInterfaceDetaillArray* DevInterfaceDetailArr_) {

    HDEVINFO diskClassDevices;
    GUID diskClassDeviceInterfaceGuid = GUID_DEVINTERFACE_DISK;
    SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
    PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData;
    DWORD requiredSize;
    DWORD deviceIndex;


    //
    // Get the handle to the device information set for installed
    // disk class devices. Returns only devices that are currently
    // present in the system and have an enabled disk device
    // interface.
    //
    diskClassDevices = SetupDiGetClassDevs(&diskClassDeviceInterfaceGuid,
        NULL,
        NULL,
        DIGCF_PRESENT |
        DIGCF_DEVICEINTERFACE);
    
    if (INVALID_HANDLE_VALUE == diskClassDevices) {
        return -1;
    }


    ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
    deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    deviceIndex = 0;

    while (SetupDiEnumDeviceInterfaces(diskClassDevices,
        NULL,
        &diskClassDeviceInterfaceGuid,
        deviceIndex,
        &deviceInterfaceData)) {


        SetupDiGetDeviceInterfaceDetail(diskClassDevices,
            &deviceInterfaceData,
            NULL,
            0,
            &requiredSize,
            NULL);
            // Reclaim temporary memory
        if (!(ERROR_INSUFFICIENT_BUFFER == GetLastError())) {
            wprintf_s(L"122\n"); // Under normal circumstances , Is to obtain 122 Error code , We don't know windows What are you doing .
            if (INVALID_HANDLE_VALUE != diskClassDevices) {
                SetupDiDestroyDeviceInfoList(diskClassDevices);
            }
            return -1;
        }


        deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);


        ZeroMemory(deviceInterfaceDetailData, requiredSize);
        deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        if (!SetupDiGetDeviceInterfaceDetail(diskClassDevices,
            &deviceInterfaceData,
            deviceInterfaceDetailData,
            requiredSize,
            NULL,
            NULL)) {
            // There is no such thing as deviceInterfaceDetailData Memory returned to DevInterfaceDetailArr_ in , So it must be released before returning , Prevent memory leaks .
            free(deviceInterfaceDetailData);
            // Reclaim temporary memory
            if (INVALID_HANDLE_VALUE != diskClassDevices) {
                SetupDiDestroyDeviceInfoList(diskClassDevices);
            }
            return -1;
        }
            
        DevInterfaceDetailArr_->deviceInterfaceDetailData_[deviceIndex] = deviceInterfaceDetailData;
        ++deviceIndex;
    }

    DWORD Err_Code = GetLastError();

    DevInterfaceDetailArr_->szCount = deviceIndex;

    // Reclaim temporary memory before returning
    if (INVALID_HANDLE_VALUE != diskClassDevices) {
        SetupDiDestroyDeviceInfoList(diskClassDevices);
    }
    if (ERROR_NO_MORE_ITEMS == Err_Code) {
        // The normal exit while The status code :259,no more data availible.
        return 0;
    }
    return -2; //0 Normal execution succeeded ,-1 Loop internal execution error ,-2 Execution error exit loop .
}


int FreeALLDISK(struct DevInterfaceDetaillArray* DevInterfaceDetailArr_) {
    for (int i = 0; i < DevInterfaceDetailArr_->szCount; i++) {
        free(DevInterfaceDetailArr_->deviceInterfaceDetailData_[i]);
    }
    return 0;
}

2、 Get hard disk information ( Capacity 、 Manufacturer , seller , edition , Hard disk number ( That is, the serial number of the hard disk displayed in the system ) etc. )

The core is through createfile Turn on the hard disk device , Get a processing handle related to the hard disk device .

And then through DeviceIoControl And the corresponding control code to obtain hard disk related information .

A project address that uses this similar method :GitHub - comefromezero/efiboot: a efiboot tool on windows

The following code is just an example , It doesn't run directly .

  if (0 != GetALLDISK(&DevIn)) {
        wprintf_s(L" call GetALLDISK error !");
        FreeALLDISK(&DevIn);
        return -1;
    }
    HANDLE hdisk = INVALID_HANDLE_VALUE ;
    PSTORAGE_DEVICE_DESCRIPTOR pDevDesc;
    STORAGE_PROPERTY_QUERY Query;
    DWORD dwOutBytes;


    Query.PropertyId = StorageDeviceProperty;
    Query.QueryType = PropertyStandardQuery;
    
    pDevDesc = (PSTORAGE_DEVICE_DESCRIPTOR)new BYTE[sizeof(STORAGE_DEVICE_DESCRIPTOR) + 512 - 1];
    
    ZeroMemory(pDevDesc, sizeof(STORAGE_DEVICE_DESCRIPTOR) + 512 - 1);
    pDevDesc->Size = sizeof(STORAGE_DEVICE_DESCRIPTOR) + 512 - 1;
    //wprintf_s(L"%d", pDevDesc->Size);
    
    //struct EFI_Disk_Info efi_disk[1024] = { 0 };
    //g_efi_disk = efi_disk;

    GET_LENGTH_INFORMATION disk_len = { 0 };
    STORAGE_DEVICE_NUMBER diskNumber = { 0 };
    DWORD sizePar = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + sizeof(PARTITION_INFORMATION_EX) * 128;
    PDRIVE_LAYOUT_INFORMATION_EX ParTable = (PDRIVE_LAYOUT_INFORMATION_EX)new BYTE[sizePar];
    ZeroMemory(ParTable, sizePar);
    int devIndex = 0;

    TCHAR szPathName[MAX_PATH + 1] = { 0 };

    for (devIndex = 0; devIndex < DevIn.szCount; devIndex++) {
        wprintf_s(L"DiskInfo:%s\n", DevIn.deviceInterfaceDetailData_[devIndex]->DevicePath);
        hdisk = CreateFile(DevIn.deviceInterfaceDetailData_[devIndex]->DevicePath, 
            GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 
            NULL,
            OPEN_EXISTING, 
            FILE_ATTRIBUTE_NORMAL, NULL);
        if (INVALID_HANDLE_VALUE == hdisk) {
            wprintf_s(L"createfile error! error_code:%d\n", GetLastError());
            return -1;
        }
        if (!DeviceIoControl(hdisk,
            IOCTL_STORAGE_QUERY_PROPERTY,
            &Query, sizeof(STORAGE_PROPERTY_QUERY),
            pDevDesc, pDevDesc->Size,
            &dwOutBytes,
            NULL)
            ){ 
            wprintf_s(L"DeviceIoControl Error! line:238 Error_Code:%d %d\n", GetLastError(),dwOutBytes);
            
            
            
        }
        if (!DeviceIoControl(hdisk, IOCTL_DISK_GET_LENGTH_INFO,
            NULL,
            0,
            &disk_len, sizeof(disk_len), &dwOutBytes, NULL)) {

            wprintf_s(L"DeviceIoControl Error! line:248 Error_Code:%d %d\n", GetLastError(), dwOutBytes); //122 It's normal .

        }

        if (!DeviceIoControl(hdisk,
            IOCTL_STORAGE_GET_DEVICE_NUMBER,
            NULL,
            0,
            &diskNumber,
            sizeof(STORAGE_DEVICE_NUMBER),
            &dwOutBytes,
            NULL)) {

            wprintf_s(L"DeviceIoControl Error! line:272 Error_Code:%d %d\n", GetLastError(), dwOutBytes);

        }
        dwOutBytes = 0;
        if (!DeviceIoControl(hdisk,
            IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
            NULL,
            0,
            ParTable,
            sizePar,
            &dwOutBytes,
            NULL)) {

            wprintf_s(L"DeviceIoControl Error! line:285 Error_Code:%d %d\n", GetLastError(), dwOutBytes);

        }

        g_efi_disk[devIndex] = (struct EFI_Disk_Info*)new (struct EFI_Disk_Info);
        CloseHandle(hdisk);
        hdisk = INVALID_HANDLE_VALUE;
        //wprintf_s(L"%d %d\n", dwOutBytes, pDevDesc->Size);
        char* p_char_string = (char*)pDevDesc;
        stringstream sz_buffer;
        g_efi_disk[devIndex]->productor = std::string(&p_char_string[pDevDesc->ProductIdOffset]);
        g_efi_disk[devIndex]->version = std::string(&p_char_string[pDevDesc->ProductRevisionOffset]);
        g_efi_disk[devIndex]->vendor = std::string(&p_char_string[pDevDesc->VendorIdOffset]);
        int buffer_disk_len = disk_len.Length.QuadPart / 1024 / 1024 / 1024;
        sz_buffer << buffer_disk_len << "GB";
        g_efi_disk[devIndex]->length = sz_buffer.str();
        g_efi_disk[devIndex]->number = std::to_string(diskNumber.DeviceNumber);
        printf_s("Productor:%s\n", g_efi_disk[devIndex]->productor.c_str());
        printf_s("Version:%s\n", g_efi_disk[devIndex]->version.c_str());
        printf_s("Vendor:%s\n", g_efi_disk[devIndex]->vendor.c_str());
        printf_s("Length:%s\n", g_efi_disk[devIndex]->length.c_str());
        printf_s("Number:%s\n", g_efi_disk[devIndex]->number.c_str());

        wprintf_s(L"===================================================================================\n");
        wprintf_s(L"ParTable:\n");
        wprintf_s(L"ParTableType:%d\n",ParTable->PartitionStyle);
        wprintf_s(L"ParCount:%d\n", ParTable->PartitionCount);
        
        wprintf_s(L"Par0:\nParNum:%d\nParName:%s\n", ParTable->PartitionEntry[0].PartitionNumber,ParTable->PartitionEntry[0].Gpt.Name);
        wprintf_s(L"PatLength:%dMB\n", ParTable->PartitionEntry[0].PartitionLength.QuadPart / 1024 / 1024);
        wprintf_s(L"ParType:{%04x-%02x-%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data1,
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data2,
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data3,
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data4[0],
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data4[1],
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data4[2],
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data4[3],
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data4[4],
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data4[5],
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data4[6],
            ParTable->PartitionEntry[0].Gpt.PartitionType.Data4[7]);
        wprintf_s(L"ParGUID:{%04x-%02x-%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data1,
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data2,
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data3,
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[0],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[1],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[2],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[3],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[4],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[5],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[6],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[7]);
        
        wprintf_s(L" Number of bytes returned :%d\n", dwOutBytes);
        //ParTable = { 0 };
        wprintf_s(L"===================================================================================\n");
        wsprintf(szPathName, L"\\\\\?\\Volume{%04x-%02x-%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\",
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data1,
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data2,
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data3,
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[0],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[1],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[2],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[3],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[4],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[5],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[6],
            ParTable->PartitionEntry[0].Gpt.PartitionId.Data4[7]);
        wprintf_s(L"%s\n", szPathName);
    }
    delete pDevDesc;
    FreeALLDISK(&DevIn);

 3、 Get information about volumes or partitions ( Volume label name and file system format, etc )

The core API Namely GetVolumeInfomation To get the corresponding information .

A project address using this method :

GitHub - comefromezero/efiboot: a efiboot tool on windows

The following example cannot be run directly .

if (0 == GetVolumeInformation(ParName, VolumeName, 1024, NULL, NULL, NULL, FileSysName, 1024)) {
wprintf_s(L"Line:%d Err_Code:%d\n",__LINE__, GetLastError());
return -1;
}

4、 obtain volume The hard disk number of the hard disk

With a hard disk number, you can pass createfile Create a handle to the hard disk device , And then use it DeviceIoControl Get information about the hard disk .

A project address using this method :

GitHub - comefromezero/efiboot: a efiboot tool on windows

The following example cannot be run directly .


    // Get the hard disk where the partition is located


    TCHAR Buf_Par_Name[1024] = { 0 };
    memcpy(Buf_Par_Name, ParName, wstrlen(ParName)-4); // Build partition devices , be used for createfile Open partition .
    //wprintf_s(L"    Line:%d ParName:%s\n",__LINE__, Buf_Par_Name);
    HANDLE h_vol = INVALID_HANDLE_VALUE;
    h_vol = CreateFile(Buf_Par_Name,
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL, NULL);

    if (INVALID_HANDLE_VALUE == h_vol) {
        wprintf_s(L"Line:%d Err_Code:%d\n",__LINE__, GetLastError());
        return -1;
    }

    DWORD dwOutBytes = 0;
    PVOLUME_DISK_EXTENTS vol_disk_info = (PVOLUME_DISK_EXTENTS)new BYTE[sizeof(VOLUME_DISK_EXTENTS) + sizeof(DISK_EXTENT) * 10];
    ZeroMemory(vol_disk_info, sizeof(VOLUME_DISK_EXTENTS) + sizeof(DISK_EXTENT) * 10);
    if (!DeviceIoControl(h_vol,
        IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
        NULL, 0,
        vol_disk_info, sizeof(VOLUME_DISK_EXTENTS) + sizeof(DISK_EXTENT) * 10,
        &dwOutBytes,
        NULL)
        ) {

        wprintf_s(L"DeviceIoControl Error! line:%d Error_Code:%d %d\n",__LINE__, GetLastError(), dwOutBytes);

    }

among VOLUME_DISK_EXTENTS The hard disk number is saved in the structure .

5、 Get all the partitions in a hard disk

  Use DeviceIoControl And control code IOCTL_DISK_GET_DRIVE_LAYOUT_EX List all partition entries of the hard disk , Then you can know the number of partitions on the hard disk and its related information .

6、 Name all the volume Information

FindFirstVolume And FindNextVolume these two items. API You can list all partition paths , And then through GetVolumeInfomation This API You can get the corresponding information .

Here's a question , On the issue of capacity ,GetDiskFreeSpaceA This gets the number of clusters , There is a problem of alignment , This API To obtain the volume The capacity may not match the actual capacity of the partition , Because there is no file system when partitioning , But after formatting to a file system , The file system manages the partition capacity , So appear GetDiskFreeSpaceA The capacity may not match the actual capacity of the partition , This needs attention .

Displayed in the system volume Capacity and GetDiskFreeSpaceA Consistent capacity .

原网站

版权声明
本文为[lengye7]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202170510558723.html