http://code.msdn.microsoft.com/SCSI-Pass-Through-a906ceef/sourcecode?fileId=59048&pathId=1919073465

http://code.msdn.microsoft.com/SCSI-Pass-Through-a906ceef/file/59048/13/SCSI%20Pass-Through%20Interface%20Tool.zip

/*++ 

 Copyright (c) 1992  Microsoft Corporation 

 Module Name: 

 spti.h 

 Abstract: 

 These are the structures and defines that are used in the
SPTI.C. Author: Revision History: --*/ #define SPT_CDB_LENGTH 32
#define SPT_SENSE_LENGTH 32
#define SPTWB_DATA_LENGTH 512 typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS
{
SCSI_PASS_THROUGH spt;
ULONG Filler; // realign buffers to double word boundary
UCHAR ucSenseBuf[ SPT_SENSE_LENGTH ];
UCHAR ucDataBuf[ SPTWB_DATA_LENGTH ];
} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER
{
SCSI_PASS_THROUGH_DIRECT sptd;
ULONG Filler; // realign buffer to double word boundary
UCHAR ucSenseBuf[ SPT_SENSE_LENGTH ];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS_EX
{
SCSI_PASS_THROUGH_EX spt;
UCHAR ucCdbBuf[ SPT_CDB_LENGTH - ]; // cushion for spt.Cdb
ULONG Filler; // realign buffers to double word boundary
STOR_ADDR_BTL8 StorAddress;
UCHAR ucSenseBuf[ SPT_SENSE_LENGTH ];
UCHAR ucDataBuf[ SPTWB_DATA_LENGTH ]; // buffer for DataIn or DataOut
} SCSI_PASS_THROUGH_WITH_BUFFERS_EX, *PSCSI_PASS_THROUGH_WITH_BUFFERS_EX; typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX
{
SCSI_PASS_THROUGH_DIRECT_EX sptd;
UCHAR ucCdbBuf[ SPT_CDB_LENGTH - ]; // cushion for sptd.Cdb
ULONG Filler; // realign buffer to double word boundary
STOR_ADDR_BTL8 StorAddress;
UCHAR ucSenseBuf[ SPT_SENSE_LENGTH ];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX,
*PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX; VOID
PrintError( ULONG ); VOID
PrintDataBuffer(_In_reads_(BufferLength) PUCHAR DataBuffer, _In_ ULONG BufferLength); VOID
PrintInquiryData( PVOID ); _Success_(return != NULL)
_Post_writable_byte_size_(size)
PUCHAR
AllocateAlignedBuffer(_In_ ULONG size, _In_ ULONG AlignmentMask,
_Outptr_result_maybenull_ PUCHAR * pUnAlignedBuffer); VOID
PrintStatusResults( BOOL, DWORD, PSCSI_PASS_THROUGH_WITH_BUFFERS, ULONG ); VOID
PrintSenseInfo( PSCSI_PASS_THROUGH_WITH_BUFFERS ); VOID
PrintStatusResultsEx( BOOL, DWORD, PSCSI_PASS_THROUGH_WITH_BUFFERS_EX, ULONG ); VOID
PrintSenseInfoEx( PSCSI_PASS_THROUGH_WITH_BUFFERS_EX ); _Success_(return)
BOOL
QueryPropertyForDevice(_In_ HANDLE, _Out_ PULONG, _Out_ PUCHAR); //
// Command Descriptor Block constants.
// #define CDB6GENERIC_LENGTH 6
#define CDB10GENERIC_LENGTH 10 #define SETBITON 1
#define SETBITOFF 0
/*++ 

Copyright (c) 1992  Microsoft Corporation 

Module Name: 

    spti.c 

Abstract: 

    Win32 application that can communicate directly with SCSI devices via
IOCTLs. Author: Environment: User mode. Notes: Revision History: --*/ #include <windows.h>
#include <devioctl.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <strsafe.h>
#include <intsafe.h>
#define _NTSCSI_USER_MODE_
#include <scsi.h>
#include "spti.h" #define NAME_COUNT 25 #define BOOLEAN_TO_STRING(_b_) \
( (_b_) ? "True" : "False" ) #if defined(_X86_)
#define PAGE_SIZE 0x1000
#define PAGE_SHIFT 12L
#elif defined(_AMD64_)
#define PAGE_SIZE 0x1000
#define PAGE_SHIFT 12L
#elif defined(_IA64_)
#define PAGE_SIZE 0x2000
#define PAGE_SHIFT 13L
#else
// undefined platform?
#define PAGE_SIZE 0x1000
#define PAGE_SHIFT 12L
#endif LPCSTR BusTypeStrings[] = {
"Unknown",
"Scsi",
"Atapi",
"Ata",
"",
"Ssa",
"Fibre",
"Usb",
"RAID",
"Not Defined",
};
#define NUMBER_OF_BUS_TYPE_STRINGS (sizeof(BusTypeStrings)/sizeof(BusTypeStrings[0])) VOID
__cdecl
main(
_In_ int argc,
_In_z_ char *argv[]
) {
BOOL status = ;
DWORD accessMode = , shareMode = ;
HANDLE fileHandle = NULL;
ULONG alignmentMask = ; // default == no alignment requirement
UCHAR srbType = ; // default == SRB_TYPE_SCSI_REQUEST_BLOCK
PUCHAR dataBuffer = NULL;
PUCHAR pUnAlignedBuffer = NULL;
SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptdwb;
SCSI_PASS_THROUGH_WITH_BUFFERS_EX sptwb_ex;
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX sptdwb_ex;
CHAR string[NAME_COUNT]; ULONG length = ,
errorCode = ,
returned = ,
sectorSize = ; if ((argc < ) || (argc > )) {
printf("Usage: %s <port-name> [-mode]\n", argv[] );
printf("Examples:\n");
printf(" spti g: (open the disk class driver in SHARED READ/WRITE mode)\n");
printf(" spti Scsi2: (open the miniport driver for the 3rd host adapter)\n");
printf(" spti Tape0 w (open the tape class driver in SHARED WRITE mode)\n");
printf(" spti i: c (open the CD-ROM class driver in SHARED READ mode)\n");
return;
} StringCbPrintf(string, sizeof(string), "\\\\.\\%s", argv[]); shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; // default
accessMode = GENERIC_WRITE | GENERIC_READ; // default if (argc == ) { switch(tolower(argv[][])) {
case 'r':
shareMode = FILE_SHARE_READ;
break; case 'w':
shareMode = FILE_SHARE_WRITE;
break; case 'c':
shareMode = FILE_SHARE_READ;
sectorSize = ;
break; default:
printf("%s is an invalid mode.\n", argv[]);
puts("\tr = read");
puts("\tw = write");
puts("\tc = read CD (2048 byte sector mode)");
return;
}
} fileHandle = CreateFile(string,
accessMode,
shareMode,
NULL,
OPEN_EXISTING,
,
NULL); if (fileHandle == INVALID_HANDLE_VALUE) {
errorCode = GetLastError();
printf("Error opening %s. Error: %d\n",
string, errorCode);
PrintError(errorCode);
return;
} //
// Get the alignment requirements
// status = QueryPropertyForDevice(fileHandle, &alignmentMask, &srbType);
if (!status ) {
errorCode = GetLastError();
printf("Error getting device and/or adapter properties; "
"error was %d\n", errorCode);
PrintError(errorCode);
CloseHandle(fileHandle);
return;
} printf("\n"
" ***** Detected Alignment Mask *****\n"
" ***** was %08x *****\n\n\n",
alignmentMask); //
// Send SCSI Pass Through
// puts(" ***** MODE SENSE -- return all pages *****");
puts(" ***** with SenseInfo buffer *****\n"); if(srbType == )
{
ZeroMemory(&sptwb_ex,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX));
sptwb_ex.spt.Version = ;
sptwb_ex.spt.Length = sizeof(SCSI_PASS_THROUGH_EX);
sptwb_ex.spt.ScsiStatus = ;
sptwb_ex.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb_ex.spt.StorAddressLength = sizeof(STOR_ADDR_BTL8);
sptwb_ex.spt.SenseInfoLength = SPT_SENSE_LENGTH;
sptwb_ex.spt.DataOutTransferLength = ;
sptwb_ex.spt.DataInTransferLength = ;
sptwb_ex.spt.DataDirection = SCSI_IOCTL_DATA_IN;
sptwb_ex.spt.TimeOutValue = ;
sptwb_ex.spt.StorAddressOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,StorAddress);
sptwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
sptwb_ex.StorAddress.Port = ;
sptwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
sptwb_ex.StorAddress.Path = ;
sptwb_ex.StorAddress.Target = ;
sptwb_ex.StorAddress.Lun = ;
sptwb_ex.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucSenseBuf);
sptwb_ex.spt.DataOutBufferOffset = ;
sptwb_ex.spt.DataInBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf);
sptwb_ex.spt.Cdb[] = SCSIOP_MODE_SENSE;
sptwb_ex.spt.Cdb[] = MODE_SENSE_RETURN_ALL;
sptwb_ex.spt.Cdb[] = ;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf) +
sptwb_ex.spt.DataInTransferLength; status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH_EX,
&sptwb_ex,
sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX),
&sptwb_ex,
length,
&returned,
FALSE); PrintStatusResultsEx(status,returned,&sptwb_ex,length);
}
else
{
ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.spt.PathId = ;
sptwb.spt.TargetId = ;
sptwb.spt.Lun = ;
sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb.spt.SenseInfoLength = SPT_SENSE_LENGTH;
sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.spt.DataTransferLength = ;
sptwb.spt.TimeOutValue = ;
sptwb.spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
sptwb.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
sptwb.spt.Cdb[] = SCSIOP_MODE_SENSE;
sptwb.spt.Cdb[] = MODE_SENSE_RETURN_ALL;
sptwb.spt.Cdb[] = ;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
sptwb.spt.DataTransferLength; status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
length,
&returned,
FALSE); PrintStatusResults(status,returned,&sptwb,length);
} printf(" ***** MODE SENSE -- return all pages *****\n");
printf(" ***** without SenseInfo buffer *****\n\n"); if(srbType == )
{
ZeroMemory(&sptwb_ex,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX));
sptwb_ex.spt.Version = ;
sptwb_ex.spt.Length = sizeof(SCSI_PASS_THROUGH_EX);
sptwb_ex.spt.ScsiStatus = ;
sptwb_ex.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb_ex.spt.StorAddressLength = sizeof(STOR_ADDR_BTL8);
sptwb_ex.spt.SenseInfoLength = ;
sptwb_ex.spt.DataOutTransferLength = ;
sptwb_ex.spt.DataInTransferLength = ;
sptwb_ex.spt.DataDirection = SCSI_IOCTL_DATA_IN;
sptwb_ex.spt.TimeOutValue = ;
sptwb_ex.spt.StorAddressOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,StorAddress);
sptwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
sptwb_ex.StorAddress.Port = ;
sptwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
sptwb_ex.StorAddress.Path = ;
sptwb_ex.StorAddress.Target = ;
sptwb_ex.StorAddress.Lun = ;
sptwb_ex.spt.SenseInfoOffset = ;
sptwb_ex.spt.DataOutBufferOffset = ;
sptwb_ex.spt.DataInBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf);
sptwb_ex.spt.Cdb[] = SCSIOP_MODE_SENSE;
sptwb_ex.spt.Cdb[] = MODE_SENSE_RETURN_ALL;
sptwb_ex.spt.Cdb[] = ;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf) +
sptwb_ex.spt.DataInTransferLength; status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH_EX,
&sptwb_ex,
sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX),
&sptwb_ex,
length,
&returned,
FALSE); PrintStatusResultsEx(status,returned,&sptwb_ex,length);
}
else
{
ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.spt.PathId = ;
sptwb.spt.TargetId = ;
sptwb.spt.Lun = ;
sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb.spt.SenseInfoLength = ;
sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.spt.DataTransferLength = ;
sptwb.spt.TimeOutValue = ;
sptwb.spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
sptwb.spt.Cdb[] = SCSIOP_MODE_SENSE;
sptwb.spt.Cdb[] = MODE_SENSE_RETURN_ALL;
sptwb.spt.Cdb[] = ;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
sptwb.spt.DataTransferLength; status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
length,
&returned,
FALSE); PrintStatusResults(status,returned,&sptwb,length);
} printf(" ***** TEST UNIT READY *****\n");
printf(" ***** DataInBufferLength = 0 *****\n\n"); if(srbType == )
{
ZeroMemory(&sptwb_ex,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX));
sptwb_ex.spt.Version = ;
sptwb_ex.spt.Length = sizeof(SCSI_PASS_THROUGH_EX);
sptwb_ex.spt.ScsiStatus = ;
sptwb_ex.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb_ex.spt.StorAddressLength = sizeof(STOR_ADDR_BTL8);
sptwb_ex.spt.SenseInfoLength = SPT_SENSE_LENGTH;
sptwb_ex.spt.DataOutTransferLength = ;
sptwb_ex.spt.DataInTransferLength = ;
sptwb_ex.spt.DataDirection = SCSI_IOCTL_DATA_IN;
sptwb_ex.spt.TimeOutValue = ;
sptwb_ex.spt.StorAddressOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,StorAddress);
sptwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
sptwb_ex.StorAddress.Port = ;
sptwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
sptwb_ex.StorAddress.Path = ;
sptwb_ex.StorAddress.Target = ;
sptwb_ex.StorAddress.Lun = ;
sptwb_ex.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucSenseBuf);
sptwb_ex.spt.DataOutBufferOffset = ;
sptwb_ex.spt.DataInBufferOffset = ;
sptwb_ex.spt.Cdb[] = SCSIOP_TEST_UNIT_READY;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf); status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH_EX,
&sptwb_ex,
sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX),
&sptwb_ex,
length,
&returned,
FALSE); PrintStatusResultsEx(status,returned,&sptwb_ex,length);
}
else
{
ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.spt.PathId = ;
sptwb.spt.TargetId = ;
sptwb.spt.Lun = ;
sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb.spt.SenseInfoLength = SPT_SENSE_LENGTH;
sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.spt.DataTransferLength = ;
sptwb.spt.TimeOutValue = ;
sptwb.spt.DataBufferOffset = ;
sptwb.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
sptwb.spt.Cdb[] = SCSIOP_TEST_UNIT_READY;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf); status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
length,
&returned,
FALSE); PrintStatusResults(status,returned,&sptwb,length);
} //
// Do a mode sense with a bad data buffer offset. This will fail.
//
printf(" ***** MODE SENSE -- return all pages *****\n");
printf(" ***** bad DataBufferOffset -- should fail *****\n\n"); if(srbType == )
{
ZeroMemory(&sptwb_ex,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX));
sptwb_ex.spt.Version = ;
sptwb_ex.spt.Length = sizeof(SCSI_PASS_THROUGH_EX);
sptwb_ex.spt.ScsiStatus = ;
sptwb_ex.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb_ex.spt.StorAddressLength = sizeof(STOR_ADDR_BTL8);
sptwb_ex.spt.SenseInfoLength = SPT_SENSE_LENGTH;
sptwb_ex.spt.DataOutTransferLength = ;
sptwb_ex.spt.DataInTransferLength = ;
sptwb_ex.spt.DataDirection = SCSI_IOCTL_DATA_IN;
sptwb_ex.spt.TimeOutValue = ;
sptwb_ex.spt.StorAddressOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,StorAddress);
sptwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
sptwb_ex.StorAddress.Port = ;
sptwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
sptwb_ex.StorAddress.Path = ;
sptwb_ex.StorAddress.Target = ;
sptwb_ex.StorAddress.Lun = ;
sptwb_ex.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucSenseBuf);
sptwb_ex.spt.DataOutBufferOffset = ;
sptwb_ex.spt.DataInBufferOffset = ;
sptwb_ex.spt.Cdb[] = SCSIOP_MODE_SENSE;
sptwb_ex.spt.Cdb[] = MODE_SENSE_RETURN_ALL;
sptwb_ex.spt.Cdb[] = ;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf) +
sptwb_ex.spt.DataInTransferLength; status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH_EX,
&sptwb_ex,
sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX),
&sptwb_ex,
length,
&returned,
FALSE); PrintStatusResultsEx(status,returned,&sptwb_ex,length);
}
else
{
ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.spt.PathId = ;
sptwb.spt.TargetId = ;
sptwb.spt.Lun = ;
sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb.spt.SenseInfoLength = ;
sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.spt.DataTransferLength = ;
sptwb.spt.TimeOutValue = ;
sptwb.spt.DataBufferOffset = ;
sptwb.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
sptwb.spt.Cdb[] = SCSIOP_MODE_SENSE;
sptwb.spt.Cdb[] = MODE_SENSE_RETURN_ALL;
sptwb.spt.Cdb[] = ;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
sptwb.spt.DataTransferLength; status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
length,
&returned,
FALSE); PrintStatusResults(status,returned,&sptwb,length);
} //
// Get caching mode sense page.
//
printf(" ***** MODE SENSE *****\n");
printf(" ***** return caching mode sense page *****\n\n"); if(srbType == )
{
ZeroMemory(&sptwb_ex,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX));
sptwb_ex.spt.Version = ;
sptwb_ex.spt.Length = sizeof(SCSI_PASS_THROUGH_EX);
sptwb_ex.spt.ScsiStatus = ;
sptwb_ex.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb_ex.spt.StorAddressLength = sizeof(STOR_ADDR_BTL8);
sptwb_ex.spt.SenseInfoLength = SPT_SENSE_LENGTH;
sptwb_ex.spt.DataOutTransferLength = ;
sptwb_ex.spt.DataInTransferLength = ;
sptwb_ex.spt.DataDirection = SCSI_IOCTL_DATA_IN;
sptwb_ex.spt.TimeOutValue = ;
sptwb_ex.spt.StorAddressOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,StorAddress);
sptwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
sptwb_ex.StorAddress.Port = ;
sptwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
sptwb_ex.StorAddress.Path = ;
sptwb_ex.StorAddress.Target = ;
sptwb_ex.StorAddress.Lun = ;
sptwb_ex.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucSenseBuf);
sptwb_ex.spt.DataOutBufferOffset = ;
sptwb_ex.spt.DataInBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf);
sptwb_ex.spt.Cdb[] = SCSIOP_MODE_SENSE;
sptwb_ex.spt.Cdb[] = 0x08; // target shall not return any block descriptors
sptwb_ex.spt.Cdb[] = MODE_PAGE_CACHING;
sptwb_ex.spt.Cdb[] = ;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf) +
sptwb_ex.spt.DataInTransferLength; status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH_EX,
&sptwb_ex,
sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX),
&sptwb_ex,
length,
&returned,
FALSE); PrintStatusResultsEx(status,returned,&sptwb_ex,length);
}
else
{
ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.spt.PathId = ;
sptwb.spt.TargetId = ;
sptwb.spt.Lun = ;
sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb.spt.SenseInfoLength = SPT_SENSE_LENGTH;
sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.spt.DataTransferLength = ;
sptwb.spt.TimeOutValue = ;
sptwb.spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
sptwb.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
sptwb.spt.Cdb[] = SCSIOP_MODE_SENSE;
sptwb.spt.Cdb[] = 0x08; // target shall not return any block descriptors
sptwb.spt.Cdb[] = MODE_PAGE_CACHING;
sptwb.spt.Cdb[] = ;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
sptwb.spt.DataTransferLength; status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
length,
&returned,
FALSE); PrintStatusResults(status,returned,&sptwb,length);
} printf(" ***** WRITE DATA BUFFER operation *****\n"); dataBuffer = AllocateAlignedBuffer(sectorSize,alignmentMask, &pUnAlignedBuffer);
FillMemory(dataBuffer,sectorSize/,'N');
FillMemory(dataBuffer + sectorSize/,sectorSize/,'T'); if(srbType == )
{
ZeroMemory(&sptdwb_ex,sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX));
sptdwb_ex.sptd.Version = ;
sptdwb_ex.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT_EX);
sptdwb_ex.sptd.ScsiStatus = ;
sptdwb_ex.sptd.CdbLength = CDB10GENERIC_LENGTH;
sptdwb_ex.sptd.StorAddressLength = sizeof(STOR_ADDR_BTL8);
sptdwb_ex.sptd.SenseInfoLength = SPT_SENSE_LENGTH;
sptdwb_ex.sptd.DataOutTransferLength = sectorSize;
sptdwb_ex.sptd.DataInTransferLength = ;
sptdwb_ex.sptd.DataDirection = SCSI_IOCTL_DATA_OUT;
sptdwb_ex.sptd.TimeOutValue = ;
sptdwb_ex.sptd.StorAddressOffset =
offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX,StorAddress);
sptdwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
sptdwb_ex.StorAddress.Port = ;
sptdwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
sptdwb_ex.StorAddress.Path = ;
sptdwb_ex.StorAddress.Target = ;
sptdwb_ex.StorAddress.Lun = ;
sptdwb_ex.sptd.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX,ucSenseBuf);
sptdwb_ex.sptd.DataOutBuffer = dataBuffer;
sptdwb_ex.sptd.DataInBuffer = NULL;
sptdwb_ex.sptd.Cdb[] = SCSIOP_WRITE_DATA_BUFF;
sptdwb_ex.sptd.Cdb[] = ; // Data mode
sptdwb_ex.sptd.Cdb[] = (UCHAR)(sectorSize >> ); // Parameter List length
sptdwb_ex.sptd.Cdb[] = ;
length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX); status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH_DIRECT_EX,
&sptdwb_ex,
length,
&sptdwb_ex,
length,
&returned,
FALSE); PrintStatusResultsEx(status,returned,
(PSCSI_PASS_THROUGH_WITH_BUFFERS_EX)&sptdwb_ex,length); if ((sptdwb_ex.sptd.ScsiStatus == ) && (status != )) {
PrintDataBuffer(dataBuffer,sptdwb_ex.sptd.DataOutTransferLength);
}
}
else
{
ZeroMemory(&sptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
sptdwb.sptd.PathId = ;
sptdwb.sptd.TargetId = ;
sptdwb.sptd.Lun = ;
sptdwb.sptd.CdbLength = CDB10GENERIC_LENGTH;
sptdwb.sptd.SenseInfoLength = SPT_SENSE_LENGTH;
sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_OUT;
sptdwb.sptd.DataTransferLength = sectorSize;
sptdwb.sptd.TimeOutValue = ;
sptdwb.sptd.DataBuffer = dataBuffer;
sptdwb.sptd.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
sptdwb.sptd.Cdb[] = SCSIOP_WRITE_DATA_BUFF;
sptdwb.sptd.Cdb[] = ; // Data mode
sptdwb.sptd.Cdb[] = (UCHAR)(sectorSize >> ); // Parameter List length
sptdwb.sptd.Cdb[] = ;
length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER); status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
&sptdwb,
length,
&sptdwb,
length,
&returned,
FALSE); PrintStatusResults(status,returned,
(PSCSI_PASS_THROUGH_WITH_BUFFERS)&sptdwb,length); if ((sptdwb.sptd.ScsiStatus == ) && (status != )) {
PrintDataBuffer(dataBuffer,sptdwb.sptd.DataTransferLength);
}
} printf(" ***** READ DATA BUFFER operation *****\n"); ZeroMemory(dataBuffer,sectorSize); if(srbType == )
{
ZeroMemory(&sptdwb_ex,sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX));
sptdwb_ex.sptd.Version = ;
sptdwb_ex.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT_EX);
sptdwb_ex.sptd.ScsiStatus = ;
sptdwb_ex.sptd.CdbLength = CDB10GENERIC_LENGTH;
sptdwb_ex.sptd.StorAddressLength = sizeof(STOR_ADDR_BTL8);
sptdwb_ex.sptd.SenseInfoLength = SPT_SENSE_LENGTH;
sptdwb_ex.sptd.DataOutTransferLength = ;
sptdwb_ex.sptd.DataInTransferLength = sectorSize;
sptdwb_ex.sptd.DataDirection = SCSI_IOCTL_DATA_IN;
sptdwb_ex.sptd.TimeOutValue = ;
sptdwb_ex.sptd.StorAddressOffset =
offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX,StorAddress);
sptdwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
sptdwb_ex.StorAddress.Port = ;
sptdwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
sptdwb_ex.StorAddress.Path = ;
sptdwb_ex.StorAddress.Target = ;
sptdwb_ex.StorAddress.Lun = ;
sptdwb_ex.sptd.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX,ucSenseBuf);
sptdwb_ex.sptd.DataOutBuffer = NULL;
sptdwb_ex.sptd.DataInBuffer = dataBuffer;
sptdwb_ex.sptd.Cdb[] = SCSIOP_READ_DATA_BUFF;
sptdwb_ex.sptd.Cdb[] = ; // Data mode
sptdwb_ex.sptd.Cdb[] = (UCHAR)(sectorSize >> ); // Parameter List length
sptdwb_ex.sptd.Cdb[] = ;
length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX); status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH_DIRECT_EX,
&sptdwb_ex,
length,
&sptdwb_ex,
length,
&returned,
FALSE); PrintStatusResultsEx(status,returned,
(PSCSI_PASS_THROUGH_WITH_BUFFERS_EX)&sptdwb_ex,length); if ((sptdwb_ex.sptd.ScsiStatus == ) && (status != )) {
PrintDataBuffer(dataBuffer,sptdwb_ex.sptd.DataInTransferLength);
}
}
else
{
ZeroMemory(&sptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
sptdwb.sptd.PathId = ;
sptdwb.sptd.TargetId = ;
sptdwb.sptd.Lun = ;
sptdwb.sptd.CdbLength = CDB10GENERIC_LENGTH;
sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_IN;
sptdwb.sptd.SenseInfoLength = SPT_SENSE_LENGTH;
sptdwb.sptd.DataTransferLength = sectorSize;
sptdwb.sptd.TimeOutValue = ;
sptdwb.sptd.DataBuffer = dataBuffer;
sptdwb.sptd.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
sptdwb.sptd.Cdb[] = SCSIOP_READ_DATA_BUFF;
sptdwb.sptd.Cdb[] = ; // Data mode
sptdwb.sptd.Cdb[] = (UCHAR)(sectorSize >> ); // Parameter List length
sptdwb.sptd.Cdb[] = ;
length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER); status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
&sptdwb,
length,
&sptdwb,
length,
&returned,
FALSE); PrintStatusResults(status,returned,
(PSCSI_PASS_THROUGH_WITH_BUFFERS)&sptdwb,length); if ((sptdwb.sptd.ScsiStatus == ) && (status != )) {
PrintDataBuffer(dataBuffer,sptdwb.sptd.DataTransferLength);
}
} if (pUnAlignedBuffer != NULL) {
free(pUnAlignedBuffer);
}
CloseHandle(fileHandle);
} VOID
PrintError(ULONG ErrorCode)
{
CHAR errorBuffer[];
ULONG count; count = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
ErrorCode,
,
errorBuffer,
sizeof(errorBuffer),
NULL
); if (count != ) {
printf("%s\n", errorBuffer);
} else {
printf("Format message failed. Error: %d\n", GetLastError());
}
} VOID
PrintDataBuffer(_In_reads_(BufferLength) PUCHAR DataBuffer, _In_ ULONG BufferLength)
{
ULONG Cnt; printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
printf(" ---------------------------------------------------------------\n");
for (Cnt = ; Cnt < BufferLength; Cnt++) {
if ((Cnt) % == ) {
printf(" %03X ",Cnt);
}
printf("%02X ", DataBuffer[Cnt]);
if ((Cnt+) % == ) {
printf(" ");
}
if ((Cnt+) % == ) {
printf("\n");
}
}
printf("\n\n");
} VOID
PrintAdapterDescriptor(PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor)
{
ULONG trueMaximumTransferLength;
LPCSTR busType; if (AdapterDescriptor->BusType < NUMBER_OF_BUS_TYPE_STRINGS) {
busType = BusTypeStrings[AdapterDescriptor->BusType];
} else {
busType = BusTypeStrings[NUMBER_OF_BUS_TYPE_STRINGS-];
} // subtract one page, as transfers do not always start on a page boundary
if (AdapterDescriptor->MaximumPhysicalPages > ) {
trueMaximumTransferLength = AdapterDescriptor->MaximumPhysicalPages - ;
} else {
trueMaximumTransferLength = ;
}
// make it into a byte value
trueMaximumTransferLength <<= PAGE_SHIFT; // take the minimum of the two
if (trueMaximumTransferLength > AdapterDescriptor->MaximumTransferLength) {
trueMaximumTransferLength = AdapterDescriptor->MaximumTransferLength;
} // always allow at least a single page transfer
if (trueMaximumTransferLength < PAGE_SIZE) {
trueMaximumTransferLength = PAGE_SIZE;
} puts("\n ***** STORAGE ADAPTER DESCRIPTOR DATA *****");
printf(" Version: %08x\n"
" TotalSize: %08x\n"
"MaximumTransferLength: %08x (bytes)\n"
" MaximumPhysicalPages: %08x\n"
" TrueMaximumTransfer: %08x (bytes)\n"
" AlignmentMask: %08x\n"
" AdapterUsesPio: %s\n"
" AdapterScansDown: %s\n"
" CommandQueueing: %s\n"
" AcceleratedTransfer: %s\n"
" Bus Type: %s\n"
" Bus Major Version: %04x\n"
" Bus Minor Version: %04x\n",
AdapterDescriptor->Version,
AdapterDescriptor->Size,
AdapterDescriptor->MaximumTransferLength,
AdapterDescriptor->MaximumPhysicalPages,
trueMaximumTransferLength,
AdapterDescriptor->AlignmentMask,
BOOLEAN_TO_STRING(AdapterDescriptor->AdapterUsesPio),
BOOLEAN_TO_STRING(AdapterDescriptor->AdapterScansDown),
BOOLEAN_TO_STRING(AdapterDescriptor->CommandQueueing),
BOOLEAN_TO_STRING(AdapterDescriptor->AcceleratedTransfer),
busType,
AdapterDescriptor->BusMajorVersion,
AdapterDescriptor->BusMinorVersion); printf("\n\n");
} VOID
PrintDeviceDescriptor(PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor)
{
LPCSTR vendorId = "";
LPCSTR productId = "";
LPCSTR productRevision = "";
LPCSTR serialNumber = "";
LPCSTR busType; if (DeviceDescriptor->BusType < NUMBER_OF_BUS_TYPE_STRINGS) {
busType = BusTypeStrings[DeviceDescriptor->BusType];
} else {
busType = BusTypeStrings[NUMBER_OF_BUS_TYPE_STRINGS-];
} if ((DeviceDescriptor->ProductIdOffset != ) &&
(DeviceDescriptor->ProductIdOffset != -)) {
productId = (LPCSTR)(DeviceDescriptor);
productId += (ULONG_PTR)DeviceDescriptor->ProductIdOffset;
}
if ((DeviceDescriptor->VendorIdOffset != ) &&
(DeviceDescriptor->VendorIdOffset != -)) {
vendorId = (LPCSTR)(DeviceDescriptor);
vendorId += (ULONG_PTR)DeviceDescriptor->VendorIdOffset;
}
if ((DeviceDescriptor->ProductRevisionOffset != ) &&
(DeviceDescriptor->ProductRevisionOffset != -)) {
productRevision = (LPCSTR)(DeviceDescriptor);
productRevision += (ULONG_PTR)DeviceDescriptor->ProductRevisionOffset;
}
if ((DeviceDescriptor->SerialNumberOffset != ) &&
(DeviceDescriptor->SerialNumberOffset != -)) {
serialNumber = (LPCSTR)(DeviceDescriptor);
serialNumber += (ULONG_PTR)DeviceDescriptor->SerialNumberOffset;
} puts("\n ***** STORAGE DEVICE DESCRIPTOR DATA *****");
printf(" Version: %08x\n"
" TotalSize: %08x\n"
" DeviceType: %08x\n"
" DeviceTypeModifier: %08x\n"
" RemovableMedia: %s\n"
" CommandQueueing: %s\n"
" Vendor Id: %s\n"
" Product Id: %s\n"
" Product Revision: %s\n"
" Serial Number: %s\n"
" Bus Type: %s\n"
" Raw Properties: %s\n",
DeviceDescriptor->Version,
DeviceDescriptor->Size,
DeviceDescriptor->DeviceType,
DeviceDescriptor->DeviceTypeModifier,
BOOLEAN_TO_STRING(DeviceDescriptor->RemovableMedia),
BOOLEAN_TO_STRING(DeviceDescriptor->CommandQueueing),
vendorId,
productId,
productRevision,
serialNumber,
busType,
(DeviceDescriptor->RawPropertiesLength ? "Follows" : "None"));
if (DeviceDescriptor->RawPropertiesLength != ) {
PrintDataBuffer(DeviceDescriptor->RawDeviceProperties,
DeviceDescriptor->RawPropertiesLength);
}
printf("\n\n");
} _Success_(return != NULL)
_Post_writable_byte_size_(size)
PUCHAR
AllocateAlignedBuffer(
_In_ ULONG size,
_In_ ULONG AlignmentMask,
_Outptr_result_maybenull_ PUCHAR *pUnAlignedBuffer)
{
PUCHAR ptr; // NOTE: This routine does not allow for a way to free
// memory. This is an excercise left for the reader.
UINT_PTR align64 = (UINT_PTR)AlignmentMask; if (AlignmentMask == ) {
ptr = malloc(size);
*pUnAlignedBuffer = ptr;
} else {
ULONG totalSize; (void) ULongAdd(size, AlignmentMask, &totalSize);
ptr = malloc(totalSize);
*pUnAlignedBuffer = ptr;
ptr = (PUCHAR)(((UINT_PTR)ptr + align64) & ~align64);
} if (ptr == NULL) {
printf("Memory allocation error. Terminating program\n");
exit();
} else {
return ptr;
}
} VOID
PrintStatusResults(
BOOL status,DWORD returned,PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb,
ULONG length)
{
ULONG errorCode; if (!status ) {
printf( "Error: %d ",
errorCode = GetLastError() );
PrintError(errorCode);
return;
}
if (psptwb->spt.ScsiStatus) {
PrintSenseInfo(psptwb);
return;
}
else {
printf("Scsi status: %02Xh, Bytes returned: %Xh, ",
psptwb->spt.ScsiStatus,returned);
printf("Data buffer length: %Xh\n\n\n",
psptwb->spt.DataTransferLength);
PrintDataBuffer((PUCHAR)psptwb,length);
}
} VOID
PrintSenseInfo(PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb)
{
UCHAR i; printf("Scsi status: %02Xh\n\n",psptwb->spt.ScsiStatus);
if (psptwb->spt.SenseInfoLength == ) {
return;
}
printf("Sense Info -- consult SCSI spec for details\n");
printf("-------------------------------------------------------------\n");
for (i=; i < psptwb->spt.SenseInfoLength; i++) {
printf("%02X ",psptwb->ucSenseBuf[i]);
}
printf("\n\n");
} VOID
PrintStatusResultsEx(
BOOL status,DWORD returned,PSCSI_PASS_THROUGH_WITH_BUFFERS_EX psptwb_ex,
ULONG length)
{
ULONG errorCode; if (!status ) {
printf( "Error: %d ",
errorCode = GetLastError() );
PrintError(errorCode);
return;
}
if (psptwb_ex->spt.ScsiStatus) {
PrintSenseInfoEx(psptwb_ex);
return;
}
else {
printf("Scsi status: %02Xh, Bytes returned: %Xh, ",
psptwb_ex->spt.ScsiStatus,returned);
printf("DataOut buffer length: %Xh\n"
"DataIn buffer length: %Xh\n\n\n",
psptwb_ex->spt.DataOutTransferLength,
psptwb_ex->spt.DataInTransferLength);
PrintDataBuffer((PUCHAR)psptwb_ex,length);
}
} VOID
PrintSenseInfoEx(PSCSI_PASS_THROUGH_WITH_BUFFERS_EX psptwb_ex)
{
ULONG i; printf("Scsi status: %02Xh\n\n",psptwb_ex->spt.ScsiStatus);
if (psptwb_ex->spt.SenseInfoLength == ) {
return;
}
printf("Sense Info -- consult SCSI spec for details\n");
printf("-------------------------------------------------------------\n");
for (i=; i < psptwb_ex->spt.SenseInfoLength; i++) {
printf("%02X ",psptwb_ex->ucSenseBuf[i]);
}
printf("\n\n");
} _Success_(return)
BOOL
QueryPropertyForDevice(
_In_ IN HANDLE DeviceHandle,
_Out_ OUT PULONG AlignmentMask,
_Out_ OUT PUCHAR SrbType
)
{
PSTORAGE_ADAPTER_DESCRIPTOR adapterDescriptor = NULL;
PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor = NULL;
STORAGE_DESCRIPTOR_HEADER header = {}; BOOL ok = TRUE;
BOOL failed = TRUE;
ULONG i; *AlignmentMask = ; // default to no alignment
*SrbType = ; // default to SCSI_REQUEST_BLOCK // Loop twice:
// First, get size required for storage adapter descriptor
// Second, allocate and retrieve storage adapter descriptor
// Third, get size required for storage device descriptor
// Fourth, allocate and retrieve storage device descriptor
for (i=;i<;i++) { PVOID buffer = NULL;
ULONG bufferSize = ;
ULONG returnedData; STORAGE_PROPERTY_QUERY query = {}; switch(i) {
case : {
query.QueryType = PropertyStandardQuery;
query.PropertyId = StorageAdapterProperty;
bufferSize = sizeof(STORAGE_DESCRIPTOR_HEADER);
buffer = &header;
break;
}
case : {
query.QueryType = PropertyStandardQuery;
query.PropertyId = StorageAdapterProperty;
bufferSize = header.Size;
if (bufferSize != ) {
adapterDescriptor = LocalAlloc(LPTR, bufferSize);
if (adapterDescriptor == NULL) {
goto Cleanup;
}
}
buffer = adapterDescriptor;
break;
}
case : {
query.QueryType = PropertyStandardQuery;
query.PropertyId = StorageDeviceProperty;
bufferSize = sizeof(STORAGE_DESCRIPTOR_HEADER);
buffer = &header;
break;
}
case : {
query.QueryType = PropertyStandardQuery;
query.PropertyId = StorageDeviceProperty;
bufferSize = header.Size; if (bufferSize != ) {
deviceDescriptor = LocalAlloc(LPTR, bufferSize);
if (deviceDescriptor == NULL) {
goto Cleanup;
}
}
buffer = deviceDescriptor;
break;
}
} // buffer can be NULL if the property queried DNE.
if (buffer != NULL) {
RtlZeroMemory(buffer, bufferSize); // all setup, do the ioctl
ok = DeviceIoControl(DeviceHandle,
IOCTL_STORAGE_QUERY_PROPERTY,
&query,
sizeof(STORAGE_PROPERTY_QUERY),
buffer,
bufferSize,
&returnedData,
FALSE);
if (!ok) {
if (GetLastError() == ERROR_MORE_DATA) {
// this is ok, we'll ignore it here
} else if (GetLastError() == ERROR_INVALID_FUNCTION) {
// this is also ok, the property DNE
} else if (GetLastError() == ERROR_NOT_SUPPORTED) {
// this is also ok, the property DNE
} else {
// some unexpected error -- exit out
goto Cleanup;
}
// zero it out, just in case it was partially filled in.
RtlZeroMemory(buffer, bufferSize);
}
}
} // end i loop // adapterDescriptor is now allocated and full of data.
// deviceDescriptor is now allocated and full of data. if (adapterDescriptor == NULL) {
printf(" ***** No adapter descriptor supported on the device *****\n");
} else {
PrintAdapterDescriptor(adapterDescriptor);
*AlignmentMask = adapterDescriptor->AlignmentMask;
*SrbType = adapterDescriptor->SrbType;
} if (deviceDescriptor == NULL) {
printf(" ***** No device descriptor supported on the device *****\n");
} else {
PrintDeviceDescriptor(deviceDescriptor);
} failed = FALSE; Cleanup:
if (adapterDescriptor != NULL) {
LocalFree( adapterDescriptor );
}
if (deviceDescriptor != NULL) {
LocalFree( deviceDescriptor );
}
return (!failed); }

SCSI Pass-Through Interface Tool的更多相关文章

  1. 使用VueCLI的User Interface Tool(GUI)创建app的图文讲解

    (英文原文) 需要安VueCLI3和nodejs. 在terminal输入vue可以看到命令列表: 其中vue ui [options] 就是用于开始和打开vue-cli ui的命令. 使用http: ...

  2. Send custom commands to Mass Storage device

    http://stackoverflow.com/questions/14363152/send-custom-commands-to-mass-storage-device I have devel ...

  3. What's Assembly - CSharp - Editor - first pass.dll? Best How to Fix Assembly - CSharp - Editor - first pass.dll Error Guide

    If you've found yourself here, I'm guessing that you're getting Assembly - CSharp - Editor - first p ...

  4. hadoop2.2编程:Tool, ToolRunner, GenericOptionsParser, Configuration

    继承关系:   1. java.util Interface Map.Entry<K,V> description: public static interface Map.Entry&l ...

  5. SCSI磁盘标准的架构与文档

    来自scsi标准的官方网站http://t10.org/,具体的文档可以去浏览官方网站. (*) This chart reflects the currently approved SCSI pro ...

  6. IPMI (Intelligent Platform Management Interface)

    4.3. ipmitool - utility for controlling IPMI-enabled devices 4.3.1. ipmitool 4.3.1.1. ubuntu 确定硬件是否支 ...

  7. 关于Tool接口--------hadoop接口:extends Configured implements Tool 和 ToolRunner.run

    我们在写Hadoop--map/reduce程序时,遇到使用按文件url来分析文件----------多表连接的DistributedCache方式,看不懂使用extends Configured i ...

  8. 读取USB HDD(USB移动硬盘信息)序列号的代码

    读取USB HDD(USB移动硬盘)序列号的代码,型号及分位. 使用Visual Studio 2010编译成功. 代码使用了CrystalDiskInfo中的代码smartata.c中相关代码: 例 ...

  9. [Windows Azure] Enabling Diagnostics in Windows Azure

    Enabling Diagnostics in Windows Azure Windows Azure Diagnostics enables you to collect diagnostic da ...

随机推荐

  1. Python3 出现'ascii' codec can't encode characters问题

    当使用urllib.request.urlopen打开包含中文的链接时报错: from urllib import request url = 'https://baike.baidu.com/ite ...

  2. 应用服务器中对JDK的epoll空转bug的处理

    原文链接:应用服务器中对JDK的epoll空转bug的处理 前面讲到了epoll的一些机制,与select和poll等传统古老的IO多路复用机制的一些区别,这些区别实质可以总结为一句话, 就是epol ...

  3. wpf image blur

    RenderOptions.BitmapScalingMode="NearestNeighbor"

  4. sem_open中信号量命名

    问题: sem_open will failed with "No such file or directory"   解释1: 这是由于在Linux内核中,创建信号量的默认路径是 ...

  5. 第一次ActiveX Fuzzing测试

    接着上一篇的看雪Exploit me试题. 这道题给出了一个ActiveX的DLL,挖掘这个DLL中的漏洞. 由于从来没有接触过ActiveX的Fuzzing,所以找了一些文章来看.自己动手试验了一下 ...

  6. mysqlsla 安装

    tar -zxvf mysqlsla-2.03.tar.gz cd mysqlsla-2.03 perl Makefile.PLmake && make install BEGIN f ...

  7. HDU - 4465 期望 + 取log优化

    思路:这个求期望的公式很容易得到,但是在算的时候我们会遇到一个问题,就是组合数太大了根本存不下, 这时候就可以在计算的时候都取log,最后复原...  以前没遇到过.. #include<bit ...

  8. Spring Boot 实用MyBatis做数据库操作

    前言: 本项目基于maven构建,使用mybatis-spring-boot作为spring-boot项目的持久层框架 spring-boot中使用mybatis持久层框架与原spring项目使用方式 ...

  9. 模拟界面请求到web服务器

    客户端 package com.lsw.client; import java.io.*; import java.net.*; import java.util.*; public class HT ...

  10. 一文搞定 Mybatis 的应用

    Mybatis 介绍 Mybatis 是一个开源的持久层框架,原来叫 ibatis ,它对 jdbc 操作数据库的过程进行了封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动. ...