相关MBR结构定义头文件
</pre><pre name="code" class="cpp">//备注: UCHAR占1字节、ULONG占4字节、一个扇区等于512字节
#pragma pack(1) //字节对齐
#define BOOTRECORDSIZE 440
#define PARTITIONTABLE 4
//分区表结构
//typedef struct _PARTITION_ENTRY{
// UCHAR BootSign; //引导标志(是否被激活)
// UCHAR StartHsc[3]; //包含起始磁头、扇区、柱面(Head、Sector、Cylinder H\S\C)
// UCHAR PartitionType; //分区类型描述
// UCHAR EndHsc[3]; //包含结束磁头、扇区、柱面
// ULONG SectorsPrecedingPartiton; //本分区之前使用的扇区数
// ULONG SectorsInPartition; //分区的总扇区数
//}PARTITION_ENTRY, *PPARTITION_ENTRY;
typedef struct _PARTITION_ENTRY{
UCHAR BootSign; //引导标志(是否被激活)
UCHAR StartHead; //开始磁头 Head
USHORT StartSC; //开始扇区、柱面 Sector、Cylinder (H\S\C描述)
UCHAR PartitionType; //分区类型描述
UCHAR EndHead; //结束磁头
USHORT EndSC; //结束扇区、柱面
ULONG SectorsPrecedingPartiton; //本分区之前使用的扇区数
ULONG SectorsInPartition; //分区的总扇区数
}PARTITION_ENTRY, *PPARTITION_ENTRY;
//引导区MBR结构 512字节
typedef struct _MBR_SECTOR{
UCHAR BootRecord[BOOTRECORDSIZE]; //引导程序 440byte
ULONG DiskSignatrue; //磁盘 4byte
USHORT NoneDisk; //占位 2byte
PARTITION_ENTRY Partition[PARTITIONTABLE]; //分区表结构 64byte
USHORT Signatrue; //结束标志 2byte
}MBR_SECTOR, *PMBR_SECTOR;
//读取MBR
BOOL ReadMbr(HANDLE hDevice,PMBR_SECTOR _pReadMbr);
//读取EBR
BOOL ReadEbr(HANDLE hDevice, ULONG uAbsolutePtBase,ULONG uOffsetPt, PMBR_SECTOR _pReadEbr);//偏移基数
//解析MBR填充到列表
ULONG ParseMbrToListBox(HWND hWnmd, MBR_SECTOR _ReadMbr, BOOL& bHaveExtented);
//解析EBR填充到列表
ULONG ParseEbrToListBox(HWND hWnmd, MBR_SECTOR _ReadEbr);
//打印结束符
void PrintEnd(MBR_SECTOR _ReadMbrOrEbr);
#pragma pack()
</pre><pre name="code" class="cpp">Win32窗口交互相关定义
#pragma once
#include "resource.h"
#include <windef.h>
//LISTBOX
#define LISTBOX_DELETEALLITEM(hWnd) SendMessageW(hWnd,LB_RESETCONTENT,0,0)
#define LISTBOX_ADDSTRING(hWnd,wstr) SendMessageW(hWnd,LB_ADDSTRING,0,(LPARAM)wstr)
#define LISTBOX_GETCOUNT(hWnd) SendMessageW(hWnd,LB_GETCOUNT,0,0)
//
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
//
//创建静态标签
HWND CrateStaticForMainWnd(HWND hWnd, LPWSTR lpStrText, LONG lStyle, int x, int y, int cx, int cy);
//创建按钮
void CreateButtonForMainWnd(HWND hWnd, LPWSTR lpStrText, UINT uID, LONG lStyle, int x, int y, int cx, int cy);
//创建列表框
HWND CreateListBoxForMainWnd(HWND hWnd, LPWSTR lpStrText, UINT uID, LONG lStyle, int x, int y, int cx, int cy);
//设置默认字体
void SetDefaultFont(HWND& hWnd);
//添加文本
void AddStringForListBox(HWND hWnd, LPWSTR lpStrText = L"");
//获取总共项
int GetItemCountForListBox(HWND hWnd);
//删除所有项
void DeleteAllItemForListBox(HWND hWnd);
//删除单个项
void DeleteItemForListBox(HWND hWnd, int iIndex);
//
//响应WM_CREATE消息
void OnCreate(HWND& hWnd);
//按钮IDC_BTN_OUTPUT被单击
void OnBtnRead1Click();
//删除按钮
void OnBtnRead2Click();
Win32 窗口实现
// MastBoot.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "MastBoot.h"
#include "mbr.h"
#include <map>
#include <Winioctl.h>
using namespace std;
#define MAX_LOADSTRING 100
#define MAINWND_DEFAULT_WIDTH 300
#define MAINWND_DEFAULT_HEIGHT 500
#define IDC_BTN_READ1 10001
#define IDC_LISTBOX_INFO 10002
#define IDC_BTN_READ2 10003
// 全局变量:
HINSTANCE hInst; //当前实例
TCHAR szTitle[MAX_LOADSTRING]; //标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; //主窗口类名
map<HANDLE, RECT> mapControls; //控件集合
HWND hWndListBox; //
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;
// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_MASTBOOT, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MASTBOOT));
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MASTBOOT));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MASTBOOT);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, MAINWND_DEFAULT_WIDTH, MAINWND_DEFAULT_HEIGHT, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
OnCreate(hWnd);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDC_BTN_READ1:
OnBtnRead1Click();
break;
case IDC_BTN_READ2:
OnBtnRead2Click();
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
void SetDefaultFont(HWND& hWnd)
{
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfHeight = 15;
lf.lfWeight = 12;
memcpy(lf.lfFaceName, L"Arial", sizeof(L"Arial"));
HFONT hFont = CreateFontIndirect(&lf);
SendMessageW(hWnd, WM_SETFONT, (WPARAM)hFont, 0);
}
void AddStringForListBox(HWND hWnd, LPWSTR lpStrText)
{
SendMessageW(hWnd, LB_ADDSTRING, 0, (LPARAM)lpStrText);
}
int GetItemCountForListBox(HWND hWnd)
{
return SendMessageW(hWnd, LB_GETCOUNT, 0, 0);
}
void DeleteItemForListBox(HWND hWnd, int iIndex)
{
SendMessageW(hWnd, LB_DELETESTRING, (WPARAM)iIndex, 0);
}
void DeleteAllItemForListBox(HWND hWnd)
{
SendMessageW(hWnd, LB_RESETCONTENT, 0, 0);
}
HWND CrateStaticForMainWnd(HWND hWnd, LPWSTR lpStrText, LONG lStyle, int x, int y, int cx, int cy)
{
HWND hWndStatic = CreateWindowW(L"STATIC",
lpStrText,
lStyle,
x, y, cx, cy,
hWnd,
NULL,
hInst,NULL);
if (hWndStatic == NULL)
{
return hWndStatic;
}
//设置默认字体
SetDefaultFont(hWndStatic);
RECT rect = {x,y,cx,cy};
mapControls.insert(pair<HWND, RECT>(hWndStatic, rect));
return hWndStatic;
}
void CreateButtonForMainWnd(HWND hWnd, LPWSTR lpStrText, UINT uID, LONG lStyle, int x, int y, int cx, int cy)
{
HWND hWndButton = CreateWindowW(L"BUTTON",
lpStrText,
lStyle,
x, y, cx, cy,
hWnd,
(HMENU)uID,
hInst, NULL);
if (hWndButton == NULL)
{
return;
}
//设置默认字体
SetDefaultFont(hWndButton);
RECT rect = { x, y, cx, cy };
mapControls.insert(pair<HWND, RECT>(hWndButton, rect));
}
HWND CreateListBoxForMainWnd(HWND hWnd, UINT uID, LONG lStyle, int x, int y, int cx, int cy)
{
HWND hWndListBox = CreateWindowW(L"LISTBOX",
NULL,lStyle,
x, y, cx, cy,
hWnd,
(HMENU)uID,
hInst, NULL);
if (hWndListBox == NULL)
{
return NULL;
}
//设置默认字体
SetDefaultFont(hWndListBox);
RECT rect = { x, y, cx, cy };
mapControls.insert(pair<HWND, RECT>(hWndListBox, rect));
return hWndListBox;
}
void OnCreate(HWND& hWnd)
{
//创建一个调试按钮
CreateButtonForMainWnd(hWnd, L"读取MBR1", IDC_BTN_READ1, WS_CHILD | WS_VISIBLE, 10, 20, 70, 30);
//创建一个删除按钮
CreateButtonForMainWnd(hWnd, L"读取MBR2", IDC_BTN_READ2, WS_CHILD | WS_VISIBLE, 90, 20, 70, 30);
//创建一个ListBox
hWndListBox = CreateListBoxForMainWnd(hWnd, IDC_LISTBOX_INFO, LBS_NOTIFY | WS_BORDER | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE | WS_VSCROLL,
10, 60, 260, 320);
}
void OnBtnRead1Click()
{
}
BOOL ReadMbr(HANDLE hDevice,PMBR_SECTOR _pReadMbr)
{
DWORD dwLeng = 512,dwCount = 0;
//清空结构
memset(_pReadMbr, 0, 512);
//锁定目标磁盘
DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwCount, NULL);
//读取MBR数据
BOOL bCheck = ReadFile(hDevice, _pReadMbr, 512, &dwLeng, NULL);
//解锁目标
DeviceIoControl(hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwCount, NULL);
return bCheck;
}
BOOL ReadEbr(HANDLE hDevice, ULONG uAbsolutePtBase, ULONG uOffsetPt, PMBR_SECTOR _pReadEbr)
{
DWORD dwLeng = 512, dwCount = 0;
//清空结构
memset(_pReadEbr, 0, 512);
//计算读取位置
LARGE_INTEGER EPOffsetByte;
//扇区绝对地址+偏移地址
EPOffsetByte.QuadPart = ((DWORD64)uAbsolutePtBase + uOffsetPt) * 512;
//锁定目标磁盘
DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwCount, NULL);
//移动读取位置
SetFilePointer(hDevice, EPOffsetByte.LowPart, &EPOffsetByte.HighPart, FILE_BEGIN); // SetFilePointerEx(hDevice, EPOffsetByte, 0, FILE_BEGIN);
//读取EBR数据
BOOL bCheck = ReadFile(hDevice, _pReadEbr, 512, &dwLeng, NULL);
//解锁目标
DeviceIoControl(hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwCount, NULL);
return bCheck;
}
ULONG ParseMbrToListBox(HWND hwnd, MBR_SECTOR _ReadMbr,BOOL& bHaveExtented)
{
WCHAR wstr[64] = { 0 }; //临时缓冲区
ULONG uAbsolutePt = 0; //扇区绝对起始位置
bHaveExtented = FALSE; //是否存在扩展分区
for (int i = 0; i < PARTITIONTABLE; i++)
{
memset(wstr, 0, 64);
wsprintf(wstr, L"引导标志:%02X", _ReadMbr.Partition[i].BootSign);
LISTBOX_ADDSTRING(hwnd, wstr);
memset(wstr, 0, 64);
wsprintf(wstr, L"开始磁头:%d", _ReadMbr.Partition[i].StartHead);
LISTBOX_ADDSTRING(hwnd, wstr);
memset(wstr, 0, 64);
wsprintf(wstr, L"起始扇区:%d", _ReadMbr.Partition[i].StartSC & 63);
LISTBOX_ADDSTRING(hwnd, wstr);
memset(wstr, 0, 64);
wsprintf(wstr, L"起始柱面:%d", _ReadMbr.Partition[i].StartSC >> 6);
LISTBOX_ADDSTRING(hwnd, wstr);
memset(wstr, 0, 64);
wsprintf(wstr, L"分区类型:%02X", _ReadMbr.Partition[i].PartitionType);
LISTBOX_ADDSTRING(hwnd, wstr);
memset(wstr, 0, 64);
wsprintf(wstr, L"结束磁头:%d", _ReadMbr.Partition[i].EndHead);
LISTBOX_ADDSTRING(hwnd, wstr);
memset(wstr, 0, 64);
wsprintf(wstr, L"结束扇区:%d", _ReadMbr.Partition[i].EndSC & 63);
LISTBOX_ADDSTRING(hwnd, wstr);
memset(wstr, 0, 64);
wsprintf(wstr, L"结束柱面:%d", _ReadMbr.Partition[i].EndSC >> 6);
LISTBOX_ADDSTRING(hwnd, wstr);
memset(wstr, 0, 64);
wsprintf(wstr, L"之前使用扇区数:%d", _ReadMbr.Partition[i].SectorsPrecedingPartiton);
LISTBOX_ADDSTRING(hwnd, wstr);
memset(wstr, 0, 64);
wsprintf(wstr, L"总扇区数:%d", _ReadMbr.Partition[i].SectorsInPartition);
LISTBOX_ADDSTRING(hwnd, wstr);
//插入换行符
LISTBOX_ADDSTRING(hwnd, L"");
//表示第没有扩展分区了
if (_ReadMbr.Partition[i].PartitionType == 0x00)
{
break;
}
//如果为0x05或0x0F表明该分区为扩展分区 不处理第三和第四分区表
if (_ReadMbr.Partition[i].PartitionType == 0x05 || _ReadMbr.Partition[i].PartitionType == 0x0F)
{
//保存0扇区到扩展分区的绝对扇区
uAbsolutePt = _ReadMbr.Partition[i].SectorsPrecedingPartiton;
//设置为扩展分区
bHaveExtented = TRUE;
break;
}
}
return uAbsolutePt;
}
void OnBtnRead2Click()
{
WCHAR szDevicename[64] = { 0 }; //临时路径换成区
MBR_SECTOR _ReadMbr,_ReadEbr; //MBR、EBR结构
BOOL bHaveExtented; //是否包含扩展分区
wsprintf(szDevicename, L"\\\\.\\PHYSICALDRIVE0");
//打开磁盘
HANDLE hDevice = CreateFileW(szDevicename,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
//判断磁盘是否打开成功
if (hDevice == INVALID_HANDLE_VALUE)
{
WCHAR lpwstrError[50] = { 0 };
wsprintf(lpwstrError, L"打开失败,错误:%d", GetLastError());
MessageBox(NULL, lpwstrError, L"", MB_OK);
return;
}
//读取MBR
ReadMbr(hDevice, &_ReadMbr);
//解析MBR数据并填充到LIST_BOX中
ULONG uAbsolutePtBase = ParseMbrToListBox(hWndListBox, _ReadMbr,bHaveExtented);
ULONG uOffsetPt = 0;
//打印出结束符
PrintEnd(_ReadMbr);
//循环读取扩展分区(EBR)
while (bHaveExtented)
{
//清空EBR
memset(&_ReadEbr, 0, sizeof(_MBR_SECTOR));
//读取EBR
BOOL bCheck = ReadEbr(hDevice, uAbsolutePtBase, uOffsetPt, &_ReadEbr);
//填充EBR
uOffsetPt = ParseMbrToListBox(hWndListBox, _ReadEbr, bHaveExtented);
//打印出结束符
PrintEnd(_ReadEbr);
}
//关闭句柄
CloseHandle(hDevice);
}
void PrintEnd(MBR_SECTOR _ReadMbrOrEbr)
{
WCHAR wstr[63] = { 0 }; //临时缓冲区
wsprintf(wstr, L"%02X", _ReadMbrOrEbr.Signatrue);
LISTBOX_ADDSTRING(hWndListBox, wstr);
LISTBOX_ADDSTRING(hWndListBox, L"");
}