From: Akihiro Sagawa sagawa.aki@gmail.com
--- dlls/ntdll/unix/cdrom.c | 76 +++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 33 deletions(-)
diff --git a/dlls/ntdll/unix/cdrom.c b/dlls/ntdll/unix/cdrom.c index 9464b752b57..6fc444dee31 100644 --- a/dlls/ntdll/unix/cdrom.c +++ b/dlls/ntdll/unix/cdrom.c @@ -1598,7 +1598,7 @@ static NTSTATUS CDROM_RawRead(int fd, const RAW_READ_INFO* raw, void* buffer, DW * Implements IOCTL_SCSI_PASS_THROUGH_DIRECT * */ -static NTSTATUS CDROM_ScsiPassThroughDirect(int fd, PSCSI_PASS_THROUGH_DIRECT pPacket) +static NTSTATUS CDROM_ScsiPassThroughDirect(int fd, const SCSI_PASS_THROUGH_DIRECT *in_pkt, SCSI_PASS_THROUGH_DIRECT *out_pkt) { int ret = STATUS_NOT_SUPPORTED; #ifdef HAVE_SG_IO_HDR_T_INTERFACE_ID @@ -1609,33 +1609,33 @@ static NTSTATUS CDROM_ScsiPassThroughDirect(int fd, PSCSI_PASS_THROUGH_DIRECT pP int io; #endif
- if (pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT)) + if (in_pkt->Length < sizeof(SCSI_PASS_THROUGH_DIRECT)) return STATUS_BUFFER_TOO_SMALL;
- if (pPacket->CdbLength > 16) + if (in_pkt->CdbLength > 16) return STATUS_INVALID_PARAMETER;
#ifdef SENSEBUFLEN - if (pPacket->SenseInfoLength > SENSEBUFLEN) + if (in_pkt->SenseInfoLength > SENSEBUFLEN) return STATUS_INVALID_PARAMETER; #endif
- if (pPacket->DataTransferLength > 0 && !pPacket->DataBuffer) + if (in_pkt->DataTransferLength > 0 && !in_pkt->DataBuffer) return STATUS_INVALID_PARAMETER;
#ifdef HAVE_SG_IO_HDR_T_INTERFACE_ID RtlZeroMemory(&cmd, sizeof(cmd));
cmd.interface_id = 'S'; - cmd.cmd_len = pPacket->CdbLength; - cmd.mx_sb_len = pPacket->SenseInfoLength; - cmd.dxfer_len = pPacket->DataTransferLength; - cmd.dxferp = pPacket->DataBuffer; - cmd.cmdp = pPacket->Cdb; - cmd.sbp = (unsigned char*)pPacket + pPacket->SenseInfoOffset; - cmd.timeout = pPacket->TimeOutValue*1000; + cmd.cmd_len = in_pkt->CdbLength; + cmd.mx_sb_len = in_pkt->SenseInfoLength; + cmd.dxfer_len = in_pkt->DataTransferLength; + cmd.dxferp = in_pkt->DataBuffer; + cmd.cmdp = (unsigned char*)in_pkt->Cdb; + cmd.sbp = (unsigned char*)out_pkt + in_pkt->SenseInfoOffset; + cmd.timeout = in_pkt->TimeOutValue*1000;
- switch (pPacket->DataIn) + switch (in_pkt->DataIn) { case SCSI_IOCTL_DATA_IN: cmd.dxfer_direction = SG_DXFER_FROM_DEV; @@ -1652,25 +1652,25 @@ static NTSTATUS CDROM_ScsiPassThroughDirect(int fd, PSCSI_PASS_THROUGH_DIRECT pP
io = ioctl(fd, SG_IO, &cmd);
- pPacket->ScsiStatus = cmd.status; - pPacket->DataTransferLength -= cmd.resid; - pPacket->SenseInfoLength = cmd.sb_len_wr; + out_pkt->ScsiStatus = cmd.status; + out_pkt->DataTransferLength = in_pkt->DataTransferLength - cmd.resid; + out_pkt->SenseInfoLength = cmd.sb_len_wr;
ret = CDROM_GetStatusCode(io);
#elif defined(__APPLE__)
memset(&cmd, 0, sizeof(cmd)); - memcpy(cmd.cdb, pPacket->Cdb, pPacket->CdbLength); + memcpy(cmd.cdb, in_pkt->Cdb, in_pkt->CdbLength);
- cmd.cdbSize = pPacket->CdbLength; - cmd.buffer = pPacket->DataBuffer; - cmd.bufferSize = pPacket->DataTransferLength; - cmd.sense = (char*)pPacket + pPacket->SenseInfoOffset; - cmd.senseLen = pPacket->SenseInfoLength; - cmd.timeout = pPacket->TimeOutValue*1000; /* in milliseconds */ + cmd.cdbSize = in_pkt->CdbLength; + cmd.buffer = in_pkt->DataBuffer; + cmd.bufferSize = in_pkt->DataTransferLength; + cmd.sense = (char*)out_pkt + in_pkt->SenseInfoOffset; + cmd.senseLen = in_pkt->SenseInfoLength; + cmd.timeout = in_pkt->TimeOutValue*1000; /* in milliseconds */
- switch (pPacket->DataIn) + switch (in_pkt->DataIn) { case SCSI_IOCTL_DATA_OUT: cmd.direction = kSCSIDataTransfer_FromInitiatorToTarget; @@ -1693,29 +1693,39 @@ static NTSTATUS CDROM_ScsiPassThroughDirect(int fd, PSCSI_PASS_THROUGH_DIRECT pP switch (cmd.status) { case kSCSITaskStatus_TaskTimeoutOccurred: return STATUS_TIMEOUT; - break; case kSCSITaskStatus_ProtocolTimeoutOccurred: return STATUS_IO_TIMEOUT; - break; case kSCSITaskStatus_DeviceNotResponding: return STATUS_DEVICE_BUSY; - break; case kSCSITaskStatus_DeviceNotPresent: return STATUS_NO_SUCH_DEVICE; - break; case kSCSITaskStatus_DeliveryFailure: return STATUS_DEVICE_PROTOCOL_ERROR; - break; case kSCSITaskStatus_No_Status: default: return STATUS_UNSUCCESSFUL; - break; } }
if (cmd.status != kSCSITaskStatus_No_Status) - pPacket->ScsiStatus = cmd.status; + out_pkt->ScsiStatus = cmd.status;
ret = CDROM_GetStatusCode(io); + + /* FIXME: Update DataTransferLength and SenseInfoLength */ #endif + if (ret == STATUS_SUCCESS) + { + out_pkt->Length = sizeof(*out_pkt); + if (out_pkt != in_pkt) + { + out_pkt->CdbLength = in_pkt->CdbLength; + out_pkt->DataIn = in_pkt->DataIn; + out_pkt->TimeOutValue = in_pkt->TimeOutValue; + out_pkt->DataBuffer = in_pkt->DataBuffer; + out_pkt->SenseInfoOffset = in_pkt->SenseInfoOffset; + memcpy(out_pkt->Cdb, in_pkt->Cdb, sizeof(in_pkt->Cdb)); + } + } + return ret; }
@@ -3017,9 +3027,9 @@ NTSTATUS cdrom_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc break; case IOCTL_SCSI_PASS_THROUGH_DIRECT: sz = sizeof(SCSI_PASS_THROUGH_DIRECT); - if (out_buffer == NULL) status = STATUS_INVALID_PARAMETER; + if (in_buffer == NULL || out_buffer == NULL) status = STATUS_INVALID_PARAMETER; else if (out_size < sizeof(SCSI_PASS_THROUGH_DIRECT)) status = STATUS_BUFFER_TOO_SMALL; - else status = CDROM_ScsiPassThroughDirect(fd, out_buffer); + else status = CDROM_ScsiPassThroughDirect(fd, in_buffer, out_buffer); break; case IOCTL_SCSI_PASS_THROUGH: if (in_wow64_call())