RSB140508 2017-06-01 10:22 采纳率: 100%
浏览 1327
已采纳

如何利用deviceiocontrol函数实现对光盘数据的读取,麻烦各位看看

源代码如下
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include"new.h"
using namespace std;
BOOL GetDriveString(TCHAR *j)
{
TCHAR cBuff[MAX_PATH]={0};
DWORD slen=GetLogicalDriveStrings(MAX_PATH,cBuff);
TCHAR *pc=cBuff;
int i=0;
int iLength=0;
while('\0'!=*pc)
{
j[i]=*pc;
iLength=_tcslen(pc);
pc+=iLength+1;
i++;
}
if(_tcslen(j)!=0)
return 1;
else
return 0;
}

BOOL GetDriveTypeStr(const TCHAR *strDrive,TCHAR *strType)
{
char RPathName[]="C:\";
RPathName[0]=*strDrive;
UINT uDrivetype=GetDriveType(RPathName);
switch(uDrivetype)
{
case DRIVE_UNKNOWN:
sprintf(strType, _T("%s: %s"), strDrive, _T("UnKnow"));
//_tcscpy(strType, _T("UnKnow"));
break;
case DRIVE_NO_ROOT_DIR:
sprintf(strType, _T("%s: %s"), strDrive, _T("DRIVE_NO_ROOT_DIR"));
break;
case DRIVE_REMOVABLE:
sprintf(strType, _T("%s: %s"), strDrive, _T("DRIVE_REMOVABLE"));
break;
case DRIVE_FIXED:
sprintf(strType, _T("%s: %s"), strDrive, _T("DRIVE_FIXED"));
break;
case DRIVE_REMOTE:
_stprintf(strType, _T("%s: %s"), strDrive, _T("DRIVE_REMOTE"));
break;
case DRIVE_CDROM:
sprintf(strType, _T("%s: %s"), strDrive, _T("DRIVE_CDROM"));
break;
case DRIVE_RAMDISK:
sprintf(strType, _T("%s: %s"), strDrive, _T("DRIVE_RAMDISK"));
break;
default:
sprintf(strType, _T("%s: %s"), strDrive, _T("Else"));
break;
}
return 1;
}

BOOL GetDriveHandle(const TCHAR *strDrive,HANDLE *hDevice)
{
TCHAR RPathName[]="\\.\C:";
RPathName[4]=*strDrive;

*hDevice = CreateFile((LPCSTR)RPathName,          // drive to open
    GENERIC_READ | GENERIC_WRITE,                // 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);
}
return TRUE;

}

