#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <windows.h>
#pragma pack(1)
#define MAX_MBR_PARTITIONS 4
#define MBR_DISK_SIGNATURE_OFFSET 440
#define MBR_DISK_PPT_OFFSET 446
#define MBR_SIGNATURE_OFFSET 510
//
// MBR Partition Entry
//
typedef struct {
UINT8 BootIndicator;
UINT8 StartHead;
UINT8 StartSector;
UINT8 StartTrack;
UINT8 OSType;
UINT8 EndHead;
UINT8 EndSector;
UINT8 EndTrack;
UINT32 StartingLBA;
UINT32 SizeInLBA;
} MBR_PARTITION_RECORD;
//
// MBR Partition table
//
typedef struct {
UINT8 BootCode[440];
UINT32 UniqueMbrSignature;
UINT16 Unknown;
MBR_PARTITION_RECORD PartitionRecord[MAX_MBR_PARTITIONS];
UINT16 Signature;
} MASTER_BOOT_RECORD;
#pragma pack()
#define MBR_SIGNATURE 0xAA55
#define EXTENDED_DOS_PARTITION 0x05
#define EXTENDED_WINDOWS_PARTITION 0x0F
BOOL ReadMBR(LPVOID *pBuffer)
{
HANDLE hDevice;
DWORD dwSize;
DWORD dwOverRead;
BOOL bRet = TRUE;
hDevice = CreateFile(TEXT("\\\\.\\PhysicalDrive2"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("Open \\\\.\\PhysicalDrive0 failed. Error=%u\n", GetLastError());
return FALSE;
}
if (!DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL)) {
CloseHandle(hDevice);
printf("FSCTL_LOCK_VOLUME \\\\.\\PhysicalDrive0 failed. Error=%u\n", GetLastError());
return FALSE;
}
DISK_GEOMETRY Geometry;
if (!DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &Geometry, sizeof(DISK_GEOMETRY), &dwSize, NULL)) {
bRet = FALSE;
printf("IOCTL_DISK_GET_DRIVE_GEOMETRY \\\\.\\PhysicalDrive0 failed. Error=%u\n", GetLastError());
goto _out;
}
*pBuffer = (LPVOID)GlobalAlloc(GPTR, Geometry.BytesPerSector);
if (*pBuffer) {
if (!ReadFile(hDevice, *pBuffer, Geometry.BytesPerSector, &dwOverRead, NULL)) {
printf("ReadFile \\\\.\\PhysicalDrive0 %u bytes failed. Error=%u\n", Geometry.BytesPerSector, GetLastError());
bRet = FALSE;
}
}
_out:
DeviceIoControl(hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
CloseHandle(hDevice);
return bRet;
}
BOOL WriteMBR(LPVOID pBuffer, DWORD nNumberOfBytesToWrite)
{
HANDLE hDevice;
DWORD dwBytesReturned = 0;
DWORD dwNumberOfBytesWritten = 0;
BOOL bRet = TRUE;
if (!pBuffer || IsBadReadPtr(pBuffer, nNumberOfBytesToWrite)){
return FALSE;
}
hDevice = CreateFile(TEXT("\\\\.\\PhysicalDrive2"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("Open \\\\.\\PhysicalDrive2 failed. Error=%u\n", GetLastError());
return FALSE;
}
if (!DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL)) {
CloseHandle(hDevice);
printf("FSCTL_LOCK_VOLUME \\\\.\\PhysicalDrive2 failed. Error=%u\n", GetLastError());
return FALSE;
}
DISK_GEOMETRY pdg;
if (!DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &pdg, sizeof(DISK_GEOMETRY), &dwBytesReturned, NULL)) {
bRet = FALSE;
printf("IOCTL_DISK_GET_DRIVE_GEOMETRY \\\\.\\PhysicalDrive2 failed. Error=%u\n", GetLastError());
goto _out;
}
printf("Write %u bytes to \\\\.\\PhysicalDrive2\n", pdg.BytesPerSector);
if (nNumberOfBytesToWrite != pdg.BytesPerSector) {
bRet = FALSE;
printf("\\\\.\\PhysicalDrive2 nNumberOfBytesToWrite %u != BytesPerSector %u.\n",
nNumberOfBytesToWrite, pdg.BytesPerSector);
goto _out;
}
if (!WriteFile(hDevice, pBuffer, pdg.BytesPerSector, &dwNumberOfBytesWritten, NULL)) {
printf("WriteFile \\\\.\\PhysicalDrive2 %u bytes failed. Error=%u\n", pdg.BytesPerSector, GetLastError());
bRet = FALSE;
}
_out:
DeviceIoControl(hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
CloseHandle(hDevice);
return bRet;
}
int main(int argc, char **argv)
{
LPVOID lpMBRBuffer = NULL;
UINT nIdx = 0x1BE;
UINT nCnt = 0;
UCHAR *pBuf = NULL;
MASTER_BOOT_RECORD *lpMbr = NULL;
if (ReadMBR(&lpMBRBuffer)){
pBuf = (UCHAR *)lpMBRBuffer;
lpMbr = (MASTER_BOOT_RECORD *)lpMBRBuffer;
for (; nIdx < 0x1FE; nIdx ++){
printf("%02X ", pBuf[nIdx]);
nCnt ++;
if (nCnt >= 0x10){
nCnt = 0;
printf("\n");
}
}
for (nIdx = 0; nIdx < MAX_MBR_PARTITIONS; nIdx ++){
printf("Part %u Type 0x%x\n", nIdx + 1, lpMbr->PartitionRecord[nIdx].OSType);
}
lpMbr->PartitionRecord[1].OSType = 0x5;
WriteMBR(pBuf, sizeof(MASTER_BOOT_RECORD));
GlobalFree(lpMBRBuffer);
lpMBRBuffer = NULL;
}
printf("*******************************************\n");
if (ReadMBR(&lpMBRBuffer)){
pBuf = (UCHAR *)lpMBRBuffer;
lpMbr = (MASTER_BOOT_RECORD *)lpMBRBuffer;
nIdx = 0x1BE;
nCnt = 0;
for (; nIdx < 0x1FE; nIdx ++){
printf("%02X ", pBuf[nIdx]);
nCnt ++;
if (nCnt >= 0x10){
nCnt = 0;
printf("\n");
}
}
for (nIdx = 0; nIdx < MAX_MBR_PARTITIONS; nIdx ++){
printf("Part %u Type 0x%x\n", nIdx + 1, lpMbr->PartitionRecord[nIdx].OSType);
}
GlobalFree(lpMBRBuffer);
lpMBRBuffer = NULL;
}
return 0;
}
编译
执行结果:
参考:
http://en.wikipedia.org/wiki/Master_boot_record
http://thestarman.pcministry.com/asm/mbr/index.html
http://en.wikipedia.org/wiki/Disk_partitioning
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363986(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363979(v=vs.85).aspx