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. FM的推导原理--推荐系统

    FM:解决稀疏数据下的特征组合问题  Factorization Machine(因子分解机) 美团技术团队的文章,觉得写得很好啊:https://tech.meituan.com/deep-unde ...

  2. set,list,map分析

    想了下集合,列表,映射三者关系 set,list,map ArrayList采用数组方式存储数据,继承List; LinkedList采用链表方式存储数据,继承List; 所以数组方式都有下表,以及每 ...

  3. wpf mvvm模式下的image绑定

    view文件 <Image Grid.Column="2" Width="48" Height="64" Stretch=" ...

  4. MongoDB查询用法大全

    转载 http://blog.163.com/lgh_2002/blog/static/440175262012052116455/ 详见官方的手册: http://www.mongodb.org/d ...

  5. 按书上学写测试pytest

    慢慢的,这块知识也补好吧. 系统的学习框架,具体的细节,可以边百度边实现. test_three.py '''Test the Task data type.''' from collections ...

  6. LoadRunner 自带订票系统flights 功能空白、1080端口被占用的解决办法

    LoadRunner 自带订票系统flights 功能空白.1080端口被占用的解决办法 安装LoadRunner8.1后运行Mercury Web Tours Application,点击fligh ...

  7. LoadRunner FAQ

    LoadRunner FAQ web_concurrent_start和web_concurrent_end web_concurrent_start 语法: int web_concurrent_s ...

  8. 全局设置axios发送cookie(axios 默认不发送cookie)

    import axios from 'axios' axios.defaults.withCredentials=true; 如图:

  9. Servlet的一点小结

    1.什么是servlet servlet是一个Java applet,一个帮助程序.用于帮助浏览器从服务器中获取资源.浏览器-servlet-服务器三者的关系如图所示. 2.servlet的生命周期 ...

  10. CSUOJ 1008 Horcrux

    Description A Horcrux is an object in which a Dark wizard or witch has hidden a fragment of his or h ...