2019-10-27 03:58:15 +00:00
|
|
|
/*
|
2020-03-01 05:44:49 +00:00
|
|
|
* This file is part of the Aaru Remote Server.
|
2020-01-03 17:42:13 +00:00
|
|
|
* Copyright (c) 2019-2020 Natalia Portillo.
|
2019-10-27 03:58:15 +00:00
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, version 3.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2020-03-01 05:46:10 +00:00
|
|
|
#include "../aaruremote.h"
|
2019-10-27 13:50:46 +00:00
|
|
|
#include "ntioctl.h"
|
2019-10-27 03:58:15 +00:00
|
|
|
#include "win32.h"
|
|
|
|
|
|
|
|
|
|
#include <stdint.h>
|
2019-10-27 13:50:46 +00:00
|
|
|
#include <windows.h>
|
2019-10-27 12:30:53 +00:00
|
|
|
|
2020-03-01 19:47:15 +00:00
|
|
|
int32_t SendScsiCommand(void* device_ctx,
|
|
|
|
|
char* cdb,
|
|
|
|
|
char* buffer,
|
|
|
|
|
char** sense_buffer,
|
|
|
|
|
uint32_t timeout,
|
|
|
|
|
int32_t direction,
|
|
|
|
|
uint32_t* duration,
|
|
|
|
|
uint32_t* sense,
|
|
|
|
|
uint32_t cdb_len,
|
|
|
|
|
uint32_t* buf_len,
|
|
|
|
|
uint32_t* sense_len)
|
2019-10-27 03:58:15 +00:00
|
|
|
{
|
2020-03-01 19:47:15 +00:00
|
|
|
DeviceContext* ctx = device_ctx;
|
2019-10-27 12:30:53 +00:00
|
|
|
PSCSI_PASS_THROUGH_DIRECT sptd;
|
|
|
|
|
PVOID sptd_and_sense;
|
|
|
|
|
UCHAR dir;
|
|
|
|
|
DWORD sptd_and_sense_len;
|
|
|
|
|
DWORD k = 0;
|
|
|
|
|
DWORD error = 0;
|
|
|
|
|
BOOL hasError;
|
2019-10-27 12:36:25 +00:00
|
|
|
LARGE_INTEGER frequency;
|
|
|
|
|
LARGE_INTEGER start;
|
|
|
|
|
LARGE_INTEGER end;
|
|
|
|
|
DOUBLE interval;
|
2019-10-27 12:30:53 +00:00
|
|
|
|
|
|
|
|
*duration = 0;
|
|
|
|
|
*sense_len = 32;
|
|
|
|
|
sptd_and_sense_len = *sense_len + sizeof(SCSI_PASS_THROUGH_DIRECT);
|
2019-10-27 03:58:15 +00:00
|
|
|
|
|
|
|
|
if(!ctx) return -1;
|
|
|
|
|
|
2019-10-27 12:30:53 +00:00
|
|
|
sptd_and_sense = malloc(sptd_and_sense_len);
|
|
|
|
|
|
|
|
|
|
if(!*sense_buffer) return -1;
|
|
|
|
|
|
|
|
|
|
memset(&sptd_and_sense, 0, sptd_and_sense_len);
|
|
|
|
|
|
|
|
|
|
*sense_buffer = malloc(*sense_len);
|
|
|
|
|
|
|
|
|
|
if(!*sense_buffer)
|
|
|
|
|
{
|
|
|
|
|
free(sptd_and_sense);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(direction)
|
|
|
|
|
{
|
2020-03-01 05:50:46 +00:00
|
|
|
case AARUREMOTE_SCSI_DIRECTION_IN: dir = SCSI_IOCTL_DATA_IN; break;
|
|
|
|
|
case AARUREMOTE_SCSI_DIRECTION_OUT: dir = SCSI_IOCTL_DATA_OUT; break;
|
|
|
|
|
case AARUREMOTE_SCSI_DIRECTION_INOUT:
|
|
|
|
|
case AARUREMOTE_SCSI_DIRECTION_UNSPECIFIED: dir = SCSI_IOCTL_DATA_BIDIRECTIONAL; break;
|
|
|
|
|
case AARUREMOTE_SCSI_DIRECTION_NONE:
|
2019-10-27 12:30:53 +00:00
|
|
|
default: dir = SCSI_IOCTL_DATA_UNSPECIFIED; break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(*sense_buffer, 0, *sense_len);
|
|
|
|
|
|
|
|
|
|
sptd = sptd_and_sense;
|
|
|
|
|
|
2019-10-27 12:36:25 +00:00
|
|
|
QueryPerformanceFrequency(&frequency);
|
|
|
|
|
|
2019-10-27 12:30:53 +00:00
|
|
|
if(cdb_len > 16) cdb_len = 16;
|
|
|
|
|
|
|
|
|
|
memcpy(&sptd->Cdb, cdb, cdb_len);
|
|
|
|
|
sptd->CdbLength = cdb_len;
|
|
|
|
|
sptd->SenseInfoLength = *sense_len;
|
|
|
|
|
sptd->DataIn = dir;
|
|
|
|
|
sptd->DataTransferLength = *buf_len;
|
|
|
|
|
sptd->TimeOutValue = timeout;
|
|
|
|
|
sptd->DataBuffer = buffer;
|
|
|
|
|
sptd->Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
|
|
|
|
|
sptd->SenseInfoOffset = sizeof(SCSI_PASS_THROUGH_DIRECT);
|
|
|
|
|
|
2019-10-27 12:36:25 +00:00
|
|
|
QueryPerformanceCounter(&start);
|
2019-10-27 12:30:53 +00:00
|
|
|
hasError = !DeviceIoControl(ctx->handle,
|
|
|
|
|
IOCTL_SCSI_PASS_THROUGH_DIRECT,
|
|
|
|
|
sptd_and_sense,
|
|
|
|
|
sptd_and_sense_len,
|
|
|
|
|
sptd_and_sense,
|
|
|
|
|
sptd_and_sense_len,
|
|
|
|
|
&k,
|
|
|
|
|
NULL);
|
2019-10-27 12:36:25 +00:00
|
|
|
QueryPerformanceCounter(&end);
|
|
|
|
|
|
|
|
|
|
interval = (DOUBLE)(end.QuadPart - start.QuadPart) / frequency.QuadPart;
|
|
|
|
|
*duration = interval * 1000;
|
2019-10-27 12:30:53 +00:00
|
|
|
|
|
|
|
|
if(hasError) error = GetLastError();
|
|
|
|
|
|
|
|
|
|
*sense = sptd->ScsiStatus != 0;
|
|
|
|
|
memcpy(*sense_buffer, (char*)sptd_and_sense + sizeof(SCSI_PASS_THROUGH_DIRECT), *sense_len);
|
|
|
|
|
|
|
|
|
|
free(sptd_and_sense);
|
|
|
|
|
return error;
|
2019-10-27 03:58:15 +00:00
|
|
|
}
|