获取磁盘、光盘的柱面扇区相关信息

 

参考:http://bbs.csdn.net/topics/390011646

        http://blog.163.com/maple_zh@126/blog/static/107129598200921072150858/

 

在VC6 XP.sp3中的运行正常的代码:


//
//  两种方式:
//    1   DeviceIoControl读取磁盘扇区
//    2    _getdiskfree显示磁盘扇区信息
//
// 方式切换开关
#define WITH_IOCTL_DISK_GET_DRIVE_GEOMETRY



#ifdef WITH_IOCTL_DISK_GET_DRIVE_GEOMETRY

/* -------------------------------------------------------------------------- *


*    1   DeviceIoControl读取磁盘扇区

*
* -------------------------------------------------------------------------- 
*/

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

enum E_DISK_TYPE
{
    eDT_Physicaldrive,
    eDT_CDROM
};

VOID __cdecl _tmain (INT Argc, PTCHAR Argv[])
{
    //E_DISK_TYPE eDiskType = eDT_Physicaldrive;  //  读取磁盘信息
    E_DISK_TYPE eDiskType = eDT_CDROM;          //  读取光盘信息时

    TCHAR szName[MAX_PATH] = { 0 };
    HANDLE hDisk = NULL;
 
    //
    
// 命令行参数可在Project Settings->Debug->Program arguments下指定 如:0 1
    
//
    if (Argc != 3
    {
        _tprintf(_T("Reads a sector on the disk "));
        _tprintf(_T("%s [disk number] [sector] "), Argv[0]);
        return;
    }
 
    switch (eDT_CDROM)
    {
    case eDT_Physicaldrive:
        _sntprintf(szName, sizeof(szName) / sizeof(szName[0]) - 1, _T("\\.\Physicaldrive%d"), _ttoi(Argv[1]));  //  读取磁盘信息时
        break;

    case eDT_CDROM:
        _sntprintf(szName, sizeof(szName) / sizeof(szName[0]) - 1, _T("\\.\CDROM%d"), _ttoi(Argv[1]));  //  读取光盘信息时
        break;
    }

    //
    
// 打开磁盘
    
//
    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))
        {
            _tprintf(_T("IOCTL_DISK_GET_DRIVE_GEOMETRY failed with error code %d "), GetLastError());            
            return;
        }

        //
        
//
        DWORD dwSize = diskGeometry.BytesPerSector;    // 每sector字节数
        PVOID lpBuffer = new BYTE [dwSize];
        if (lpBuffer == NULL) 
        {
            _tprintf(_T("Unable to allocate resources, exiting "));
            return;
        } 

        //
        
//  关于磁盘分区的信息
        
//
        /*
        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)) 
        {
            switch (eDT_CDROM)
            {
            case eDT_Physicaldrive:
                _tprintf ( _T("磁盘空间为 %.2fGB 每扇区 %ld字节 共%ld个扇区 "), 
                                partitionInfo.PartitionLength.QuadPart/1024./1024./1024.    //  磁盘空间
                                , diskGeometry.BytesPerSector                               //  每扇区字节数
                                , partitionInfo.PartitionLength.QuadPart / diskGeometry.BytesPerSector);  // 总扇区数
                break;

            case eDT_CDROM:
                _tprintf ( _T("光盘空间为 %.2fMB 每扇区 %ld字节 共%ld个扇区 "), 
                    partitionInfo.PartitionLength.QuadPart/1024./1024.          //  光盘空间
                    , diskGeometry.BytesPerSector                               //  每扇区字节数
                    , partitionInfo.PartitionLength.QuadPart / diskGeometry.BytesPerSector);  // 总扇区数

                break;
            }

            // 获取总扇区数
            LONGLONG sectorCount = partitionInfo.PartitionLength.QuadPart / diskGeometry.BytesPerSector;
            // 以16进制输出
            switch (eDT_CDROM)
            {
            case eDT_Physicaldrive:
                _tprintf(_T("PhysicalDisk %d has 0x%I64x sectors with 0x%x bytes in every sector "), _ttoi(Argv[1]), sectorCount, diskGeometry.BytesPerSector);
                break;
            case eDT_CDROM:
                _tprintf(_T("CDROM %d has 0x%I64x sectors with 0x%x bytes in every sector "), _ttoi(Argv[1]), sectorCount, diskGeometry.BytesPerSector);
                break;
            }
            
            //
            LONGLONG nIndex = _ttoi64(Argv[2]);

            //
            
// 读取被请求的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)) 
                {
                    //  扇区的数据
                    _tprintf(_T("扇区%d数据: "), nIndex);

                    //
                    
// 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(" "));
                    }

                } // end ReadFile
                else
                {
                    _tprintf(_T("ReadFile() on sector 0x%I64x failed with error code: %d "), nIndex, GetLastError());
                }

            } // end if (nIndex < sectorCount) 
            else
            {
                _tprintf(_T("The requested sector is out-of-bounds "));
            }

        } // end 1 if (DeviceIoControl   
        else
        {
            _tprintf(_T("IOCTL_DISK_GET_PARTITION_INFO failed with error code %d "), GetLastError());
        }


        delete [] lpBuffer;
        CloseHandle(hDisk);
  
    } // if (hDisk != INVALID_HANDLE_VALUE) 
    else
    {
        _tprintf(_T("CreateFile() on %s failed with error code %d "), szName, GetLastError());
    }

    _tprintf(_T(" "));

    return;
}


#else


/* -------------------------------------------------------------------------- *


*    2    _getdiskfree显示磁盘扇区信息

*
* -------------------------------------------------------------------------- 
*/

// crt_getdiskfree.c

#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <tchar.h>

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

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+84100, 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/ant-wjf/p/3432865.html