存储设备的一种访问方法

本文是根据Lynn McGuire的著名程序 DiskID32程序基础修改而来的 ,部分关键代码,仅供参考.

主要用到了ATA/APAPI的IDENTIFY DEVICE指令,

ATA/APAPI是T13起草和发布的IDE/EIDE/UDMA硬盘及其它可移动存储设备与主机接口的标准,

该接口标准规定了ATA/ATAPI设备的输入输出寄存器和指令集.

用到的常量和结构如下

#include <winioctl.h>

 

//  IOCTL控制码
#define  IOCTL_STORAGE_QUERY_PROPERTY   CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)

 

#define   DFP_SEND_DRIVE_COMMAND   CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define   DFP_RECEIVE_DRIVE_DATA   CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define   IDE_ATA_IDENTIFY    0xEC    //   ATA的ID指令(IDENTIFY DEVICE)
#define   FILE_DEVICE_SCSI         0x0000001b
#define   IOCTL_SCSI_MINIPORT_IDENTIFY  ((FILE_DEVICE_SCSI << 16) + 0x0501)
#define   IOCTL_SCSI_MINIPORT 0x0004D008   //   see NTDDSCSI.H for definition

 

IDENTIFY DEVICE专门用于固定硬盘,而IDENTIFY PACKET DEVICE用于可移动存储设备如CDROM、CF、MO、ZIP、TAPE等。因为驱动程序的原因,不管是IDENTIFY DEVICE也好,IDENTIFY PACKET DEVICE也好,获取可移动存储设备的详细信息,一般是做不到的。而且除了IDE硬盘,对SCSI、USB等接口的硬盘也不起作用。除非厂商提供的驱动支持这样的功能。另外ATA/ATAPI有很多指令,如READ SECTORS, WRITE SECTORS, SECURITY, SLEEP, STANDBY等,对这些指令操作的过程中也要很慎重.

 最新的SDK已经声明了很多以前需要手工声明的结构类型,如

IDEREGS  DRIVERSTATUS SENDCMDINPARAMS SENDCMDOUTPARAMS

 

结构声明:

 

//  查询存储设备属性的类型
typedef  enum  _STORAGE_QUERY_TYPE {
    PropertyStandardQuery 
=   0 ,           //  读取描述
        PropertyExistsQuery,                 //  测试是否支持
        PropertyMaskQuery,                   //  读取指定的描述
        PropertyQueryMaxDefined                 //  验证数据
} STORAGE_QUERY_TYPE,  * PSTORAGE_QUERY_TYPE;

//  查询存储设备还是适配器属性
typedef  enum  _STORAGE_PROPERTY_ID {
    StorageDeviceProperty 
=   0 ,             //  查询设备属性
        StorageAdapterProperty                 //  查询适配器属性
} STORAGE_PROPERTY_ID,  * PSTORAGE_PROPERTY_ID;

//  查询属性输入的数据结构
typedef  struct  _STORAGE_PROPERTY_QUERY {
    STORAGE_PROPERTY_ID PropertyId;        
//  设备/适配器
    STORAGE_QUERY_TYPE QueryType;         //  查询类型 
    UCHAR AdditionalParameters[ 1 ];         //  额外的数据(仅定义了象征性的1个字节)
} STORAGE_PROPERTY_QUERY,  * PSTORAGE_PROPERTY_QUERY;


typedef 
struct  _STORAGE_DEVICE_DESCRIPTOR {
    ULONG Version;        
//  版本
    ULONG Size;             //  结构大小
    UCHAR DeviceType;     //  设备类型
    UCHAR DeviceTypeModifier;     //  SCSI-2额外的设备类型
    BOOLEAN RemovableMedia;         //  是否可移动
    BOOLEAN CommandQueueing;     //  是否支持命令队列
    ULONG VendorIdOffset;         //  厂家设定值的偏移
    ULONG ProductIdOffset;         //  产品ID的偏移
    ULONG ProductRevisionOffset;     //  产品版本的偏移
    ULONG SerialNumberOffset;         //  序列号的偏移
    STORAGE_BUS_TYPE BusType;         //  总线类型
    ULONG RawPropertiesLength;         //  额外的属性数据长度
    UCHAR RawDeviceProperties[ 1 ];     //  额外的属性数据(仅定义了象征性的1个字节)
} STORAGE_DEVICE_DESCRIPTOR,  * PSTORAGE_DEVICE_DESCRIPTOR;

 

typedef  struct  _IDINFO
{
    USHORT  wGenConfig;                    
//  WORD 0: 基本信息字
    USHORT  wNumCyls;                     //  WORD 1: 柱面数
    USHORT  wReserved2;                     //  WORD 2: 保留
    USHORT  wNumHeads;                     //  WORD 3: 磁头数
    USHORT  wReserved4;                     //  WORD 4: 保留
    USHORT  wReserved5;                     //  WORD 5: 保留
    USHORT  wNumSectorsPerTrack;         //  WORD 6: 每磁道扇区数
    USHORT  wVendorUnique[ 3 ];             //  WORD 7-9: 厂家设定值
    CHAR    sSerialNumber[ 20 ];             //  WORD 10-19:序列号
    USHORT  wBufferType;                 //  WORD 20: 缓冲类型
    USHORT  wBufferSize;                 //  WORD 21: 缓冲大小
    USHORT  wECCSize;                     //  WORD 22: ECC校验大小
    CHAR    sFirmwareRev[ 8 ];             //  WORD 23-26: 固件版本
    CHAR    sModelNumber[ 40 ];             //  WORD 27-46: 内部型号
    USHORT  wMoreVendorUnique;             //  WORD 47: 厂家设定值
    USHORT  wReserved48;                 //  WORD 48: 保留
     struct  {
        USHORT  reserved1:
8 ;
        USHORT  DMA:
1 ;                     //  1=支持DMA
        USHORT  LBA: 1 ;                     //  1=支持LBA
        USHORT  DisIORDY: 1 ;                 //  1=可不使用IORDY
        USHORT  IORDY: 1 ;                 //  1=支持IORDY
        USHORT  SoftReset: 1 ;             //  1=需要ATA软启动
        USHORT  Overlap: 1 ;                 //  1=支持重叠操作
        USHORT  Queue: 1 ;                 //  1=支持命令队列
        USHORT  InlDMA: 1 ;                 //  1=支持交叉存取DMA
    } wCapabilities;                     //  WORD 49: 一般能力
    USHORT  wReserved1;                     //  WORD 50: 保留
    USHORT  wPIOTiming;                     //  WORD 51: PIO时序
    USHORT  wDMATiming;                     //  WORD 52: DMA时序
     struct  {
        USHORT  CHSNumber:
1 ;             //  1=WORD 54-58有效
        USHORT  CycleNumber: 1 ;             //  1=WORD 64-70有效
        USHORT  UnltraDMA: 1 ;             //  1=WORD 88有效
        USHORT  reserved: 13 ;
    } wFieldValidity;                    
//  WORD 53: 后续字段有效性标志
    USHORT  wNumCurCyls;                 //  WORD 54: CHS可寻址的柱面数
    USHORT  wNumCurHeads;                 //  WORD 55: CHS可寻址的磁头数
    USHORT  wNumCurSectorsPerTrack;         //  WORD 56: CHS可寻址每磁道扇区数
    USHORT  wCurSectorsLow;                 //  WORD 57: CHS可寻址的扇区数低位字
    USHORT  wCurSectorsHigh;             //  WORD 58: CHS可寻址的扇区数高位字
     struct  {
        USHORT  CurNumber:
8 ;             //  当前一次性可读写扇区数
        USHORT  Multi: 1 ;                 //  1=已选择多扇区读写
        USHORT  reserved1: 7 ;
    } wMultSectorStuff;                    
//  WORD 59: 多扇区读写设定
    ULONG  dwTotalSectors;                 //  WORD 60-61: LBA可寻址的扇区数
    USHORT  wSingleWordDMA;                 //  WORD 62: 单字节DMA支持能力
     struct  {
        USHORT  Mode0:
1 ;                 //  1=支持模式0 (4.17Mb/s)
        USHORT  Mode1: 1 ;                 //  1=支持模式1 (13.3Mb/s)
        USHORT  Mode2: 1 ;                 //  1=支持模式2 (16.7Mb/s)
        USHORT  Reserved1: 5 ;
        USHORT  Mode0Sel:
1 ;                 //  1=已选择模式0
        USHORT  Mode1Sel: 1 ;                 //  1=已选择模式1
        USHORT  Mode2Sel: 1 ;                 //  1=已选择模式2
        USHORT  Reserved2: 5 ;
    } wMultiWordDMA;                    
//  WORD 63: 多字节DMA支持能力
     struct  {
        USHORT  AdvPOIModes:
8 ;             //  支持高级POI模式数
        USHORT  reserved: 8 ;
    } wPIOCapacity;                        
//  WORD 64: 高级PIO支持能力
    USHORT  wMinMultiWordDMACycle;         //  WORD 65: 多字节DMA传输周期的最小值
    USHORT  wRecMultiWordDMACycle;         //  WORD 66: 多字节DMA传输周期的建议值
    USHORT  wMinPIONoFlowCycle;             //  WORD 67: 无流控制时PIO传输周期的最小值
    USHORT  wMinPOIFlowCycle;             //  WORD 68: 有流控制时PIO传输周期的最小值
    USHORT  wReserved69[ 11 ];             //  WORD 69-79: 保留
     struct  {
        USHORT  Reserved1:
1 ;
        USHORT  ATA1:
1 ;                     //  1=支持ATA-1
        USHORT  ATA2: 1 ;                     //  1=支持ATA-2
        USHORT  ATA3: 1 ;                     //  1=支持ATA-3
        USHORT  ATA4: 1 ;                     //  1=支持ATA/ATAPI-4
        USHORT  ATA5: 1 ;                     //  1=支持ATA/ATAPI-5
        USHORT  ATA6: 1 ;                     //  1=支持ATA/ATAPI-6
        USHORT  ATA7: 1 ;                     //  1=支持ATA/ATAPI-7
        USHORT  ATA8: 1 ;                     //  1=支持ATA/ATAPI-8
        USHORT  ATA9: 1 ;                     //  1=支持ATA/ATAPI-9
        USHORT  ATA10: 1 ;                 //  1=支持ATA/ATAPI-10
        USHORT  ATA11: 1 ;                 //  1=支持ATA/ATAPI-11
        USHORT  ATA12: 1 ;                 //  1=支持ATA/ATAPI-12
        USHORT  ATA13: 1 ;                 //  1=支持ATA/ATAPI-13
        USHORT  ATA14: 1 ;                 //  1=支持ATA/ATAPI-14
        USHORT  Reserved2: 1 ;
    } wMajorVersion;                    
//  WORD 80: 主版本
    USHORT  wMinorVersion;                 //  WORD 81: 副版本
    USHORT  wReserved82[ 6 ];                 //  WORD 82-87: 保留
     struct  {
        USHORT  Mode0:
1 ;                 //  1=支持模式0 (16.7Mb/s)
        USHORT  Mode1: 1 ;                 //  1=支持模式1 (25Mb/s)
        USHORT  Mode2: 1 ;                 //  1=支持模式2 (33Mb/s)
        USHORT  Mode3: 1 ;                 //  1=支持模式3 (44Mb/s)
        USHORT  Mode4: 1 ;                 //  1=支持模式4 (66Mb/s)
        USHORT  Mode5: 1 ;                 //  1=支持模式5 (100Mb/s)
        USHORT  Mode6: 1 ;                 //  1=支持模式6 (133Mb/s)
        USHORT  Mode7: 1 ;                 //  1=支持模式7 (166Mb/s) ???
        USHORT  Mode0Sel: 1 ;                 //  1=已选择模式0
        USHORT  Mode1Sel: 1 ;                 //  1=已选择模式1
        USHORT  Mode2Sel: 1 ;                 //  1=已选择模式2
        USHORT  Mode3Sel: 1 ;                 //  1=已选择模式3
        USHORT  Mode4Sel: 1 ;                 //  1=已选择模式4
        USHORT  Mode5Sel: 1 ;                 //  1=已选择模式5
        USHORT  Mode6Sel: 1 ;                 //  1=已选择模式6
        USHORT  Mode7Sel: 1 ;                 //  1=已选择模式7
    } wUltraDMA;                         //  WORD 88:  Ultra DMA支持能力
    USHORT    wReserved89[ 167 ];             //  WORD 89-255
} IDINFO,  * PIDINFO;

头文件声明的几个重要函数

 

     void  AdjustString( char *  str,  int  len);
    BOOL IdentifyDevice(HANDLE hDevice, PIDINFO pIdInfo);
    BOOL GetPhysicalDriveInfoInNT(
int  nDrive, PIDINFO pIdInfo);
    
void  GetBoisUUID();
    CString MakeActualString(LPCTSTR pszMsg);
    BOOL GetDriveProperty(HANDLE hDevice, PSTORAGE_DEVICE_DESCRIPTOR pDevDesc);
    BOOL GetDriveGeometry(HANDLE hDevice, PDISK_GEOMETRY pGeometry);
    HANDLE OpenDevice(LPCTSTR pszDevicePath);
    
int  GetDevicePath(LPGUID lpGuid, LPTSTR *  pszDevicePath);

 

cpp

 

#pragma  comment(lib,"Setupapi.lib")
#define  BUFSIZE1 1024

#define  INTERFACE_DETAIL_SIZE    (1024)
#define  MEDIA_INFO_SIZE        (sizeof(GET_MEDIA_TYPES) + sizeof(DEVICE_MEDIA_INFO) * 15)

#define  MAX_DEVICE        16

const  GUID DiskClassGuid  =   { 0x53f56307L 0xb6bf 0x11d0 , { 0x94 0xf2 0x00 0xa0 0xc9 0x1e 0xfb 0x8b }};

 

void  CCGuardTestDlg::OnStart() 
{
    HANDLE hDevice;
    PDISK_GEOMETRY pGeometry;
    PSTORAGE_DEVICE_DESCRIPTOR pDevDesc;
    
int  i,j;
    
int  nDevice;
    
char *  szDevicePath[MAX_DEVICE];
    pGeometry 
=   new  DISK_GEOMETRY;
    CString strTmp 
=   "" ;
    
for (i = 0 ;i < MAX_DEVICE;i ++ ) szDevicePath[i] = new   char [ 256 ];
    pDevDesc 
=  (PSTORAGE_DEVICE_DESCRIPTOR) new  BYTE[ sizeof (STORAGE_DEVICE_DESCRIPTOR)  +   512   -   1 ];
    
    pDevDesc
-> Size  =   sizeof (STORAGE_DEVICE_DESCRIPTOR)  +   512   -   1 ;
    
    LPGUID lpGuid 
=  (LPGUID) & DiskClassGuid;
    
for (i = 0 ; i < sizeof (lpGuid) / sizeof (LPGUID); i ++ )
    {
        nDevice    
=  GetDevicePath(lpGuid, szDevicePath);

        
for (j = 0 ; j < nDevice; j ++ )
        {
            hDevice 
=  OpenDevice( szDevicePath[j] );
            
if (hDevice  !=  INVALID_HANDLE_VALUE)
            {
                GetDriveGeometry(hDevice, pGeometry);
                GetDriveProperty(hDevice, pDevDesc);
                
char *  p;
                
                p
=  ( char * )pDevDesc;
                
                strTmp 
=  (pDevDesc -> ProductRevisionOffset  ?   & p[pDevDesc -> ProductRevisionOffset] :  "" ); //  firmware version
                strTmp  =  MakeActualString(strTmp);
                
                strTmp 
=  (pDevDesc -> SerialNumberOffset  ?   & p[pDevDesc -> SerialNumberOffset] :  "" );
                strTmp 
=  MakeActualString(strTmp);

                strTmp 
=  (pDevDesc -> ProductIdOffset  ?   & p[pDevDesc -> ProductIdOffset] :  "" );
                strTmp 
=  MakeActualString(strTmp);
                ULONGLONG DiskSize 
=  pGeometry -> Cylinders.QuadPart  *  (ULONGLONG)pGeometry -> TracksPerCylinder  *
                    (ULONGLONG)pGeometry
-> SectorsPerTrack  *  (ULONGLONG)pGeometry -> BytesPerSector;
                strTmp.Format(
" Disk size = %I64d Bytes (%I64d MB) " , DiskSize, DiskSize  /  ( 1024   *   1024 ));
                
                CloseHandle(hDevice);
            }
        }
    }    
    delete pGeometry;
    
for (i = 0 ;i < MAX_DEVICE;i ++ ) delete []szDevicePath[i];
}

 

 

void  CCGuardTestDlg::OnGetPhyinfo() 
{
    CString strInfo;
    IDINFO IdInfo;

    
for ( int  i = 0 ; i < 4 ; i ++ ) // 一般不会挂十来块硬盘吧
    {
        
if (GetPhysicalDriveInfoInNT(i,  & IdInfo))
        {
            strInfo 
+=   " "   +  MakeIdeInfo(i,  0 & IdInfo);
        }
    }
    
}

 

 

int  CCGuardTestDlg::GetDevicePath(LPGUID lpGuid, LPTSTR  * pszDevicePath)
{
    HDEVINFO hDevInfoSet;
    SP_DEVICE_INTERFACE_DATA ifdata;
    PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
    
int  nCount;
    BOOL bResult;
    
    hDevInfoSet 
=  ::SetupDiGetClassDevs(lpGuid,     
            NULL,                                    
            NULL,                                    
            DIGCF_PRESENT 
|  DIGCF_DEVICEINTERFACE);
    
if  ( INVALID_HANDLE_VALUE  ==  hDevInfoSet )
    {
        
return   0 ;
    }
    pDetail 
=  (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);
    pDetail
-> cbSize  =   sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
    
    
    nCount 
=   0 ;
    bResult 
=  TRUE;
    
    
while  (bResult)
    {
                ifdata.cbSize
= sizeof (ifdata);
    
        
//  枚举符合该GUID的设备接口
        bResult  =  ::SetupDiEnumDeviceInterfaces(
                hDevInfoSet,            
//  设备信息集句柄
                NULL,                     //  不需额外的设备描述
                lpGuid,                     //  GUID
                (ULONG)nCount,             //  设备信息集里的设备序号
                 & ifdata);                 //  设备接口信息

        
if (bResult)
        {
            
//  取得该设备接口的细节(设备路径)
            bResult  =  SetupDiGetInterfaceDeviceDetail(
                    hDevInfoSet,            
//  设备信息集句柄
                     & ifdata,                 //  设备接口信息
                    pDetail,                 //  设备接口细节(设备路径)
                    INTERFACE_DETAIL_SIZE,     //  输出缓冲区大小
                    NULL,                     //  不需计算输出缓冲区大小(直接用设定值)
                    NULL);                     //  不需额外的设备描述

            
if (bResult)
            {
                
//  复制设备路径到输出缓冲区
                ::strcpy(pszDevicePath[nCount], pDetail -> DevicePath);

                
//  调整计数值
                nCount ++ ;
            }
        }
    }
    
    
//  释放设备接口数据空间
    ::GlobalFree(pDetail);

    
//  关闭设备信息集句柄
    ::SetupDiDestroyDeviceInfoList(hDevInfoSet);

    
return  nCount;
}

HANDLE CCGuardTestDlg::OpenDevice(LPCTSTR pszDevicePath)
{
    HANDLE hDevice;
    
    
//  打开设备
    hDevice =  ::CreateFile(pszDevicePath,             //  设备路径
        GENERIC_READ  |  GENERIC_WRITE,             //  读写方式
        FILE_SHARE_READ  |  FILE_SHARE_WRITE,         //  共享方式
        NULL,                                     //  默认的安全描述符
        OPEN_EXISTING,                             //  创建方式
         0 ,                                         //  不需设置文件属性
        NULL);                                     //  不需参照模板文件
    
    
return  hDevice;
}

BOOL CCGuardTestDlg::GetDriveGeometry(HANDLE hDevice, PDISK_GEOMETRY pGeometry)
{
    PGET_MEDIA_TYPES pMediaTypes;    
//  内部用的输出缓冲区
    DWORD dwOutBytes;                 //  输出数据长度
    BOOL bResult;                     //  DeviceIoControl的返回结果

    
//  申请内部用的输出缓冲区
    pMediaTypes  =  (PGET_MEDIA_TYPES)::GlobalAlloc(LMEM_ZEROINIT, MEDIA_INFO_SIZE);

        bResult 
=  ::DeviceIoControl(hDevice,             //  设备句柄
            IOCTL_STORAGE_GET_MEDIA_TYPES_EX,         //  取介质类型参数
            NULL,  0 ,                                 //  不需要输入数据
            pMediaTypes, MEDIA_INFO_SIZE,             //  输出数据缓冲区
             & dwOutBytes,                             //  输出数据长度
            (LPOVERLAPPED)NULL);                     //  用同步I/O    

    
if (bResult)
    {
        
//  注意到结构DEVICE_MEDIA_INFO是在结构DISK_GEOMETRY的基础上扩充的
        
//  为简化程序,用memcpy代替如下多条赋值语句:
        
//  pGeometry->MediaType = (MEDIA_TYPE)pMediaTypes->MediaInfo[0].DeviceSpecific.DiskInfo.MediaType;
        
//  pGeometry->Cylinders = pMediaTypes->MediaInfo[0].DeviceSpecific.DiskInfo.Cylinders;
        
//  pGeometry->TracksPerCylinder = pMediaTypes->MediaInfo[0].DeviceSpecific.DiskInfo.TracksPerCylinder;
        
//  ... ...
        ::memcpy(pGeometry, pMediaTypes -> MediaInfo,  sizeof (DISK_GEOMETRY));
    }

    ::GlobalFree(pMediaTypes);

    
return  bResult;
}

BOOL CCGuardTestDlg::GetDriveProperty(HANDLE hDevice, PSTORAGE_DEVICE_DESCRIPTOR pDevDesc)
{
    STORAGE_PROPERTY_QUERY    Query;    
//  查询输入参数
    DWORD dwOutBytes;                 //  IOCTL输出数据长度
    BOOL bResult;                     //  IOCTL返回值
    
    
//  指定查询方式
    Query.PropertyId  =  StorageDeviceProperty;
    Query.QueryType 
=  PropertyStandardQuery;
    
    
//  用IOCTL_STORAGE_QUERY_PROPERTY取设备属性信息
    bResult  =  ::DeviceIoControl(hDevice,             //  设备句柄
        IOCTL_STORAGE_QUERY_PROPERTY,             //  取设备属性信息
         & Query,  sizeof (STORAGE_PROPERTY_QUERY),     //  输入数据缓冲区
        pDevDesc, pDevDesc -> Size,                 //  输出数据缓冲区
         & dwOutBytes,                             //  输出数据长度
        (LPOVERLAPPED)NULL);                     //  用同步I/O    
    
    
return  bResult;
}

CString CCGuardTestDlg::MakeActualString(LPCTSTR pszMsg)
{
        
int  i;
    
int  len;
    BOOL fNeedTranslation;
    CString strMsg;

    len 
=  ::strlen(pszMsg);
    
    fNeedTranslation 
=  TRUE;

    i
= 0 ;
    
while (i < len  &&  fNeedTranslation)
    {
        
if ( ! (pszMsg[i] >= ' 0 '   &&  pszMsg[i] <= ' 9 '   ||  
            pszMsg[i]
>= ' A '   &&  pszMsg[i] <= ' F '   ||
            pszMsg[i]
>= ' a '   &&  pszMsg[i] <= ' f ' ))
        {
            fNeedTranslation 
=  FALSE;
        }

        i
++ ;
    }

    
if (fNeedTranslation)
    {
        WORD word;

        
for (i = 0 ; i < len; i += 4 )
        {
            ::sscanf(
& pszMsg[i],  " %04x " & word);

            strMsg 
+=  ( char )(word % 256 );
            strMsg 
+=  ( char )(word / 256 );
        }
    }
    
else
    {
        strMsg 
=  pszMsg;
    }

    strMsg.TrimLeft();
    strMsg.TrimRight();

    
return  strMsg;
}


BOOL CCGuardTestDlg::GetPhysicalDriveInfoInNT(
int  nDrive, PIDINFO pIdInfo)
{
    HANDLE hDevice;            
//  设备句柄
    BOOL bResult;             //  返回结果
     char  szFileName[ 20 ];     //  文件名

    ::sprintf(szFileName,
" //./PhysicalDrive%d " , nDrive);
//     nDevice    = GetDevicePath(lpGuid, szDevicePath);
    hDevice  =  OpenDevice(szFileName);

    
if (hDevice  ==  INVALID_HANDLE_VALUE)
    {
        
return  FALSE;
    }

    
//  IDENTIFY DEVICE
    bResult  =  IdentifyDevice(hDevice, pIdInfo);

    
if (bResult)
    {
        
//  调整字符串
        AdjustString(pIdInfo -> sSerialNumber,  20 );
        AdjustString(pIdInfo
-> sModelNumber,  40 );
        AdjustString(pIdInfo
-> sFirmwareRev,  8 );
    }

    ::CloseHandle (hDevice);

    
return  bResult;
}

BOOL CCGuardTestDlg::IdentifyDevice(HANDLE hDevice, PIDINFO pIdInfo)
{
    PSENDCMDINPARAMS pSCIP;        
//  输入数据结构指针
    PSENDCMDOUTPARAMS pSCOP;     //  输出数据结构指针
    DWORD dwOutBytes;             //  IOCTL输出数据长度
    BOOL bResult;                 //  IOCTL返回值

    
//  申请输入/输出数据结构空间
    pSCIP  =  (PSENDCMDINPARAMS)::GlobalAlloc(LMEM_ZEROINIT,  sizeof (SENDCMDINPARAMS) - 1 );
    pSCOP 
=  (PSENDCMDOUTPARAMS)::GlobalAlloc(LMEM_ZEROINIT,  sizeof (SENDCMDOUTPARAMS) + sizeof (IDINFO) - 1 );

    pSCIP
-> irDriveRegs.bCommandReg  =  IDE_ATA_IDENTIFY;  //  really important!

    
    
//  指定输入/输出数据缓冲区大小
    pSCIP -> cBufferSize  =   0 ;
    pSCOP
-> cBufferSize  =   sizeof (IDINFO);

    
//  IDENTIFY DEVICE
    bResult  =  ::DeviceIoControl(hDevice,                         //  设备句柄
        DFP_RECEIVE_DRIVE_DATA,                                     //  指定IOCTL
        pSCIP,  sizeof (SENDCMDINPARAMS)  -   1 ,                         //  输入数据缓冲区
        pSCOP,  sizeof (SENDCMDOUTPARAMS)  +   sizeof (IDINFO)  -   1 ,     //  输出数据缓冲区
         & dwOutBytes,                                             //  输出数据长度
        (LPOVERLAPPED)NULL);                                     //  用同步I/O

    
//  复制设备参数结构
    ::memcpy(pIdInfo, pSCOP -> bBuffer,  sizeof (IDINFO));

    
//  释放输入/输出数据空间
    ::GlobalFree(pSCOP);
    ::GlobalFree(pSCIP);

    
return  bResult;
}

 

void CCGuardTestDlg::AdjustString(char *str, int len)
{
  char ch;
 int i;

 // 两两颠倒
 for(i=0;i<len;i+=2)
 {
  ch = str[i];
  str[i] = str[i+1];
  str[i+1] = ch;
 }

 // 若是右对齐的,调整为左对齐 (去掉左边的空格)
 i=0;
 while(i<len && str[i]==' ') i++;

 ::memmove(str, &str[i], len-i);

 // 去掉右边的空格
 i = len - 1;
 while(i>=0 && str[i]==' ')
 {
  str[i] = '/0';
  i--;
 }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值