我正在尝试使用SCSI命令从我的物理驱动器中读取扇区。
我参考了别人的代码并修改了一些,下面是代码。
#include <stddef.h>
#include <stdio.h>
#include <iostream>
#include <windows.h>
#include <winioctl.h>
#define ULONG_PTR ULONG
//#include <ntddscsi.h> // SDK
//#include <spti.h>
#define wszDrive "\\\\.\\PhysicalDrive1"
// by using CreateFileW(), we need to add a L(means wchar_t) before the wszDrive string
#define SPT_CDB_LENGTH 32
#define SPT_SENSE_LENGTH 32
#define SPTWB_DATA_LENGTH 512
#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
//
// NtDeviceIoControlFile IoControlCode values for this device.
//
// Warning: Remember that the low two bits of the code specify how the
// buffers are passed to the driver!
//
#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//
// Define values for pass-through DataIn field.
//
#define SCSI_IOCTL_DATA_OUT 0
#define SCSI_IOCTL_DATA_IN 1
#define SCSI_IOCTL_DATA_UNSPECIFIED 2
typedef struct _SCSI_PASS_THROUGH_DIRECT {
USHORT Length;// contains the value of sizeof(SCSI_PASS_THROUGH_DIRECT)
UCHAR ScsiStatus;// reports the SCSI status that was returned by the HBA or the target device.
UCHAR PathId;// indicate the SCSI port or bus for the request
UCHAR TargetId;// indicates the target controller or device on the bus
UCHAR Lun;// indicates the logical unit number of the device
UCHAR CdbLength;//indicates the size in bytes of the SCSI command descriptor block
UCHAR SenseInfoLength;// indicates the size in bytes of the request-sense buffer
UCHAR DataIn;// indicates whether the SCSI command will read(SCSI_IOCTL_DATA_IN) or write(SCSI_IOCTL_DATA_OUT) data, or no data transferred(SCSI_IOCTL_DATA_UNSPECIFIED)
ULONG DataTransferLength;//indicates the size in bytes of the data buffer.
ULONG TimeOutValue;// indicates the interval in seconds that the request can execute before the OS-specific port driver might consider it timed out.
PVOID DataBuffer;// pointer to the data buffer
ULONG SenseInfoOffset;// contains an offset from the beginning of this structure to the request-sense buffer.
UCHAR Cdb[16];// specifies the SCSI command descriptor block to be sent to the target drive.
}SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
int main()
{
HANDLE hDevice = INVALID_HANDLE_VALUE;
SCSI_PASS_THROUGH_DIRECT sptd;
ULONG length = 0;
DWORD bytesReturn;
BYTE myBuffer[512];
int iRet;
hDevice = CreateFile (wszDrive,
GENERIC_READ, // dwDesiredAccess: GENERIC_READ means allow read access
FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode: FILE_SHARE_READ | FILE_SHARE_WRITE means allow shared access
NULL, // lpSecurityAttributes: points to a SECURITY_ATTRIBUTE structure
OPEN_EXISTING, // dwCreationDisposition: OPEN_EXISTING(the opening file should be already existing)
0, // dwFlagsAndAttributes: some attributes
NULL); // hTemplateFile: if not 0, it points to a file handler. The newly created file will copy the attributes from this file.
if(hDevice == INVALID_HANDLE_VALUE)
{
printf("Get disk handle failed\n");
return 0;
}
else
{
printf("Get disk handle successfully\n");
}
int posSector = 14; //starting at sector 14
int readSectors = 1 ; // read 1 sector
ZeroMemory(&sptd, sizeof(SCSI_PASS_THROUGH_DIRECT));
sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
sptd.PathId = 0;
sptd.TargetId = 1;
sptd.Lun = 0;
sptd.CdbLength = 10;
sptd.DataIn = SCSI_IOCTL_DATA_IN;
sptd.SenseInfoLength = 24;
sptd.DataTransferLength = 512 * readSectors;
sptd.TimeOutValue = 2;
sptd.DataBuffer = myBuffer;
sptd.Cdb[0] = 0x28 ;
sptd.Cdb[2] = (posSector>>24)&0xff; // start at sector posSector
sptd.Cdb[3] = (posSector>>16)&0xff;
sptd.Cdb[4] = (posSector>>8)&0xff;
sptd.Cdb[5] = posSector&0xff;
sptd.Cdb[7] = (readSectors>>8)&0xff;
sptd.Cdb[8] = readSectors&0xff; //
length = sizeof(SCSI_PASS_THROUGH_DIRECT);
iRet = DeviceIoControl(hDevice,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
&sptd,
length,
&sptd,
length,
&bytesReturn,
NULL);
if (0 == iRet)
{
printf("Get disk data failed\n");
printf("Error message: %u\n", GetLastError());
return 0;
}
CloseHandle(hDevice);
return 0;
}
我可以得到句柄,我想把一个SCSI_PASS_THROUGH_DIRECT结构传递给设备。
我读了微软的文档,但仍然不明白SCSI_PASS_THROUGH_DIRECT的参数(特别是CDB)应该如何设置。
从GetLastError()获取的错误代码是5(访问被拒绝)。
有没有人可以解释一下或者给我一些参考链接来阅读?谢谢。
发布于 2021-03-22 19:33:30
在Administrator下运行您的代码。
访问实体磁盘需要管理员的权限。
https://stackoverflow.com/questions/66745070
复制相似问题