首页 > 其他分享 >11.9 实现磁盘相关操作

11.9 实现磁盘相关操作

时间:2023-11-20 09:11:37浏览次数:32  
标签:return 11.9 space int char printf 磁盘 操作

11.9.1 遍历磁盘容量

如下代码实现了在Windows系统中获取所有磁盘驱动器的信息。具体包括两个函数,一个用于获取驱动器类型,另一个用于获取驱动器空间信息。主函数则调用这两个函数来遍历所有逻辑驱动器并输出相应的信息。在输出驱动器空间信息时,会输出该驱动器的总大小、已用空间以及可用空间。

#include <stdio.h>
#include <Windows.h>

void GetDrivesType(const char* lpRootPathName)
{
  UINT uDriverType = GetDriveType(lpRootPathName);
  switch (uDriverType)
  {
    case DRIVE_UNKNOWN:puts("未知磁盘"); break;
    case DRIVE_NO_ROOT_DIR: puts("路径无效"); break;
    case DRIVE_REMOVABLE: puts("可移动磁盘"); break;
    case DRIVE_FIXED: puts("固定磁盘"); break;
    case DRIVE_REMOTE: puts("网络磁盘"); break;
    case DRIVE_CDROM: puts("光驱"); break;
    case DRIVE_RAMDISK: puts("内存映射盘"); break;
    default: break;
  }
}

void GetDrivesFreeSpace(const char* lpRootPathName)
{
  unsigned long long available, total, free;
  if (GetDiskFreeSpaceEx(lpRootPathName, (ULARGE_INTEGER*)&available, 
    (ULARGE_INTEGER*)&total, (ULARGE_INTEGER*)&free))
  {
    printf("磁盘: %s | 总计: %lld MB 已用: %lld MB 剩余: %lld MB \n",
      lpRootPathName, total >> 20, available >> 20, free >> 20);
  }
}

int main(int argc,char *argv[])
{
  DWORD dwSize = MAX_PATH;
    char szLogicalDrives[MAX_PATH] = {0};

    // 获取逻辑驱动器号字符串
  DWORD dwResult = GetLogicalDriveStringsA(dwSize, szLogicalDrives);
  
  if (dwResult > 0 && dwResult <= MAX_PATH)
  {
      // 从缓冲区起始地址开始
    char* szSingleDrive = szLogicalDrives;
    while (*szSingleDrive) {
      //printf("Drive: %s\n", szSingleDrive);      // 输出单个驱动器的驱动器号
      // GetDrivesType(szSingleDrive);
      GetDrivesFreeSpace(szSingleDrive);
      // 获取下一个驱动器地址
      szSingleDrive += strlen(szSingleDrive) + 1;
    }
  }

  system("pause");
  return 0;
}

11.9.2 遍历盘符并存储

循环遍历盘符分区,并将所有盘符结构存储到std::vector<MyDriver>定义的容器中.

#include <windows.h>
#include <iostream>
#include <vector>
#include <string>

// 将字节转换为GB单位显示的宏定义
#define ToGB(x) (x.HighPart << 2) + (x.LowPart >> 20) / 1024.0

// 定义基础结构
typedef struct
{
    double available_space;
    double free_space;
    double total_space;
}DriverInfo;

// 定义完整结构
typedef struct
{
    char driver_name[128];
    char driver_type[128];
    double available_space;
    double free_space;
    double total_space;
}MyDriver;

using namespace std;

// 获取驱动器数量
int GutDrivesCount()
{
    DWORD drivers;
    int count = 0;

    //获取驱动器数
    drivers = GetLogicalDrives();
    while (drivers != 0)
    {
        if (drivers & 1 != 0)
        {
            count++;
        }
        drivers >>= 1;
    }
    return count;
}

