天天看点

使用DeviceIoControl读写磁盘MBR, 修改分区类型示例

#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;
}
           

编译

使用DeviceIoControl读写磁盘MBR, 修改分区类型示例

执行结果:

使用DeviceIoControl读写磁盘MBR, 修改分区类型示例

参考:

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

继续阅读