BOOL GetDriveGeometry(HANDLE hDevice, const TCHAR *strDrive, char *Dgeometry)
{
BOOL bResult = FALSE; // results flag
DWORD junk = 0; // discard results
DISK_GEOMETRY pdg={0}; // disk drive geometry structure
ULONGLONG DiskSize = 0; // size of the drive, in bytes
bResult =DeviceIoControl(hDevice, // device to be queried
IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform
NULL, 0, // no input buffer
&pdg, sizeof(pdg), // output buffer
&junk, // # bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O
if (bResult)
{
sprintf(Dgeometry, "Drive path = %s;\n", strDrive);

        DiskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder * (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;
        sprintf(Dgeometry, "%sDisk size  = %I64d (Bytes);\n"
        "           = %.2f (Gb).\n", 
                            Dgeometry,DiskSize, (double) DiskSize / (1024 * 1024 * 1024));  
        return 1;
    } 
    else 
    {
        sprintf (Dgeometry, "GetDriveGeometry failed.");
        return 0;
    }

}

BOOL ScsiPassthrough(HANDLE hDevice,BYTE *ucAddress,int wBlock)
{

SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptdwb;
ULONG length = 0;
DWORD bytesReturn;
BYTE bufDataRead[64 * 1024 + 10];
//数组清零
memset(bufDataRead,0,sizeof(bufDataRead));
int iRet;

//扇区数
int sectors=bufDataRead[0]*(1<<24)+bufDataRead[1]*(1<<16)+bufDataRead[2]*(1<<8)+bufDataRead[3]+1;
//每个扇区的字节数
int bytesPerSector=bufDataRead[4]*(1<<24)+bufDataRead[5]*(1<<16)+bufDataRead[6]*(1<<8)+bufDataRead[7];
printf("sectors=%d bytesPerSector=%d\n",sectors,bytesPerSector);

ZeroMemory(&sptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
sptdwb.sptd.PathId = 0;
sptdwb.sptd.TargetId = 1;
sptdwb.sptd.Lun = 0;
sptdwb.sptd.CdbLength = 12; //SCSI命令长度
sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_IN;
sptdwb.sptd.SenseInfoLength = 24;
sptdwb.sptd.DataTransferLength =bytesPerSector*wBlock; //读数据量
sptdwb.sptd.TimeOutValue = 2;
sptdwb.sptd.DataBuffer =bufDataRead;
sptdwb.sptd.SenseInfoOffset =offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);

sptdwb.sptd.Cdb[0] = 0x28;          //读READ(10)数据命令
sptdwb.sptd.Cdb[1] = 0x00;
sptdwb.sptd.Cdb[2] = (*ucAddress>>24)&0xff; 
sptdwb.sptd.Cdb[3] = (*ucAddress>>16)&0xff;
sptdwb.sptd.Cdb[4] = (*ucAddress>>8)&0xff;
sptdwb.sptd.Cdb[5] = *ucAddress&0xff;
sptdwb.sptd.Cdb[6] = 0x00;
sptdwb.sptd.Cdb[7] = (wBlock>>8)&0xff;
sptdwb.sptd.Cdb[8] = wBlock&0xff;   //读readSectors个扇区 ,注意这个值一定要与DataTransferLength相对应
sptdwb.sptd.Cdb[9] = 0x00;
sptdwb.sptd.Cdb[10] = 0x00;
sptdwb.sptd.Cdb[11] = 0x00;
length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
//向设备发送
iRet = DeviceIoControl(hDevice,
    IOCTL_SCSI_PASS_THROUGH_DIRECT,
    NULL,
    0,
    bufDataRead,
    wBlock,
    &bytesReturn,
    NULL);
if (0 == iRet)
{
    printf("读取光盘数据失败");
    return 0;
}
//放置到公用数组
memcpy(&ucAddress[0],&bufDataRead[0],wBlock);
return true;

}
/*for(int i=0;i<iSize*bytesPerSector;i++)
{

if(i%16==0)
{

printf("\n");
}
printf("%02X",bufDataRead[i]);
}
printf("\n");
return 0;
}*/

BOOL SetCDSpeed(HANDLE hDevice, int speed)
{
DWORD dwOutBytes;
CDROM_SET_SPEED SetSpeed;
SetSpeed.RequestType =(CDROM_SPEED_REQUEST)0;
SetSpeed.ReadSpeed =speed;
if (DeviceIoControl(hDevice,
IOCTL_CDROM_SET_SPEED,
&SetSpeed, sizeof(SetSpeed),
0, NULL,
&dwOutBytes,
(LPOVERLAPPED)NULL))
return true;

return false;
}

BOOL CloseDriveHandle(HANDLE hDevice)
{
return (CloseHandle(hDevice));
}

void main()
{
TCHAR j[MAX_PATH]={0};
TCHAR strType[100] = {0};
TCHAR Dgeometry[1000] = {0};
int speed =100;
HANDLE hDevice;
BYTE bufDataRead[64 * 1024 + 10];
int ucAddress=65;
int wBlock=2;

GetDriveString(j);
j[0] ='H';
GetDriveTypeStr(j,strType);
GetDriveHandle(j,&hDevice);
GetDriveGeometry(hDevice, j, Dgeometry);
if(ScsiPassthrough(hDevice,ucAddress,wBlock))
    printf("%d,%d",ucAddress,wBlock);
CloseDriveHandle(hDevice);
while(1);

}

  • 写回答

2条回答 默认 最新

  • shen_wei 2017-06-02 08:47
    关注
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 (标签-STM32|关键词-智能小车)
  • ¥20 关于#stm32#的问题,请各位专家解答!
  • ¥15 (标签-python)
  • ¥15 第一个已完成,求第二个做法
  • ¥20 搭建awx,试了很多版本都有错
  • ¥15 java corba的客户端该如何指定使用本地某个固定IP去连接服务端?
  • ¥15 activiti工作流问题,求解答
  • ¥15 有人写过RPA后台管理系统么?
  • ¥15 Bioage计算生物学年龄
  • ¥20 如何将FPGA Alveo U50恢复原来出厂设置哇?