// 获取驱动器类型
std::string GetDrivesType(const char* lpRootPathName)
{
    UINT uDriverType = GetDriveType(lpRootPathName);
    switch (uDriverType)
    {
    case DRIVE_UNKNOWN:
        return "未知类型"; break;
    case DRIVE_NO_ROOT_DIR:
        return "路径无效"; break;
    case DRIVE_REMOVABLE:
        return "可移动磁盘"; break;
    case DRIVE_FIXED:
        return "固定磁盘"; break;

    case DRIVE_REMOTE:
        return "网络磁盘"; break;
    case DRIVE_CDROM:
        return "光驱设备"; break;
    case DRIVE_RAMDISK:
        return "内存映射盘"; break;
    default:
        break;
    }
    return "错误参数";
}

// 获取盘符容量
DriverInfo GetDrivesFreeSpace(const char* lpRootPathName)
{
    // ULARGE_INTEGER 64位无符号整型值
    ULARGE_INTEGER available, total, free;
    DriverInfo ref;

    // 获取分区数据并返回DriversInfo结构体
    if (GetDiskFreeSpaceEx(lpRootPathName, (ULARGE_INTEGER*)&available, (ULARGE_INTEGER*)&total, (ULARGE_INTEGER*)&free))
    {
        ref.total_space = ToGB(total);
        ref.free_space = ToGB(available);
        ref.available_space = ref.total_space - ref.free_space;
    }
    return ref;
}

std::vector<MyDriver> GetDriveForVector()
{
    DWORD count = GutDrivesCount();
    std::cout << "驱动器个数: " << count << std::endl;

    DWORD dwSize = MAX_PATH;
    char szLogicalDrives[MAX_PATH] = { 0 };

    // 获取逻辑驱动器号字符串
    DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives);

    // 处理获取到的结果
    if (dwResult > 0 && dwResult <= MAX_PATH)
    {
        // 定义两个结构, MyDriver 临时存储单个结构,ref存储所有磁盘的容器
        MyDriver my_driver_ptr;
        std::vector<MyDriver> ref;

        // 从缓冲区起始地址开始
        char* szSingleDrive = szLogicalDrives;

        while (*szSingleDrive)
        {
            // 逻辑驱动器类型
            std::string type = GetDrivesType(szSingleDrive);

            // 获取磁盘空间信息并存入 DriverInfo 结构
            DriverInfo ptr;
            ptr = GetDrivesFreeSpace(szSingleDrive);

            // 填充结构数据
            strcpy(my_driver_ptr.driver_name, szSingleDrive);
            strcpy(my_driver_ptr.driver_type, type.c_str());
            my_driver_ptr.total_space = ptr.total_space;
            my_driver_ptr.free_space = ptr.free_space;
            my_driver_ptr.available_space = ptr.available_space;

            // 加入到容器中
            ref.push_back(my_driver_ptr);
            /*
            std::cout
                << "盘符: " << szSingleDrive
                << " 类型: " << type
                << " 总容量: " << ptr.total_space
                << " 可用空间: " << ptr.free_space
                << " 已使用: " << ptr.available_space
                << std::endl;
            */
            // 获取下一个驱动器号起始地址
            szSingleDrive += strlen(szSingleDrive) + 1;
        }
        return ref;
    }
}

int main(int argc,char *argv[])
{
    std::vector<MyDriver> ptr = GetDriveForVector();

    // 循环输出vector容器
    for (int x = 0; x < ptr.size(); x++)
    {
        std::cout
            << "盘符: " << ptr[x].driver_name
            << " 类型: " << ptr[x].driver_type
            << " 总容量: " << ptr[x].total_space
            << " 可用空间: " << ptr[x].free_space
            << " 已使用: " << ptr[x].available_space
            << std::endl;
    }

    std::system("pause");
    return 0;
}

11.9.3 实现磁盘格式化

如下代码定义了一个函数FormatDisk,用于格式化由指定为字符串的驱动器号标识的磁盘。该函数使用Shell2.dll模块中的SHFormatDrive()这个未导出函数实现对特定磁盘的格式化。

FormatDisk函数采用std::string参数strDisk,该参数指定要格式化的磁盘的驱动器号。该函数首先使用LoadLibraryA加载Shell32.dll库,然后使用GetProcAddress检索SHFormatDrive函数的地址。使用控制台应用程序的窗口句柄、要格式化的磁盘的驱动器ID(根据驱动器号计算)以及指定格式选项的标志来调用SHFormatDrive函数。

#include <iostream>
#include <string>
#include <Windows.h>
#include <ShlObj.h>

#pragma comment(lib, "Shell32.lib")

// 格式化磁盘
void FormatDisk(std::string strDisk)
{
  HINSTANCE hInstance = ::LoadLibraryA("Shell32.dll");
  if (NULL == hInstance)
  {
    return;
  }
  typedef DWORD(*PSHFORMATDRIVE)(HWND, UINT, UINT, UINT);
  PSHFORMATDRIVE SHFormatDrive = (PSHFORMATDRIVE)::GetProcAddress(hInstance, "SHFormatDrive");
  if (NULL == SHFormatDrive)
  {
    return;
  }
  UINT uiID = strDisk[0] - 'A';

  // 获取控制台程序窗口句柄
  HWND hWnd = ::GetConsoleWindow();

  SHFormatDrive((HWND)hWnd, uiID, 0xFFFF, 0x0001);
  ::FreeLibrary(hInstance);
}

int main(int argc, char* argv[])
{
  // 传入磁盘
  FormatDisk("D");

  return 0;
}

11.9.4 移除指定磁盘

如下代码演示了如何通过 Windows API 移除指定的磁盘驱动器,包括移除盘符和卸载卷加载点。代码首先定义了一个 DeleteVolume 函数,接收一个指向字符串的指针,表示要删除的磁盘驱动器的盘符。然后,函数将盘符转换为设备名称,使用 DefineDosDeviceA 函数将其从系统中移除。接着,函数使用 DeleteVolumeMountPointA 函数删除卷加载点。最后,main 函数调用 DeleteVolume 函数四次,移除了 C:、D:、E:、F: 四个磁盘驱动器。

#include <iostream>
#include <Windows.h>

// 移除指定盘符
BOOL DeleteVolume(char* lpszDriver)
{
  // 将盘符和Dos设备路径移除
  char szDeviceName[MAX_PATH] = { 0 };
  strcpy(szDeviceName, lpszDriver);
  szDeviceName[2] = '\0';
  if (!DefineDosDeviceA(DDD_REMOVE_DEFINITION, szDeviceName, NULL))
  {
    return FALSE;
  }

  // 卸载卷加载点
  if (!DeleteVolumeMountPointA(lpszDriver))
  {
    return FALSE;
  }
  return TRUE;
}

int main(int argc, char *argv[])
{
  DeleteVolume((char*)"C:");
  DeleteVolume((char *)"D:");
  DeleteVolume((char*)"E:");
  DeleteVolume((char*)"F:");

    return 0;
}

11.9.5 输出磁盘分区表

如下代码,用于读取和分析Windows系统上第一个物理硬盘的主引导记录MBR。代码中定义了几个数据结构来表示MBR及其组件,包括引导记录、磁盘分区表和磁盘签名,ShowMbr使用ReadFile函数从硬盘读取MBR数据,然后以十六进制格式逐字节打印MBR数据。AnalysMbr函数提取并分析MBR数据,打印出引导记录、磁盘签名和分区表信息。

主函数中使用CreateFileA打开第一个物理硬盘,使用ShowMbr函数读取MBR数据,使用AnalystMbr函数分析MBR数据,然后使用CloseHandle函数关闭文件句柄,此段代码读者在编译时需采用64位模式编译。

#include <iostream>
#include <Windows.h>

// 定义数据结构体
#define BOOTRECORDSIZE 440
typedef struct _BOOTRECORD
{
  unsigned char BootRecore[BOOTRECORDSIZE];
}BOOTRECORD, * PBOOTRECORD;

#define DPTSIZE 64
typedef struct _DPT
{
  unsigned char Dpt[DPTSIZE];
}DPT, * PDPT;

#define DPTNUMBER 4
typedef struct _DP
{
  unsigned char BootSign;     // 引导标志
  unsigned char StartHsc[3];
  unsigned char PatitionType;   // 分区类型
  unsigned char EndHsc[3];
  ULONG SectorsPreceding;     // 本分去之前使用的扇区数
  ULONG SectorsInPatition;    // 分区的总扇区数
}DP, * PDP;

typedef struct _MBR
{
  BOOTRECORD BootRecord;      // 引导程序
  unsigned char ulSigned[4];    // windows磁盘签名
  unsigned char sReserve[2];    // 保留位
  DPT Dpt;            // 分区表
  unsigned char EndSign[2];   // 结束标志
}MBR, * PMBR;

void ShowMbr(HANDLE hFile, PMBR pMbr)
{
  DWORD dwTemp = 0;
  ::ReadFile(hFile, (LPVOID)pMbr, sizeof(MBR), &dwTemp, NULL);
  for (int i = 0; i < 512; i++)
  {
    printf("%2x ", ((BYTE*)pMbr)[i]);
    if (0 == ((i + 1) % 16))
    {
      printf("\r\n");
    }
    else if (0 == ((i + 1) % 8))
    {
      printf("   ");
    }
  }
}

void AnalysMbr(MBR Mbr)
{
  printf("\r\n引导记录:\r\n");

  for (int i = 0; i < BOOTRECORDSIZE; i++)
  {
    printf("%2x ", Mbr.BootRecord.BootRecore[i]);
    if (0 == ((i + 1) % 16))
    {
      printf("\r\n");
    }
    else if (0 == ((i + 1) % 8))
    {
      printf("   ");
    }
  }

  printf("\r\n磁盘签名:\r\n");
  for (int i = 0; i < 4; i++)
  {
    printf("%02x ", Mbr.ulSigned[i]);
  }

  printf("\r\n解析分区表:\r\n");
  for (int i = 0; i < DPTSIZE; i++)
  {
    printf("%02x ", Mbr.Dpt.Dpt[i]);
    if (0 == ((i + 1) % 16))
    {
      printf("\r\n");
    }
    else if (0 == ((i + 1) % 8))
    {
      printf("   ");
    }
  }

  printf("\r\n");

  PDP pDp = (PDP) & (Mbr.Dpt.Dpt);
  for (int i = 0; i < DPTNUMBER; i++)
  {
    printf("引导标识:%02x ", pDp[i].BootSign);
    printf("分区类型:%02x ", pDp[i].PatitionType);
    printf("\r\n");
    printf("本分区之前扇区数:%d ", pDp[i].SectorsPreceding);
    printf("本分区的总扇区数:%d", pDp[i].SectorsInPatition);
    printf("\r\n");
    printf("该分区的大小:%f\r\n", (double)pDp[i].SectorsInPatition / 1024 / 1024 * 512 / 1024 / 1024);
    printf("\r\n");
  }

  printf("结束标志:\r\n");
  for (int i = 0; i < 2; i++)
  {
    printf("%02x ", Mbr.EndSign[i]);
  }
  printf("\r\n");
}

int main(int argc, char* argv[])
{
  // 打开物理硬盘设备
  HANDLE hFile = ::CreateFileA("\\\\.\\PhysicalDrive0",
    GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL);
  if (INVALID_HANDLE_VALUE == hFile)
  {
    return -1;
  }

  MBR Mbr = { 0 };
  ShowMbr(hFile, &Mbr);
  AnalysMbr(Mbr);
  CloseHandle(hFile);
  return 0;
}

标签:return,11.9,space,int,char,printf,磁盘,操作
From: https://www.cnblogs.com/LyShark/p/17843170.html

相关文章

  • Docker开始收费了,开始转学podman【第一篇podman容器的安装和基本操作】
    podman什么是Podman?Podman是无守护程序容器引擎,用于在Linux系统上开发,管理和运行OCI容器。容器可以以root用户或无根模式运行。简而言之:`aliasdocker=podman`。Podman(PodManager)是一个功能齐全的容器引擎,它是一个简单的无守护工具。Podman提供了一个类似Docker-CLI的命令......
  • 【5.0】Python中级之文件操作
    【一】文本处理引入应用程序运行过程中产生的数据最先都是存放于内存中的若想永久保存下来,必须要保存于硬盘中。应用程序若想操作硬件必须通过操作系统而文件就是操作系统提供给应用程序来操作硬盘的虚拟概念用户或应用程序对文件的操作,就是向操作系统发起调用,然后由操作系统......
  • 位操作运算符
    ......
  • c语言学习 - 逗号表达式及操作符
    条件操作符(三目操作数)exp1?exp2:exp3;若exp1的结果为真,则exp2是整个表达式的结果若exp1为假,则执行exp3作为整个表达式的结果赋值z++为先赋值再自增。++z为先自增再赋值。......
  • 什么是 Windows 操作系统的 DLL 文件
    .dll文件指的是动态链接库(DynamicLinkLibrary)文件。这些文件包含可被程序在运行时调用的代码和数据。它们是Windows操作系统中重要的组成部分,允许程序共享资源,提高效率并降低重复编码的需要。.dll文件允许程序模块化,以便多个应用程序可以共享它们,这样便于维护和更新。在本文中,我......
  • 什么是 Windows 操作系统 DLL 文件的 Side-by-Side Assemblies 技术
    .dll文件是Windows操作系统中的一种重要文件类型。全名为“动态链接库”(DynamicLinkLibraries),它包含了一些可以由多个程序共享的代码和数据。这使得在Windows下的开发者可以将一些公共的功能和数据集中到一些.dll文件中,而这些功能和数据可以被任何需要的程序所调用和使用......
  • linux环境安装可操作图库语言Gremlin的图框架HugeGraph
    原创/朱季谦 若你还没接触过图数据库,可能看到这个概念时,会比较蒙蔽。图是什么?图数据库又是什么?首先,在数据结构中,图是一种由顶点(vertex)集合及顶点间关系集合组成的一种非线性数据结构。而图数据库,则是以图这种具有点边结构来增、删、改、查之类操作的NoSQL数据库,它特别擅长处理大数......
  • win10注册表的备份与恢复;对“未将所有数据都成功写入到注册表中。某些项是由系统或其
    为什么要备份注册表呢?现在网络上的软件下载渠道良莠不齐,一不小心就给你一个全家桶服务,而仅仅是通过控制面板将它们卸载是删不干净的,鬼知道它们在电脑的注册表上留下了什么。所以在从不知名网站下载一些软件之前,对注册表进行备份,若出了什么问题,事后对注册表进行恢复是最便捷的方式了......
  • Docker部署Excalidraw | 一个功能齐全、操作简单的画板
    一、介绍界面简洁,交互细致,上手简单,操作习惯和大部分制图软件相似免注册,支持中文界面,打开浏览器就能开始画图支持众多键盘快捷键操作,配合鼠标能快速画图(适配触摸屏)内容安全受保护,Excalidraw采用端到端加密,绘图内容不会上传到服务器支持通过网页链接共享协作二、部署Excalid......
  • Docker部署Excalidraw | 一个功能齐全、操作简单的画板
    一、介绍界面简洁,交互细致,上手简单,操作习惯和大部分制图软件相似免注册,支持中文界面,打开浏览器就能开始画图支持众多键盘快捷键操作,配合鼠标能快速画图(适配触摸屏)内容安全受保护,Excalidraw采用端到端加密,绘图内容不会上传到服务器支持通过网页链接共享协作二、部署Excalid......