C/C++编程解析硬盘分区信息

人狠话不多,直接上代码:

#include <windows.h>
#include <winioctl.h> //DDK驱动开发与控制
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define BufferLength 1024

//将四个连续字节存放的值转为int型
int transtoint(unsigned char a[])
			{
				int sum = 0;
				for(int i=0;i<4;i++){
					int m = a[i]/16;
					int n = a[i]%16;
					float len =16;
					//printf(" %d %d ",m,n);
					int temp1 = m*(pow(len,7-2*i));
					int temp2 = n*(pow(len,6-2*i));
					//printf(" %d ",temp);
					sum = sum+temp1+temp2;
				}
				return sum;
			}
//十六进制输出
void HexOutput(char* buf, size_t len)   
{ 
	unsigned char a = buf[0];
	printf("第一字节是:%x\n\n",a);
	printf("          第一部分(引导代码):\n\n");
	int flag = 0;
    for(size_t i=0; i<len; ++i)   
    {   
        unsigned char c = buf[i]; // must use unsigned char to print >128 value 
  
		flag++;
        if( c< 16)   
            printf("0%x ", c);     
        else    
            printf("%x ", c); 
  
		if (i == 445)
		{
			flag=0;
			printf("\n\n          第二部分(分区表):\n");
		}

		if (i == 509)
		{
			flag=0;
			printf("\n\n          第三部分(结束标志):\n");
		}
		if ((flag)%16 == 0)
			printf("\n");
    }

	printf("\n<-------------------分区表信息解析------------------->\n\n");
	printf("\n\n分区地址和大小分别为: \n\n");
	
	for(int m=445,rank=1;m<509;m+=16,rank++)
	{
		
		unsigned char fifth = buf[m+6];//取得第五位标志位
		if(fifth<16) //调整输出格式
			printf("第%d分区表标志位为: 0%x\n",rank,fifth);
		else 
			printf("第%d分区表标志位为: %x\n",rank,fifth);
		if(fifth == 0x00)//当第五位(标志位)是00时,代表分区表信息为空,无分区
		{
			printf(" 分区表为空\n\n");
		}
		else{
			unsigned char offsetadd[20]={0};
			printf("地址:");
			for(int n=m+12,t=0;n>m+8,t<4;n--,t++)
			{
				unsigned char temp = buf[n];
				if(temp<16)
					printf("  0%x  ",temp);
				else
					printf("  %x  ",temp);
				offsetadd[t] = buf[n];
			}
			//计算地址,转换为十进制扇区数LBA
			printf("\n");
			int tempadd = transtoint(offsetadd);
			printf("\n地址为: %d",tempadd);
			printf("\n\n");
			printf("大小:");
			for(int p=m+16,w=0;p>m+12,w<4;p--,w++)
			{
				unsigned char temp1 = buf[p];
				if(temp1<16)
					printf("  0%x  ",temp1);
				else
					printf("  %x  ",temp1);
				offsetadd[w] = buf[p];
			}
			//计算大小,转化为GB单位
			printf("\n");
			int tempsize = transtoint(offsetadd);
			printf("\n大小为: %d 扇区 = %d GB \n",tempsize,tempsize/2/1024/1024);
		}
		
		
	}
    printf("\n\n");   
}  

//函数:对主分区表进行解析,分别得到每个分区的偏移地址以及分区大小

BOOL GetDriveGeometry(DISK_GEOMETRY *pdg,int addr)
{
	HANDLE hDevice;               // 设备句柄
	BOOL bResult;                 // results flag
	DWORD junk;                   // discard resultscc
	char lpBuffer[BufferLength] = {0};


//通过CreateFile来获得设备的句柄
	hDevice = CreateFile(TEXT("\\\\.\\PhysicalDrive0"), // 设备名称,这里指第一块硬盘
						GENERIC_READ,                // no access to the drive
						FILE_SHARE_READ | FILE_SHARE_WRITE,  // share mode
						NULL,             // default security attributes
						OPEN_EXISTING,    // disposition
						0,                // file attributes
						NULL);            // do not copy file attributes
	if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
	{
		return (FALSE);
	}

//通过DeviceIoControl函数与设备进行IO
	bResult = DeviceIoControl(hDevice, // 设备的句柄
							  IOCTL_DISK_GET_DRIVE_GEOMETRY, // 控制码,指明设备的类型
								NULL, 0, // no input buffer
								pdg, 
								sizeof(*pdg),     // output buffer 输出,保存磁盘参数信息
								&junk,                 // # bytes returned
								(LPOVERLAPPED) NULL); // synchronous I/O
//主引导扇区的位置为0柱面0磁头1扇区
	//int BlockAddr = ( 0 * 256 + 0 ) * 63 + 1 - 1; //计算绝对地址
	//SetFilePointer(hDevice, (BlockAddr*512), NULL, FILE_BEGIN);
	LARGE_INTEGER offset;
	offset.QuadPart = (ULONGLONG)addr * (ULONGLONG)512;
	SetFilePointer(hDevice,offset.LowPart,&offset.HighPart,FILE_BEGIN);
	printf("错误类型代号:%ld\n\n",GetLastError());
    DWORD dwCB;
    BOOL bRet = ReadFile(hDevice,lpBuffer,512,&dwCB,NULL);
	//printf("%x\n\n",lpBuffer);
    HexOutput(lpBuffer,512);


	CloseHandle(hDevice);

	return bResult;
}
extern int add[20];
extern int disknum;
int main()
{
	DISK_GEOMETRY pdg;            // 保存磁盘参数的结构体
	BOOL bResult;                 // generic results flag
	ULONGLONG DiskSize;           // size of the drive, in bytes
	printf("<-----------------欢迎使用分区读取程序----------------->\n\n");
	bResult = GetDriveGeometry (&pdg,0);

	if (bResult) 
	{
		printf("柱面数 = %I64d\n", pdg.Cylinders); //柱面数
		printf("每柱面的磁道数 = %ld\n", (ULONG) pdg.TracksPerCylinder);//每柱面的磁道数
		printf("每磁道扇区数 = %ld\n", (ULONG) pdg.SectorsPerTrack);//每磁道扇区数
		printf("每扇区的字节数 = %ld\n", (ULONG) pdg.BytesPerSector); //每扇区的字节数
  
		DiskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *
					(ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;
  
		printf("磁盘大小 = %I64d (Bytes) = %I64d (Gb)\n", DiskSize,DiskSize / (1024 * 1024 * 1024));
	} 
	else 
	{
		printf ("GetDriveGeometry failed. Error %ld.\n", GetLastError ());
	}
	system("pause");
	return ((int)bResult);
}

运行结果类似于:
主分区
主分区
主分区
总硬盘