⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disk.c

📁 WIN CE 下storage 存储外设的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
                    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 + -