存储设备的一种访问方法

本文是根据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 =  {0x53f56307L0xb6bf0x11d0, {0x940xf20x000xa00xc90x1e0xfb0x8b}};

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值