📄 cdio.cpp
字号:
//**********************************************************************
//
// Filename: cdio.cpp
//
// Description:
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to
// use this source code. For a copy of the EULA, please see the
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2005, All Rights Reserved
//
//**********************************************************************
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//**********************************************************************
#include <atamain.h>
#include <CEDDK.h>
#include <oalintr.h>
#include <hwdefs.h>
#include <dbgapi.h>
/*
#define DEBUG
#undef DEBUGMSG
#define DEBUGMSG RETAILMSG
#define ZONE_IOCTL 1
#define ZONE_IO 1
#define ZONE_ERROR 1
#define ZONE_CDROM 1
#define ZONE_DMA 1
*/
DWORD CDisk::AtapiIoctl(PIOREQ pIOReq)
{
DWORD dwError = ERROR_SUCCESS;
DWORD dwBytesReturned = 0;
BOOL fUserMode = ::GetDirectCallerProcessId() != ::GetCurrentProcessId();
BOOL fIsDVD = FALSE;
DEBUGMSG( ZONE_IOCTL, (TEXT("ATAPI:PerformIoctl: %x DeviceId: %x \r\n"),pIOReq->dwCode, m_dwDeviceId));
switch( pIOReq->dwCode)
{
case IOCTL_SCSI_PASS_THROUGH:
{
SCSI_PASS_THROUGH PassThrough = { 0 };
SENSE_DATA SenseData = { 0 };
PSENSE_DATA pSenseData = NULL;
DWORD dwSenseSize = 0;
BOOL fDataIn = FALSE;
SGX_BUF SgxBuf = { 0 };
//
// Validate buffers.
//
if( NULL == pIOReq->pInBuf )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
if( pIOReq->dwInBufSize < sizeof(SCSI_PASS_THROUGH) )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
//
// 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,
pIOReq->pInBuf,
sizeof(SCSI_PASS_THROUGH) ) )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
SgxBuf.sb_buf = pIOReq->pInBuf + PassThrough.DataBufferOffset;
SgxBuf.sb_len = PassThrough.DataTransferLength;
fDataIn = PassThrough.DataIn != 0;
//
// The Test Unit Ready commmand is neither data in/out and will
// have a size of zero. So allow zero length data in.
//
// if( fDataIn && SgxBuf.sb_len == 0 )
// {
// dwError = ERROR_INVALID_PARAMETER;
// break;
// }
//
// Validate that the data buffer looks correct.
//
if( PassThrough.DataTransferLength &&
PassThrough.DataBufferOffset < sizeof(SCSI_PASS_THROUGH) )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
if( PassThrough.DataTransferLength >
pIOReq->dwInBufSize - sizeof(SCSI_PASS_THROUGH) )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
if( pIOReq->dwInBufSize - PassThrough.DataTransferLength <
PassThrough.DataBufferOffset )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
//
// Validate that the sense buffer and the data buffer don't
// overlap.
//
if( PassThrough.DataBufferOffset < PassThrough.SenseInfoOffset &&
PassThrough.DataBufferOffset + PassThrough.DataTransferLength > PassThrough.SenseInfoOffset )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
if( PassThrough.SenseInfoOffset < PassThrough.DataBufferOffset &&
PassThrough.SenseInfoOffset + PassThrough.SenseInfoLength > PassThrough.DataBufferOffset )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
if( PassThrough.SenseInfoOffset == PassThrough.DataBufferOffset &&
PassThrough.SenseInfoOffset != 0 &&
PassThrough.DataTransferLength != 0 )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
if( pIOReq->dwInBufSize -
sizeof(SCSI_PASS_THROUGH) -
PassThrough.DataTransferLength <
PassThrough.SenseInfoLength )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
if( PassThrough.SenseInfoLength &&
PassThrough.SenseInfoOffset < sizeof(SCSI_PASS_THROUGH) )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
//
// Determine the size of the sense info to return.
//
dwSenseSize = PassThrough.SenseInfoLength;
if( pIOReq->dwInBufSize - sizeof(SCSI_PASS_THROUGH) < dwSenseSize )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
pSenseData = (PSENSE_DATA)(pIOReq->pInBuf + PassThrough.SenseInfoOffset);
if (FALSE == AtapiIsUnitReadyEx()) {
dwError = ERROR_NOT_READY;
//
// We need to let the Load medium pass through, as well as
// GET CONFIGURATION.
//
if( ((PassThrough.Cdb[0] != SCSIOP_START_STOP_UNIT) ||
(PassThrough.Cdb[4] & 1 ) == 0 ) &&
(PassThrough.Cdb[0] != SCSIOP_GET_CONFIGURATION) )
{
if( dwSenseSize && AtapiGetSenseInfo( &SenseData ) )
{
CeSafeCopyMemory( pSenseData, &SenseData, dwSenseSize );
}
break;
}
}
dwError = ScsiPassThrough( PassThrough,
&SgxBuf,
&SenseData,
&dwBytesReturned,
SgxBuf.sb_len == 0 );
if( dwError != ERROR_SUCCESS )
{
if( dwSenseSize )
{
CeSafeCopyMemory( pSenseData, &SenseData, dwSenseSize );
}
}
CeSafeCopyMemory( pIOReq->pBytesReturned, &dwBytesReturned, sizeof(dwBytesReturned) );
break;
}
case IOCTL_SCSI_PASS_THROUGH_DIRECT:
{
PSCSI_PASS_THROUGH_DIRECT pPassThroughDirect = NULL;
PSENSE_DATA pSenseData = NULL;
DWORD dwSenseSize = 0;
SENSE_DATA SenseData = { 0 };
SGX_BUF SgxBuf = { 0 };
BOOL fDataIn = FALSE;
//
// Validate buffers.
//
if( NULL == pIOReq->pInBuf )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
if( pIOReq->dwInBufSize < sizeof(SCSI_PASS_THROUGH_DIRECT) )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
pPassThroughDirect = (PSCSI_PASS_THROUGH_DIRECT)pIOReq->pInBuf;
//
// The pass through buffer could be changed at any time and we need
// to make sure that we don't puke if this happens.
//
__try
{
SgxBuf.sb_buf = (PUCHAR)pPassThroughDirect->DataBuffer;
SgxBuf.sb_len = pPassThroughDirect->DataTransferLength;
fDataIn = pPassThroughDirect->DataIn != 0;
if( fUserMode && !::IsValidUsrPtr( SgxBuf.sb_buf,
SgxBuf.sb_len,
fDataIn ? TRUE : FALSE ) )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
dwSenseSize = pPassThroughDirect->SenseInfoLength;
if( pIOReq->dwInBufSize - sizeof(SCSI_PASS_THROUGH_DIRECT) < dwSenseSize )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
pSenseData = (PSENSE_DATA)(pIOReq->pInBuf + pPassThroughDirect->SenseInfoOffset);
if( dwSenseSize > sizeof(SENSE_DATA) )
{
dwSenseSize = sizeof(SENSE_DATA);
}
if (FALSE == AtapiIsUnitReadyEx()) {
//
// We need to let the Load medium pass through, as well as
// GET CONFIGURATION.
//
if( ((pPassThroughDirect->Cdb[0] != SCSIOP_START_STOP_UNIT) ||
(pPassThroughDirect->Cdb[4] & 1 ) == 0 ) &&
(pPassThroughDirect->Cdb[0] != SCSIOP_GET_CONFIGURATION) )
{
dwError = ERROR_NOT_READY;
if( dwSenseSize && AtapiGetSenseInfo( &SenseData ) )
{
CeSafeCopyMemory( pSenseData, &SenseData, dwSenseSize );
}
break;
}
}
if( !AtapiSendCommand( (PATAPI_COMMAND_PACKET)pPassThroughDirect->Cdb,
0,
FALSE ) )
{
if( dwSenseSize )
{
AtapiGetSenseInfo( &SenseData );
CopyMemory( pSenseData, &SenseData, dwSenseSize );
}
AtapiDumpSenseData();
dwError = ERROR_GEN_FAILURE;
break;
}
if (fDataIn)
{
if( !AtapiReceiveData( &SgxBuf,
1,
&dwBytesReturned
) )
{
if( dwSenseSize )
{
AtapiGetSenseInfo( &SenseData );
CopyMemory( pSenseData, &SenseData, dwSenseSize );
AtapiDumpSenseData( );
} else {
AtapiDumpSenseData();
}
dwError = ERROR_GEN_FAILURE;
break;
}
}
else
{
if( !AtapiSendData( &SgxBuf,
1,
&dwBytesReturned ) )
{
if( dwSenseSize )
{
AtapiGetSenseInfo( &SenseData );
CopyMemory( pSenseData, &SenseData, dwSenseSize );
AtapiDumpSenseData();
} else {
AtapiDumpSenseData();
}
dwError = ERROR_GEN_FAILURE;
break;
}
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
dwError = ERROR_INVALID_PARAMETER;
break;
}
CeSafeCopyMemory( pIOReq->pBytesReturned,
&dwBytesReturned,
sizeof(dwBytesReturned) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -