-
-
Save GXTX/f501911ab216cc7569b0576f773bd520 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define REPS 200 | |
// http://www.ioctls.net/ | |
#define IOCTL_SCSI_PASS_THROUGH_DIRECT 0x4D014 | |
#define SCSI_IOCTL_DATA_IN 1 // read data | |
#define SCSIOP_READ 0x28 | |
typedef struct _SCSI_PASS_THROUGH_DIRECT | |
{ | |
USHORT Length; | |
UCHAR ScsiStatus; | |
UCHAR PathId; | |
UCHAR TargetId; | |
UCHAR Lun; | |
UCHAR CdbLength; | |
UCHAR SenseInfoLength; | |
UCHAR DataIn; | |
ULONG DataTransferLength; | |
ULONG TimeOutValue; | |
PVOID DataBuffer; | |
ULONG SenseInfoOffset; | |
UCHAR Cdb[16]; | |
} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; | |
#pragma pack(push, scsi, 1) | |
typedef union _CDB | |
{ | |
struct _CDB10 { | |
UCHAR OperationCode; | |
UCHAR RelativeAddress : 1; | |
UCHAR Reserved1 : 2; | |
UCHAR ForceUnitAccess : 1; | |
UCHAR DisablePageOut : 1; | |
UCHAR Lun : 3; | |
//UCHAR LBA[4]; | |
ULONG LBA; | |
UCHAR Reserved2; | |
//UCHAR TransferBlocks[2]; | |
USHORT TransferBlocks; | |
UCHAR Control; | |
} CDB10, *PCDB10; | |
} CDB, *PCDB; | |
#pragma pack(pop, scsi) | |
FILE_FS_SIZE_INFORMATION GetGeometry(ANSI_STRING dev_name) | |
{ | |
HANDLE handle; | |
NTSTATUS status; | |
IO_STATUS_BLOCK io_status; | |
OBJECT_ATTRIBUTES obj_attr; | |
FILE_FS_SIZE_INFORMATION size = {}; | |
InitializeObjectAttributes(&obj_attr, &dev_name, OBJ_CASE_INSENSITIVE, NULL, NULL); | |
status = NtOpenFile(&handle, GENERIC_READ | SYNCHRONIZE, &obj_attr, &io_status, FILE_SHARE_READ, FILE_OPEN_FOR_FREE_SPACE_QUERY | FILE_SYNCHRONOUS_IO_NONALERT); | |
if (!NT_SUCCESS(status)) { | |
debugPrint("Couldn't open device for reading\n"); | |
return size; | |
} | |
NtQueryVolumeInformationFile(handle, &io_status, &size, sizeof(size), FileFsSizeInformation); | |
NtClose(handle); | |
debugPrint("%lld %lld %lu %lu\n", size.TotalAllocationUnits.QuadPart, size.AvailableAllocationUnits.QuadPart, size.SectorsPerAllocationUnit, size.BytesPerSector); | |
Sleep(1000); | |
return size; | |
} | |
void DoRawRead() | |
{ | |
NTSTATUS status; | |
LARGE_INTEGER freq, start, end; | |
PDEVICE_OBJECT pDevice; | |
ULONG returnSize; | |
ANSI_STRING name; | |
char *abc = "\\Device\\CdRom0"; | |
RtlInitAnsiString(&name, abc); | |
status = ObReferenceObjectByName(&name, 0, &IoDeviceObjectType, 0, (void**)&pDevice); | |
if (!NT_SUCCESS(status)) { | |
debugPrint("Couldn't open %s for reading\n", name.Buffer); | |
goto cleanup; | |
} | |
FILE_FS_SIZE_INFORMATION geometry = GetGeometry(name); | |
int size = 1 * geometry.BytesPerSector; | |
int max_sectors = geometry.TotalAllocationUnits.QuadPart / 6; | |
char *buffer = malloc(size + MAX_READ_SECTORS); | |
if (!buffer) { | |
debugPrint("Couldn't allocate buffer memory!\n"); | |
goto cleanup; | |
} | |
SCSI_PASS_THROUGH_DIRECT direct; | |
memset(&direct, 0, sizeof(SCSI_PASS_THROUGH_DIRECT)); | |
direct.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); | |
direct.DataIn = SCSI_IOCTL_DATA_IN; | |
direct.DataBuffer = buffer; | |
direct.DataTransferLength = size; | |
PCDB cdb = (PCDB)&direct.Cdb; | |
cdb->CDB10.OperationCode = SCSIOP_READ; | |
cdb->CDB10.ForceUnitAccess = 1; | |
cdb->CDB10.LBA = __builtin_bswap32(0); | |
cdb->CDB10.TransferBlocks = __builtin_bswap16(1); | |
QueryPerformanceFrequency(&freq); | |
for (int i = 0; i < REPS; i++) { | |
if (__builtin_bswap32(cdb->CDB10.LBA) == max_sectors) { | |
cdb->CDB10.LBA = __builtin_bswap32(0); | |
} else { | |
cdb->CDB10.LBA = __builtin_bswap32(max_sectors); | |
} | |
QueryPerformanceCounter(&start); | |
status = IoSynchronousDeviceIoControlRequest(IOCTL_SCSI_PASS_THROUGH_DIRECT, pDevice, &direct, sizeof(SCSI_PASS_THROUGH_DIRECT), NULL, 0, &returnSize, FALSE); | |
QueryPerformanceCounter(&end); | |
if (!NT_SUCCESS(status)) { | |
debugPrint("\nFailed. %lX\n", status); | |
Sleep(10000); | |
goto cleanup; | |
} else { | |
double speed = size * freq.QuadPart; | |
speed /= (end.QuadPart - start.QuadPart); | |
//speed /= 1000; | |
//speed /= 1024; // KB/s is more useful than B/s | |
debugPrint("Read Block: %lu %lu\n", (ULONG)speed, returnSize); | |
} | |
} | |
cleanup: | |
free(buffer); | |
debugPrint("Finished.\n"); | |
Sleep(10000); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment