Windows上面读磁盘分区表

2024-09-04 22:48
文章标签 windows 磁盘分区 上面

本文主要是介绍Windows上面读磁盘分区表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 概述

在 GPT分区表 一文中,讲解了MBR分区表的一些概念。本文进一步给出了Windows系统上读取MBR的示例代码,以及MBR的具体数据,可进一步加深对MBR的理解。


在参考网上一些文章&代码的基础上,本文给出了下面的展示MBR的示例代码;同时最后针对几个典型问题,给出了一些解释和参考文档。


2. 代码

下面是代码:

/*** ref: http://noyesno.net/page/it/20100701-172* */
#include <stdio.h>
#include <windows.h>struct CHS {unsigned int header;unsigned int sector; unsigned int cylinder;
};struct partition_record {unsigned char boot_indicator;unsigned char os_type;struct CHS starting_chs;struct CHS ending_chs;unsigned int starting_LBA;unsigned int size_in_LBA;
};void dump_partition_record(const partition_record& record) {const double DISK_SECTOR_SIZE = 512.0;const size_t GB = 1024 * 1024 * 1024;printf("\tboot indicator: 0x%02x\n""\tOS Type: 0x%02x\n""\tStarting CHS: (%d, %d, %d)\n""\tEnding_CHS: (%d, %d, %d)\n""\tSize in LBA: %d\n""\tSize:%.2f\n\n",record.boot_indicator, record.os_type, record.starting_chs.cylinder,record.starting_chs.header,record.starting_chs.sector,record.ending_chs.cylinder,record.ending_chs.header,record.ending_chs.sector,record.size_in_LBA,record.size_in_LBA * DISK_SECTOR_SIZE / GB);
}// transform the 16-bytes buffer to partition record
void get_partition_record(unsigned char buffer[], partition_record& record) {record.boot_indicator = buffer[0];record.starting_chs.header = buffer[1];record.starting_chs.sector = buffer[2] & 0x3f;record.starting_chs.cylinder = (((buffer[2] & 0xff) >> 6) << 8) + buffer[3];record.os_type = buffer[4];record.ending_chs.header = buffer[5];record.ending_chs.sector = buffer[6] & 0x3f;record.ending_chs.cylinder = (((buffer[6] & 0xff) >> 6) << 8) + buffer[7];record.size_in_LBA = *(unsigned int*)(buffer + 12);
}void read_mbr(const char *devname){HANDLE hDevice = CreateFile(devname, GENERIC_READ,   FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);  if (hDevice == INVALID_HANDLE_VALUE){  printf("Open %s failed, the error code is %d.\n", devname, GetLastError());  return;  }DWORD dwRead = 0;  const size_t DISK_SECTOR_SIZE = 512;unsigned char buffer[DISK_SECTOR_SIZE];  BOOL bSuccess = ReadFile(hDevice, buffer, DISK_SECTOR_SIZE, &dwRead, NULL);  CloseHandle(hDevice);if ( !bSuccess || DISK_SECTOR_SIZE != dwRead)  {  printf("Error: read error! Read size = %d\n",  dwRead);  return; }  size_t i, j;printf("%10s 0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F \n", " ");  for (i = 0; i < 32; i++) {  printf("%.8XH: ", i);  for (j = 0; j < 16; j++) {printf("%.2X ", buffer[i * 16 + j] & 0xFF);  }printf("\n");  }printf("====MBR Partition Entries====\n");partition_record record = {0};for(i = 0x01be; i < 0x01FE; i += 16){get_partition_record(buffer + i, record);dump_partition_record(record);}
}int main(int argc, char *argv[]){const char* LOG_FILE = "./log.txt";freopen(LOG_FILE, "a", stdout); setbuf(stdout, NULL);read_mbr("\\\\.\\PhysicalDrive0");return 0;
}

运行结果如下:

           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
00000000H: 33 FF BE 00 02 8E D7 BC 00 7A BB A0 07 8B CE 8E 
00000001H: DB 8E C3 F3 A4 EA 5D 00 A0 07 10 00 01 00 00 7A 
00000002H: 00 00 00 00 00 00 00 00 00 00 07 66 8B 55 08 B4 
00000003H: 42 C6 06 1F 00 7C 32 C0 66 89 16 22 00 BE 1A 00 
00000004H: B2 80 CD 13 0F 82 CD 00 81 3E FE 03 55 AA C3 AC 
00000005H: 0A C0 74 FA B4 0E BB 07 00 CD 10 EB F2 8B E9 8B 
00000006H: D9 C6 06 2A 00 0C BF EE 01 B9 04 00 38 6D 04 74 
00000007H: 37 E8 B7 FF 75 1F 66 B8 52 45 43 4F 66 39 06 03 
00000008H: 02 74 0C 66 39 06 F0 03 75 0B C6 06 2A 00 07 8B 
00000009H: DF C6 45 04 12 8A 45 04 3C 07 74 0A 3C 0B 74 06 
0000000AH: 24 F5 3C 04 75 02 8B EF 88 2D 83 EF 10 E2 BD 0B 
0000000BH: DB 74 3D 0B ED 74 39 8B FB F6 06 6D 01 04 75 76 
0000000CH: F6 06 6D 01 02 75 73 B4 11 CD 16 75 5C 8A 16 6C 
0000000DH: 01 0A D2 74 65 FE CA 78 17 36 8A 0E 6C 04 80 C1 
0000000EH: 12 B4 11 CD 16 75 42 36 3A 0E 6C 04 75 F3 EB E5 
0000000FH: 66 33 D2 E8 39 FF B1 04 BF BE 03 80 3D 80 74 5E 
00000010H: 83 C7 10 E2 F6 B1 04 BF BE 03 80 7D 04 00 75 4E 
00000011H: 83 C7 10 E2 F5 8B 36 70 01 E8 33 FF 8B 36 72 01 
00000012H: E8 2C FF B4 00 CD 16 CD 18 B4 10 CD 16 3C 72 74 
00000013H: 05 80 FC 85 75 BA 8B EF EB 07 F6 06 6D 01 10 74 
00000014H: 06 A0 2A 00 88 45 04 8B FD C6 05 80 80 26 6D 01 
00000015H: F9 66 33 D2 C6 06 1F 00 7A B4 43 E8 D8 FE E8 CA 
00000016H: FE 8B 36 6E 01 75 B2 EA 00 7C 00 00 01 11 76 01 
00000017H: 7B 01 82 01 87 01 45 72 72 32 00 0D 0A 45 72 72 
00000018H: 31 00 45 72 72 33 00 0D 0A 50 72 65 73 73 20 46 
00000019H: 31 31 20 66 6F 72 20 45 6D 65 72 67 65 6E 63 79 
0000001AH: 20 52 65 63 6F 76 65 72 79 20 00 73 20 61 20 6B 
0000001BH: 65 79 0D 0A 00 00 6C 01 32 F2 49 15 00 00 80 01 
0000001CH: 01 00 07 EF FF FF 3F 00 00 00 D0 88 81 1D 00 EF 
0000001DH: FF FF 07 EF FF FF 00 90 81 1D 00 60 07 1C 00 EF 
0000001EH: FF FF 07 EF FF FF 10 F1 88 39 80 57 AF 00 00 00 
0000001FH: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA 
====MBR Partition Entries====boot indicator: 0x80OS Type: 0x07Starting CHS: (0, 1, 1)Ending_CHS: (1023, 239, 63)Size in LBA: 495028432Size:236.05boot indicator: 0x00OS Type: 0x07Starting CHS: (1023, 239, 63)Ending_CHS: (1023, 239, 63)Size in LBA: 470245376Size:224.23boot indicator: 0x00OS Type: 0x07Starting CHS: (1023, 239, 63)Ending_CHS: (1023, 239, 63)Size in LBA: 11491200Size:5.48boot indicator: 0x00OS Type: 0x00Starting CHS: (0, 0, 0)Ending_CHS: (0, 0, 0)Size in LBA: 0Size:0.00

下图是实际的硬盘中各分区的数据:



3. 典型问题

3.1 Vista上返回错误码5

vista上访问硬件时会有权限问题,比如上面代码CreateFile()在IDE中执行失败,返回错误码5. 规避的方法就是直接在资源管理器中运行exe程序,并选择“以管理员身份运行”。


3.2 超过8GB的CHS表示形式

在MBR的每个分区记录(partition record, partition entry)中,CHS(Cylinder Header Sector)部分是3个字节,如此最大表示8G的磁盘空间(粗略计算:8x3=24, 每个扇区512字节, 512 * 2^24 = 8GB)。但现在的磁盘空间最少都是几百G,因此CHS无法表示出正确的取值。为此,MBR通常规定0xfeffff表示非法的CHS,或无效的CHS;但UEFI规范规定的是0xffffff表示无效值,但如同上面代码运行结果显示的,在示例代码运行的系统上,却是0xefffff表示无效取值。


在这种情况下,都取Partition Entry中的起始LBA(StartingLBA)、以及LBA个数(SizeInLBA)两个字段来计算每个分区的起始位置、以及该分区的实际大小。


相关的两个链接提及了chs的特殊取值:

  • gdisk - Interactive GUID partition table (GPT) manipulator
     
  • MBR/EBR Partition Tables :系统地介绍了分区表的概念,以及CHS的计算方法

3.3 把打印重定向到文件

在上面的示例代码中,main()一开始把标准输出重定向到一个文件中。可以参考Android源码bootable/recovery/recovery.cpp的main()函数:

int
main(int argc, char **argv) {time_t start = time(NULL);// If these fail, there's not really anywhere to complain...freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL);freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL);

关于如何下载Android源码,请参考 The steps for download android source code。

3.4 磁盘管理相关的知识、以及MSDN相关的API

  • 参考入口链接:http://msdn.microsoft.com/en-us/library/windows/desktop/aa363978%28v=vs.85%29.aspx


3.5 编码风格

Windows上面编码的风格和Linux及其他语言有相当大的差异,比如Windows的函数名是驼峰式、首字母大写;但Linux、以及STL等的命名均是小写字母、单词之间是下划线等风格。


为此,以上的示例代码主要侧重于Linux的编码习惯,如此会和Windows SDK API的风格存在差异。以此说明。

这篇关于Windows上面读磁盘分区表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1137257

相关文章

在 Windows 上部署 gitblit

在 Windows 上部署 gitblit 在 Windows 上部署 gitblit 缘起gitblit 是什么安装JDK部署 gitblit 下载 gitblit 并解压配置登录注册为 windows 服务 修改 installService.cmd 文件运行 installService.cmd运行 gitblitw.exe查看 services.msc 缘起

Windows如何添加右键新建菜单

Windows如何添加右键新建菜单 文章目录 Windows如何添加右键新建菜单实验环境缘起以新建`.md`文件为例第一步第二步第三步 总结 实验环境 Windows7 缘起 因为我习惯用 Markdown 格式写文本,每次新建一个.txt后都要手动修改为.md,真的麻烦。如何在右键新建菜单中添加.md选项呢? 网上有很多方法,这些方法我都尝试了,要么太麻烦,要么不凑效

Windows下Nginx的安装及开机启动

1、将nginx-1.16.1.zip解压拷贝至D:\web\nginx目录下。 2、启动Nginx,两种方法: (1)直接双击nginx.exe,双击后一个黑色的弹窗一闪而过。 (2)打开cmd命令窗口,切换到nginx目录下,输入命令 nginx.exe 或者 start nginx ,回车即可。 3、检查nginx是否启动成功。 直接在浏览器地址栏输入网址 http://lo

Windows环境利用VS2022编译 libvpx 源码教程

libvpx libvpx 是一个开源的视频编码库,由 WebM 项目开发和维护,专门用于 VP8 和 VP9 视频编码格式的编解码处理。它支持高质量的视频压缩,广泛应用于视频会议、在线教育、视频直播服务等多种场景中。libvpx 的特点包括跨平台兼容性、硬件加速支持以及灵活的接口设计,使其可以轻松集成到各种应用程序中。 libvpx 的安装和配置过程相对简单,用户可以从官方网站下载源代码

C++实现俄罗斯方块(Windows控制台版)

C++实现俄罗斯方块(Windows控制台版) 在油管上看到一个使用C++控制台编写的俄罗斯方块小游戏,源代码200多行,B站上也有相关的讲解视频,非常不错,值得学习。 B站讲解视频地址为:【百万好评】国外技术大神C++游戏编程实战教程,油管580W收藏,新手10小时入门,并快速达到游戏开发能力(中英字幕) B站 CSDN博主千帐灯无此声还为此写了一篇博客:C++实现俄罗斯方块(源码+详解),讲

Windows下php扩展开发c++动态库

PHP扩展开发,从零了解到初步完成一个小项目,经过三天的仔细研究,现整理如下 一、需求介绍 PHP扩展开发,调用自己之前的c++动态库,完成功能 二、项目之前 系统:windows xp  开发工具:vs 2008 web环境:apache2.4  PHP5.3.29-VC9-ts-x86 aphach和PHP 环境之前已经搭建完成 PHP源码:去官网http://www.php.n

OpenStack镜像制作系列4—Windows Server2019镜像

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录  CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作系

Windows与linux中docker的安装与使用

windos中安装使用docker 下载Docker_Desktop 安装包进入docker官网下载Docker_Desktop: https://www.docker.com/ 启用wsl 我们搜索“启用或关闭Windows功能”,打开后勾选适用于Linux的Windows 子系统 Docker_Desktop设置 出现Docker Engine stopped的解决

Windows 10 各版本

对应于服务选项的 Windows 10 当前版本 Version服务选项上市日期OS build最后修订日期1803半年频道7/10/201817134.1917/24/2018Microsoft 建议使用1803半年频道(定向)4/30/201817134.1917/24/20181709半年频道1/18/201816299.5797/24/20181709半年频道(定向)10/17/2017

Windows系统不关机故障的解决方法

当Windows系统出现不关机故障时,首先要查找引起Windows系统不关机的原因,然后根据 具体的故障原因采取相应的解决方法。   Windows系统不关机故障的解决方法如下。   1.检查所有正在运行的程序   检查运行的程序主要包括关闭任何在实模式下加载的TSR程序、关闭开机时从启动组自动启 动的程序、关闭任何非系统引导必需的第三方设备驱动程序。   检查运行的程序并停