📄 disk.c
字号:
dwErr = ERROR_INVALID_PARAMETER;
break;
}
}
break;
}
case IOCTL_SCSI_PASS_THROUGH:
{
//
// This translates the parameters from the IOCTL_SCSI_PASS_THROUGH
// command to those already used by the IOCTL_SCSI_PASSTHROUGH
// command and issues the request in an identical manner.
//
TRANSPORT_COMMAND SafeTransportCommand = {0};
TRANSPORT_DATA SafeTransportData = {0};
LPVOID pCommandBlockOrig = NULL;
SCSI_PASS_THROUGH PassThrough = { 0 };
SENSE_DATA SenseData = { 0 };
PSENSE_DATA pSenseData = NULL;
DWORD dwSenseSize = 0;
BOOL fDataIn = FALSE;
BOOL fCloseCallerBuffer = FALSE;
SafeBytesReturned = 0;
DEBUGMSG(ZONE_DSK_IOCTL, (TEXT("USBDISK6>DSK_IOControl>IOCTL_SCSI_PASS_THROUGH\r\n")));
if (
NULL == pInBuf ||
InBufLen < sizeof(SCSI_PASS_THROUGH))
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
//
// The pass through buffer could be changed at any time and we need
// to make sure that we don't puke if this happens.
//
if( !CeSafeCopyMemory( &PassThrough,
pInBuf,
sizeof(SCSI_PASS_THROUGH) ) )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
fDataIn = PassThrough.DataIn != 0;
//
// Validate that the data buffer looks correct.
//
if( PassThrough.DataTransferLength &&
PassThrough.DataBufferOffset < sizeof(SCSI_PASS_THROUGH) )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
if( PassThrough.DataTransferLength >
InBufLen - sizeof(SCSI_PASS_THROUGH) )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
if( InBufLen - PassThrough.DataTransferLength <
PassThrough.DataBufferOffset )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
//
// Validate that the sense buffer and the data buffer don't
// overlap.
//
if( PassThrough.DataBufferOffset < PassThrough.SenseInfoOffset &&
PassThrough.DataBufferOffset + PassThrough.DataTransferLength > PassThrough.SenseInfoOffset )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
if( PassThrough.SenseInfoOffset < PassThrough.DataBufferOffset &&
PassThrough.SenseInfoOffset + PassThrough.SenseInfoLength > PassThrough.DataBufferOffset )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
if( PassThrough.SenseInfoOffset == PassThrough.DataBufferOffset &&
PassThrough.SenseInfoOffset != 0 &&
PassThrough.DataTransferLength != 0 )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
if( InBufLen -
sizeof(SCSI_PASS_THROUGH) -
PassThrough.DataTransferLength <
PassThrough.SenseInfoLength )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
if( PassThrough.SenseInfoLength &&
PassThrough.SenseInfoOffset < sizeof(SCSI_PASS_THROUGH) )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
//
// Determine the size of the sense info to return.
//
dwSenseSize = PassThrough.SenseInfoLength;
if( InBufLen - sizeof(SCSI_PASS_THROUGH) < dwSenseSize )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
pSenseData = (PSENSE_DATA)(pInBuf + PassThrough.SenseInfoOffset);
SafeTransportCommand.Flags = PassThrough.DataIn ? DATA_IN : DATA_OUT;
SafeTransportCommand.Length = PassThrough.CdbLength;
SafeTransportCommand.Timeout = PassThrough.TimeOutValue;
SafeTransportCommand.CommandBlock = (PVOID)PassThrough.Cdb;
SafeTransportCommand.dwLun = pDevice->Lun;
SafeTransportData.RequestLength = PassThrough.DataTransferLength;
// The data block may be NULL. Map the caller's data block as
// appropriate.
if (0 != PassThrough.DataBufferOffset &&
0 != PassThrough.DataTransferLength) {
if (FAILED(CeOpenCallerBuffer(
&SafeTransportData.DataBlock,
pInBuf + PassThrough.DataBufferOffset,
SafeTransportData.RequestLength,
ARG_IO_PTR,
FALSE))) {
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
fCloseCallerBuffer = TRUE;
}
// Issue command.
dwErr = ScsiPassthrough(pDevice, &SafeTransportCommand, &SafeTransportData);
CleanUp_Pass_Through:
if (fCloseCallerBuffer) {
if (FAILED(CeCloseCallerBuffer(
SafeTransportData.DataBlock,
pInBuf + PassThrough.DataBufferOffset,
SafeTransportData.RequestLength,
ARG_IO_PTR))) {
ASSERT(!"Unexpected failure in CeCloseCallerBuffer");
dwErr = ERROR_GEN_FAILURE;
break;
}
}
if (ERROR_SUCCESS != dwErr) {
DWORD dwError = ERROR_SUCCESS;
SENSE_DATA SenseData= { 0 };
SafeTransportData.RequestLength = sizeof(SENSE_DATA);
SafeTransportData.DataBlock = (PVOID)&SenseData;
dwError = ScsiRequestSense( pDevice, &SafeTransportData, pDevice->Lun );
if( dwError == ERROR_SUCCESS )
{
if( dwSenseSize )
{
CeSafeCopyMemory( pSenseData, &SenseData, sizeof(SenseData) );
}
DEBUGMSG(ZONE_ERR, (TEXT("USBDISK6:IOCTL_SCSI_PASS_THROUGH - SenseData: %x\\%x\\%x\r\n"), SenseData.SenseKey, SenseData.AdditionalSenseCode, SenseData.AdditionalSenseCodeQualifier));
}
else
{
DEBUGMSG(ZONE_ERR, (TEXT("USBDISK6:IOCTL_SCSI_PASS_THROUGH - Unable to retrieve sense data\r\n")));
}
break;
}
if (pdwBytesTransferred) {
if (0 == CeSafeCopyMemory((LPVOID)pdwBytesTransferred, (LPVOID)&SafeTransportData.TransferLength, sizeof(DWORD))) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
}
break;
}
case IOCTL_SCSI_PASS_THROUGH_DIRECT:
{
//
// This translates the parameters from the
// IOCTL_SCSI_PASS_THROUGH_DIRECT command to those already used by
// the IOCTL_SCSI_PASSTHROUGH command and issues the request in an
// identical manner.
//
TRANSPORT_COMMAND SafeTransportCommand = {0};
TRANSPORT_DATA SafeTransportData = {0};
LPVOID pCommandBlockOrig = NULL;
SCSI_PASS_THROUGH_DIRECT PassThrough = { 0 };
PSENSE_DATA pSenseData = NULL;
DWORD dwSenseSize = 0;
SENSE_DATA SenseData = { 0 };
BOOL fDataIn = FALSE;
BOOL fUserMode = GetDirectCallerProcessId() != GetCurrentProcessId();
BOOL fCloseCallerBuffer = FALSE;
SafeBytesReturned = 0;
DEBUGMSG(ZONE_DSK_IOCTL, (TEXT("USBDISK6>DSK_IOControl>IOCTL_SCSI_PASS_THROUGH_DIRECT\r\n")));
if (
NULL == pInBuf ||
InBufLen < sizeof(SCSI_PASS_THROUGH_DIRECT))
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through;
}
//
// The pass through buffer could be changed at any time and we need
// to make sure that we don't puke if this happens.
//
if( !CeSafeCopyMemory( &PassThrough,
pInBuf,
sizeof(SCSI_PASS_THROUGH_DIRECT) ) )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through_Direct;
}
fDataIn = PassThrough.DataIn != 0;
if( fUserMode && !IsKModeAddr( (DWORD)pInBuf ) )
{
if( fUserMode && !IsValidUsrPtr( PassThrough.DataBuffer,
PassThrough.DataTransferLength,
fDataIn ? TRUE : FALSE ) )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through_Direct;
}
}
//
// Determine the size of the sense info to return.
//
dwSenseSize = PassThrough.SenseInfoLength;
if( InBufLen - sizeof(SCSI_PASS_THROUGH) < dwSenseSize )
{
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through_Direct;
}
pSenseData = (PSENSE_DATA)(pInBuf + PassThrough.SenseInfoOffset);
SafeTransportCommand.Flags = PassThrough.DataIn ? DATA_IN : DATA_OUT;
SafeTransportCommand.Length = PassThrough.CdbLength;
SafeTransportCommand.Timeout = PassThrough.TimeOutValue;
SafeTransportCommand.CommandBlock = (PVOID)PassThrough.Cdb;
SafeTransportCommand.dwLun = pDevice->Lun;
SafeTransportData.RequestLength = PassThrough.DataTransferLength;
// The data block may be NULL. Map the caller's data block as
// appropriate.
if (0 != PassThrough.DataBuffer &&
0 != SafeTransportData.RequestLength) {
if (FAILED(CeOpenCallerBuffer(
&SafeTransportData.DataBlock,
PassThrough.DataBuffer,
SafeTransportData.RequestLength,
ARG_IO_PTR,
FALSE))) {
dwErr = ERROR_INVALID_PARAMETER;
goto CleanUp_Pass_Through_Direct;
}
fCloseCallerBuffer = TRUE;
}
// Issue command.
dwErr = ScsiPassthrough(pDevice, &SafeTransportCommand, &SafeTransportData);
CleanUp_Pass_Through_Direct:
if (fCloseCallerBuffer) {
if (FAILED(CeCloseCallerBuffer(
SafeTransportData.DataBlock,
PassThrough.DataBuffer,
SafeTransportData.RequestLength,
ARG_IO_PTR))) {
ASSERT(!"Unexpected failure in CeCloseCallerBuffer");
dwErr = ERROR_GEN_FAILURE;
break;
}
}
if (ERROR_SUCCESS != dwErr) {
DWORD dwError = ERROR_SUCCESS;
SENSE_DATA SenseData= { 0 };
SafeTransportData.RequestLength = sizeof(SENSE_DATA);
SafeTransportData.DataBlock = (PVOID)&SenseData;
dwError = ScsiRequestSense( pDevice, &SafeTransportData, pDevice->Lun );
if( dwError == ERROR_SUCCESS )
{
if( dwSenseSize )
{
CeSafeCopyMemory( pSenseData, &SenseData, sizeof(SenseData) );
}
DEBUGMSG(ZONE_ERR, (TEXT("USBDISK6:IOCTL_SCSI_PASS_THROUGH - SenseData: %x\\%x\\%x\r\n"), SenseData.SenseKey, SenseData.AdditionalSenseCode, SenseData.AdditionalSenseCodeQualifier));
}
else
{
DEBUGMSG(ZONE_ERR, (TEXT("USBDISK6:IOCTL_SCSI_PASS_THROUGH - Unable to retrieve sense data\r\n")));
}
break;
}
if (pdwBytesTransferred) {
if (0 == CeSafeCopyMemory((LPVOID)pdwBytesTransferred, (LPVOID)&SafeTransportData.TransferLength, sizeof(DWORD))) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
}
break;
}
case IOCTL_CDROM_READ_SG:
{
DWORD SgCount = 0;
PCDROM_READ pUnsafeCDROMRead = (PCDROM_READ)pInBuf;
BYTE rgbBuffer[sizeof(SG_REQ) + ((MAX_SG_BUF - 1) * sizeof(SG_BUF))] = {0};
PSG_REQ pPseudoUnsafeIoRequest = (PSG_REQ)rgbBuffer;
DWORD i = 0;
SafeBytesReturned = 0;
DEBUGMSG(ZONE_DSK_IOCTL, (TEXT("USBDISK6>DSK_IOControl>IOCTL_CDROM_READ_SG\r\n")));
if (NULL == pInBuf) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
if (InBufLen < sizeof(CDROM_READ)) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
if (SCSI_DEVICE_CDROM != pDevice->DeviceType) {
dwErr = ERROR_NOT_SUPPORTED;
break;
}
if (pDevice->Flags.Busy) {
dwErr = ERROR_BUSY;
break;
}
// Mark device as busy.
pDevice->Flags.Busy = TRUE;
// Prepare device for I/O.
dwErr = ScsiUnitAttention(pDevice, pDevice->Lun);
if (ERROR_SUCCESS != dwErr) {
if (!pDevice->Flags.MediumPresent) {
DEBUGMSG(ZONE_ERR, (TEXT("USBDISK6>DSK_IOControl> The device does not contain any media\r\n")));
dwErr = ERROR_MEDIA_NOT_AVAILABLE;
}
pDevice->Flags.Busy = FALSE;
break;
}
// Convert the supplied CDROM_READ to a SG_REQ. Note that, we
// don't support CD-DA formatted CDs or raw reads.
// TrackMode is TBD
if (
CDDA == pUnsafeCDROMRead->TrackMode ||
CDROM_ADDR_LBA != pUnsafeCDROMRead->StartAddr.Mode ||
pUnsafeCDROMRead->bRawMode
) {
dwErr = ERROR_NOT_SUPPORTED;
pDevice->Flags.Busy = FALSE;
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -