通过CreateFile来读取磁盘扇区的方法

测试程序包括两个测试方法,以#define SECTOR 开关进行相应的程序段测试,程序在XP + vc6 环境下测试通过,程序如下: 

#include "stdafx.h"

/* -------------------------------------------------------------------------- *
*
*
*    1   读取磁盘扇区
*
*
* -------------------------------------------------------------------------- */

#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <tchar.h>
#include <winioctl.h>

// 以CreateFile方式读取扇区开关
//#define SECTOR 

#ifdef SECTOR

VOID __cdecl _tmain (INT Argc, PTCHAR Argv[])
{
 TCHAR szName[MAX_PATH] = { 0 };
 HANDLE hDisk;
 
 //
 // 命令行参数可在Project Settings->Debug->Program arguments下指定 如:0 1
 //
 if (Argc != 3) {
  
  _tprintf(_T("Reads a sector on the disk/n/n"));
  _tprintf(_T("%s [disk number] [sector]/n"), Argv[0]);
  return;
 }
 
 _sntprintf(szName, sizeof(szName) / sizeof(szName[0]) - 1,
  _T("////.//Physicaldrive%d"), _ttoi(Argv[1]));
 
 //
 // 打开磁盘
 //
 hDisk = CreateFile(szName,
  GENERIC_READ,
  FILE_SHARE_READ,
  NULL,
  OPEN_EXISTING,
  NULL,
  0);
 
 if (hDisk != INVALID_HANDLE_VALUE)
 {
  
  // 磁盘的结构信息存在此结束中。
  /*
  typedef struct _DISK_GEOMETRY
  {
  LARGE_INTEGER Cylinders;    // 柱面数
  MEDIA_TYPE MediaType;       // 磁盘类型,见MSDN
  DWORD TracksPerCylinder;    // 每道柱面数
  DWORD SectorsPerTrack;      // 每道扇区数
  DWORD BytesPerSector;       // 每扇区字节数
  } DISK_GEOMETRY;
  */
  
  DISK_GEOMETRY diskGeometry;
  
  
  DWORD dwBytes = 0;
  
  //
  // 获得磁盘结构信息
  //
  if (DeviceIoControl(hDisk,
   IOCTL_DISK_GET_DRIVE_GEOMETRY,    // 调用了CTL_CODE macro宏
   NULL,
   0,
   &diskGeometry,
   sizeof(DISK_GEOMETRY),
   &dwBytes,
   NULL))
  {
   
   DWORD dwSize = diskGeometry.BytesPerSector;    // 每sector字节数
   PVOID lpBuffer = new BYTE [dwSize];
   
   if (lpBuffer)
   {
    
   /*
   typedef struct _PARTITION_INFORMATION
   {
   LARGE_INTEGER StartingOffset;     // 启动分区偏移
   LARGE_INTEGER PartitionLength;    // 分区长度(字节)
   DWORD HiddenSectors;              // 分区中隐藏扇区数
   DWORD PartitionNumber;            // 分区数
   BYTE PartitionType;               // 分区类型
   BOOLEAN BootIndicator;            // 是否为引导分区,TRUE是
   BOOLEAN RecognizedPartition;      // 验证过的分区。TRUE是
   BOOLEAN RewritePartition;         // 分区是否可改变。TRUE
   } PARTITION_INFORMATION, *PPARTITION_INFORMATION;
    */
    // 提供关于磁盘分区的信息
    PARTITION_INFORMATION partitionInfo;
    
    //
    // 获得磁盘大小
    //
    if (DeviceIoControl(hDisk,
     IOCTL_DISK_GET_PARTITION_INFO,
     NULL,
     0,
     &partitionInfo,
     sizeof(PARTITION_INFORMATION),
     &dwBytes,
     NULL))
    {
     
     // 获取总扇区数
     LONGLONG sectorCount = partitionInfo.PartitionLength.QuadPart / diskGeometry.BytesPerSector;
     
     _tprintf ( _T("磁盘空间为 %.2fGB 每扇区 %ld字节 共%ld个扇区/r/n"),
      partitionInfo.PartitionLength.QuadPart/1024./1024./1024.    //  磁盘空间
      , diskGeometry.BytesPerSector                               //  每扇区字节数
      , partitionInfo.PartitionLength.QuadPart / diskGeometry.BytesPerSector);  // 总扇区数
     
     LONGLONG nIndex = _ttoi64(Argv[2]);
     
     // 以16进制输出
     _tprintf(_T("Disk %d has 0x%I64x sectors with 0x%x bytes in every sector/n"), _ttoi(Argv[1]), sectorCount, diskGeometry.BytesPerSector);
     
     //
     // 读取被请求的sector
     //
     if (nIndex < sectorCount) {
      
      // 有符号的64位整型表示
      LARGE_INTEGER offset;
      
      // sector数所占字节
      offset.QuadPart = (nIndex) * diskGeometry.BytesPerSector;
      
      // 从打开的文件(磁盘)中移动文件指针。offset.LowPart低32位为移动字节数
      SetFilePointer(hDisk, offset.LowPart, &offset.HighPart, FILE_BEGIN);
      
      // 读取扇区的数据
      if (ReadFile(hDisk, lpBuffer, dwSize, &dwBytes, NULL))
      {
       
       //
       // The dwBytes field holds the number of bytes that were actually read [ <= dwSize ]
       //
       for (ULONG nOffset = 0; nOffset < dwBytes; nOffset += 0x10) {
        
        ULONG nBytes, nIdx;
        
        //
        // 显示地址
        //
        _tprintf(_T("%011I64x "), (offset.QuadPart) + nOffset);
        
        //
        // 显示16进制数据
        //
        nBytes = min(0x10, dwBytes - nOffset);
        
        for (nIdx = 0; nIdx < nBytes; nIdx++) {
         _tprintf(_T("%02x %s"), ((PUCHAR)lpBuffer)[nOffset + nIdx], ((nIdx + 1) % 0x8) ? _T("") : _T(" "));
        }
        
        for ( ; nIdx < 0x10; nIdx++) {
         _tprintf(_T(" %s"), ((nIdx + 1) % 0x8) ? _T("") : _T(" "));
        }
        
        //
        // 显示ascii格式数据
        //
        for (nIdx = 0; nIdx < nBytes; nIdx++) {
         _tprintf(_T("%c"), isprint(((PUCHAR)lpBuffer)[nOffset + nIdx]) ? ((PUCHAR)lpBuffer)[nOffset + nIdx] : _T('.'));
        }
        
        _tprintf(_T("/n"));
       }
       
      } // end ReadFile
      else
      {
       _tprintf(_T("ReadFile() on sector 0x%I64x failed with error code: %d/n"), nIndex, GetLastError());
      }
      
     } // end if (nIndex < sectorCount)
     else
     {
      _tprintf(_T("The requested sector is out-of-bounds/n"));
     }
     
    } // end 1 if (DeviceIoControl  
    else
    {
     _tprintf(_T("IOCTL_DISK_GET_PARTITION_INFO failed with error code %d/n"), GetLastError());
    }
    
    delete [] lpBuffer;
    
   } // if (lpBuffer)
   else
   {
    _tprintf(_T("Unable to allocate resources, exiting/n"));
   }
   
  } // end 2 if (DeviceIoControl
  else
  {
   _tprintf(_T("IOCTL_DISK_GET_DRIVE_GEOMETRY failed with error code %d/n"), GetLastError());
  }
  
  CloseHandle(hDisk);
  
 } // if (hDisk != INVALID_HANDLE_VALUE)
 else
 {
  _tprintf(_T("CreateFile() on %s failed with error code %d/n"), szName, GetLastError());
 }

_tprintf(_T("/n"));

return;
}
#else


/* -------------------------------------------------------------------------- *
*
*
*    2    _getdiskfree显示磁盘扇区信息
*
*
* -------------------------------------------------------------------------- */
// crt_getdiskfree.c
#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <tchar.h>

TCHAR   g_szBorder[] = _T("======================================================================/n");
TCHAR   g_szTitle1[] = _T("|DRIVE|TOTAL CLUSTERS|AVAIL CLUSTERS|SECTORS / CLUSTER|BYTES / SECTOR|/n");
TCHAR   g_szTitle2[] = _T("|=====|==============|==============|=================|==============|/n");
TCHAR   g_szLine[]   = _T("|  A: |              |              |                 |              |/n");

void utoiRightJustified(TCHAR* szLeft, TCHAR* szRight, unsigned uVal);

int main(int argc, char* argv[]) {
 TCHAR szMsg[4200];
 struct _diskfree_t df = {0};
 ULONG uDriveMask = _getdrives();   // 表示当前可用的磁盘
 unsigned uErr, uLen, uDrive;
 
 printf(g_szBorder);
 printf(g_szTitle1);
 printf(g_szTitle2);
 
 int ifor = 0;
 for (uDrive=1; uDrive<=26; ++uDrive)
 {
  if (uDriveMask & 1)
  {
   uErr = _getdiskfree(uDrive, &df);
   memcpy(szMsg, g_szLine, sizeof(g_szLine));
   szMsg[3] = uDrive + 'A' - 1;
   char lp[5] = "C://";
   lp [0] = uDrive + 'A' - 1;
  
   if (uErr == 0) {
    utoiRightJustified(szMsg+8,  szMsg+19, df.total_clusters);
    utoiRightJustified(szMsg+23, szMsg+34, df.avail_clusters);
    utoiRightJustified(szMsg+38, szMsg+52, df.sectors_per_cluster);
    utoiRightJustified(szMsg+56, szMsg+67, df.bytes_per_sector);

    ifor ++;
   }
   else {
    uLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
     uErr, 0, szMsg+8, 4100, NULL);
    szMsg[uLen+6] = ' ';
    szMsg[uLen+7] = ' ';
    szMsg[uLen+8] = ' ';
    ifor ++;
   }
   
   printf(szMsg);
  }
  
  uDriveMask >>= 1;
  if (!uDriveMask)
   break;
 }
 
 printf(g_szBorder);
 printf ("共%d个", ifor);
 return 0;
}

void utoiRightJustified(TCHAR* szLeft, TCHAR* szRight, unsigned uVal) {
 TCHAR* szCur = szRight;
 int nComma = 0;
 
 if (uVal) {
  while (uVal && (szCur >= szLeft)) {
   if   (nComma == 3) {
    *szCur = ',';
    nComma = 0;
   }
   else {
    *szCur = (uVal % 10) | 0x30;
    uVal /= 10;
    ++nComma;
   }
   
   --szCur;
  }
 }
 else {
  *szCur = '0';
  --szCur;
 }
 
 if (uVal) {
  szCur = szLeft;
  
  while   (szCur <= szRight) {
   *szCur = '*';
   ++szCur;
  }
 }
}
#endif

原文地址:https://www.cnblogs.com/tyjsjl/p/2156071.html