summaryrefslogtreecommitdiff
path: root/storage/tools/spti/src
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /storage/tools/spti/src
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'storage/tools/spti/src')
-rw-r--r--storage/tools/spti/src/spti.c1204
-rw-r--r--storage/tools/spti/src/spti.h97
-rw-r--r--storage/tools/spti/src/spti.htmbin0 -> 109034 bytes
-rw-r--r--storage/tools/spti/src/spti.vcxproj167
-rw-r--r--storage/tools/spti/src/spti.vcxproj.Filters22
5 files changed, 1490 insertions, 0 deletions
diff --git a/storage/tools/spti/src/spti.c b/storage/tools/spti/src/spti.c
new file mode 100644
index 00000000..6dfb2c39
--- /dev/null
+++ b/storage/tools/spti/src/spti.c
@@ -0,0 +1,1204 @@
+/*++
+
+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",
+ "1394",
+ "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 = 0;
+ DWORD accessMode = 0, shareMode = 0;
+ HANDLE fileHandle = NULL;
+ ULONG alignmentMask = 0; // default == no alignment requirement
+ UCHAR srbType = 0; // 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 = 0,
+ errorCode = 0,
+ returned = 0,
+ sectorSize = 512;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s <port-name> [-mode]\n", argv[0] );
+ 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[1]);
+
+ shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; // default
+ accessMode = GENERIC_WRITE | GENERIC_READ; // default
+
+ if (argc == 3) {
+
+ switch(tolower(argv[2][0])) {
+ case 'r':
+ shareMode = FILE_SHARE_READ;
+ break;
+
+ case 'w':
+ shareMode = FILE_SHARE_WRITE;
+ break;
+
+ case 'c':
+ shareMode = FILE_SHARE_READ;
+ sectorSize = 2048;
+ break;
+
+ default:
+ printf("%s is an invalid mode.\n", argv[2]);
+ puts("\tr = read");
+ puts("\tw = write");
+ puts("\tc = read CD (2048 byte sector mode)");
+ return;
+ }
+ }
+
+ fileHandle = CreateFile(string,
+ accessMode,
+ shareMode,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ 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 == 1)
+ {
+ ZeroMemory(&sptwb_ex,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX));
+ sptwb_ex.spt.Version = 0;
+ sptwb_ex.spt.Length = sizeof(SCSI_PASS_THROUGH_EX);
+ sptwb_ex.spt.ScsiStatus = 0;
+ 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 = 0;
+ sptwb_ex.spt.DataInTransferLength = 192;
+ sptwb_ex.spt.DataDirection = SCSI_IOCTL_DATA_IN;
+ sptwb_ex.spt.TimeOutValue = 2;
+ sptwb_ex.spt.StorAddressOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,StorAddress);
+ sptwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
+ sptwb_ex.StorAddress.Port = 0;
+ sptwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
+ sptwb_ex.StorAddress.Path = 0;
+ sptwb_ex.StorAddress.Target = 1;
+ sptwb_ex.StorAddress.Lun = 0;
+ sptwb_ex.spt.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucSenseBuf);
+ sptwb_ex.spt.DataOutBufferOffset = 0;
+ sptwb_ex.spt.DataInBufferOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf);
+ sptwb_ex.spt.Cdb[0] = SCSIOP_MODE_SENSE;
+ sptwb_ex.spt.Cdb[2] = MODE_SENSE_RETURN_ALL;
+ sptwb_ex.spt.Cdb[4] = 192;
+ 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 = 0;
+ sptwb.spt.TargetId = 1;
+ sptwb.spt.Lun = 0;
+ sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
+ sptwb.spt.SenseInfoLength = SPT_SENSE_LENGTH;
+ sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
+ sptwb.spt.DataTransferLength = 192;
+ sptwb.spt.TimeOutValue = 2;
+ sptwb.spt.DataBufferOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
+ sptwb.spt.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
+ sptwb.spt.Cdb[0] = SCSIOP_MODE_SENSE;
+ sptwb.spt.Cdb[2] = MODE_SENSE_RETURN_ALL;
+ sptwb.spt.Cdb[4] = 192;
+ 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 == 1)
+ {
+ ZeroMemory(&sptwb_ex,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX));
+ sptwb_ex.spt.Version = 0;
+ sptwb_ex.spt.Length = sizeof(SCSI_PASS_THROUGH_EX);
+ sptwb_ex.spt.ScsiStatus = 0;
+ sptwb_ex.spt.CdbLength = CDB6GENERIC_LENGTH;
+ sptwb_ex.spt.StorAddressLength = sizeof(STOR_ADDR_BTL8);
+ sptwb_ex.spt.SenseInfoLength = 0;
+ sptwb_ex.spt.DataOutTransferLength = 0;
+ sptwb_ex.spt.DataInTransferLength = 192;
+ sptwb_ex.spt.DataDirection = SCSI_IOCTL_DATA_IN;
+ sptwb_ex.spt.TimeOutValue = 2;
+ sptwb_ex.spt.StorAddressOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,StorAddress);
+ sptwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
+ sptwb_ex.StorAddress.Port = 0;
+ sptwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
+ sptwb_ex.StorAddress.Path = 0;
+ sptwb_ex.StorAddress.Target = 1;
+ sptwb_ex.StorAddress.Lun = 0;
+ sptwb_ex.spt.SenseInfoOffset = 0;
+ sptwb_ex.spt.DataOutBufferOffset = 0;
+ sptwb_ex.spt.DataInBufferOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf);
+ sptwb_ex.spt.Cdb[0] = SCSIOP_MODE_SENSE;
+ sptwb_ex.spt.Cdb[2] = MODE_SENSE_RETURN_ALL;
+ sptwb_ex.spt.Cdb[4] = 192;
+ 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 = 0;
+ sptwb.spt.TargetId = 1;
+ sptwb.spt.Lun = 0;
+ sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
+ sptwb.spt.SenseInfoLength = 0;
+ sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
+ sptwb.spt.DataTransferLength = 192;
+ sptwb.spt.TimeOutValue = 2;
+ sptwb.spt.DataBufferOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
+ sptwb.spt.Cdb[0] = SCSIOP_MODE_SENSE;
+ sptwb.spt.Cdb[2] = MODE_SENSE_RETURN_ALL;
+ sptwb.spt.Cdb[4] = 192;
+ 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 == 1)
+ {
+ ZeroMemory(&sptwb_ex,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX));
+ sptwb_ex.spt.Version = 0;
+ sptwb_ex.spt.Length = sizeof(SCSI_PASS_THROUGH_EX);
+ sptwb_ex.spt.ScsiStatus = 0;
+ 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 = 0;
+ sptwb_ex.spt.DataInTransferLength = 0;
+ sptwb_ex.spt.DataDirection = SCSI_IOCTL_DATA_IN;
+ sptwb_ex.spt.TimeOutValue = 2;
+ sptwb_ex.spt.StorAddressOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,StorAddress);
+ sptwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
+ sptwb_ex.StorAddress.Port = 0;
+ sptwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
+ sptwb_ex.StorAddress.Path = 0;
+ sptwb_ex.StorAddress.Target = 1;
+ sptwb_ex.StorAddress.Lun = 0;
+ sptwb_ex.spt.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucSenseBuf);
+ sptwb_ex.spt.DataOutBufferOffset = 0;
+ sptwb_ex.spt.DataInBufferOffset = 0;
+ sptwb_ex.spt.Cdb[0] = 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 = 0;
+ sptwb.spt.TargetId = 1;
+ sptwb.spt.Lun = 0;
+ sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
+ sptwb.spt.SenseInfoLength = SPT_SENSE_LENGTH;
+ sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
+ sptwb.spt.DataTransferLength = 0;
+ sptwb.spt.TimeOutValue = 2;
+ sptwb.spt.DataBufferOffset = 0;
+ sptwb.spt.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
+ sptwb.spt.Cdb[0] = 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 == 1)
+ {
+ ZeroMemory(&sptwb_ex,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX));
+ sptwb_ex.spt.Version = 0;
+ sptwb_ex.spt.Length = sizeof(SCSI_PASS_THROUGH_EX);
+ sptwb_ex.spt.ScsiStatus = 0;
+ 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 = 0;
+ sptwb_ex.spt.DataInTransferLength = 192;
+ sptwb_ex.spt.DataDirection = SCSI_IOCTL_DATA_IN;
+ sptwb_ex.spt.TimeOutValue = 2;
+ sptwb_ex.spt.StorAddressOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,StorAddress);
+ sptwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
+ sptwb_ex.StorAddress.Port = 0;
+ sptwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
+ sptwb_ex.StorAddress.Path = 0;
+ sptwb_ex.StorAddress.Target = 1;
+ sptwb_ex.StorAddress.Lun = 0;
+ sptwb_ex.spt.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucSenseBuf);
+ sptwb_ex.spt.DataOutBufferOffset = 0;
+ sptwb_ex.spt.DataInBufferOffset = 0;
+ sptwb_ex.spt.Cdb[0] = SCSIOP_MODE_SENSE;
+ sptwb_ex.spt.Cdb[2] = MODE_SENSE_RETURN_ALL;
+ sptwb_ex.spt.Cdb[4] = 192;
+ 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 = 0;
+ sptwb.spt.TargetId = 1;
+ sptwb.spt.Lun = 0;
+ sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
+ sptwb.spt.SenseInfoLength = 0;
+ sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
+ sptwb.spt.DataTransferLength = 192;
+ sptwb.spt.TimeOutValue = 2;
+ sptwb.spt.DataBufferOffset = 0;
+ sptwb.spt.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
+ sptwb.spt.Cdb[0] = SCSIOP_MODE_SENSE;
+ sptwb.spt.Cdb[2] = MODE_SENSE_RETURN_ALL;
+ sptwb.spt.Cdb[4] = 192;
+ 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 == 1)
+ {
+ ZeroMemory(&sptwb_ex,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX));
+ sptwb_ex.spt.Version = 0;
+ sptwb_ex.spt.Length = sizeof(SCSI_PASS_THROUGH_EX);
+ sptwb_ex.spt.ScsiStatus = 0;
+ 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 = 0;
+ sptwb_ex.spt.DataInTransferLength = 192;
+ sptwb_ex.spt.DataDirection = SCSI_IOCTL_DATA_IN;
+ sptwb_ex.spt.TimeOutValue = 2;
+ sptwb_ex.spt.StorAddressOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,StorAddress);
+ sptwb_ex.StorAddress.Type = STOR_ADDRESS_TYPE_BTL8;
+ sptwb_ex.StorAddress.Port = 0;
+ sptwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
+ sptwb_ex.StorAddress.Path = 0;
+ sptwb_ex.StorAddress.Target = 1;
+ sptwb_ex.StorAddress.Lun = 0;
+ sptwb_ex.spt.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucSenseBuf);
+ sptwb_ex.spt.DataOutBufferOffset = 0;
+ sptwb_ex.spt.DataInBufferOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS_EX,ucDataBuf);
+ sptwb_ex.spt.Cdb[0] = SCSIOP_MODE_SENSE;
+ sptwb_ex.spt.Cdb[1] = 0x08; // target shall not return any block descriptors
+ sptwb_ex.spt.Cdb[2] = MODE_PAGE_CACHING;
+ sptwb_ex.spt.Cdb[4] = 192;
+ 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 = 0;
+ sptwb.spt.TargetId = 1;
+ sptwb.spt.Lun = 0;
+ sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
+ sptwb.spt.SenseInfoLength = SPT_SENSE_LENGTH;
+ sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
+ sptwb.spt.DataTransferLength = 192;
+ sptwb.spt.TimeOutValue = 2;
+ sptwb.spt.DataBufferOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
+ sptwb.spt.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
+ sptwb.spt.Cdb[0] = SCSIOP_MODE_SENSE;
+ sptwb.spt.Cdb[1] = 0x08; // target shall not return any block descriptors
+ sptwb.spt.Cdb[2] = MODE_PAGE_CACHING;
+ sptwb.spt.Cdb[4] = 192;
+ 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/2,'N');
+ FillMemory(dataBuffer + sectorSize/2,sectorSize/2,'T');
+
+ if(srbType == 1)
+ {
+ ZeroMemory(&sptdwb_ex,sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX));
+ sptdwb_ex.sptd.Version = 0;
+ sptdwb_ex.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT_EX);
+ sptdwb_ex.sptd.ScsiStatus = 0;
+ 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 = 0;
+ sptdwb_ex.sptd.DataDirection = SCSI_IOCTL_DATA_OUT;
+ sptdwb_ex.sptd.TimeOutValue = 2;
+ 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 = 0;
+ sptdwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
+ sptdwb_ex.StorAddress.Path = 0;
+ sptdwb_ex.StorAddress.Target = 1;
+ sptdwb_ex.StorAddress.Lun = 0;
+ 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[0] = SCSIOP_WRITE_DATA_BUFF;
+ sptdwb_ex.sptd.Cdb[1] = 2; // Data mode
+ sptdwb_ex.sptd.Cdb[7] = (UCHAR)(sectorSize >> 8); // Parameter List length
+ sptdwb_ex.sptd.Cdb[8] = 0;
+ 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 == 0) && (status != 0)) {
+ 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 = 0;
+ sptdwb.sptd.TargetId = 1;
+ sptdwb.sptd.Lun = 0;
+ 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 = 2;
+ sptdwb.sptd.DataBuffer = dataBuffer;
+ sptdwb.sptd.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
+ sptdwb.sptd.Cdb[0] = SCSIOP_WRITE_DATA_BUFF;
+ sptdwb.sptd.Cdb[1] = 2; // Data mode
+ sptdwb.sptd.Cdb[7] = (UCHAR)(sectorSize >> 8); // Parameter List length
+ sptdwb.sptd.Cdb[8] = 0;
+ 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 == 0) && (status != 0)) {
+ PrintDataBuffer(dataBuffer,sptdwb.sptd.DataTransferLength);
+ }
+ }
+
+
+ printf(" ***** READ DATA BUFFER operation *****\n");
+
+ ZeroMemory(dataBuffer,sectorSize);
+
+ if(srbType == 1)
+ {
+ ZeroMemory(&sptdwb_ex,sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER_EX));
+ sptdwb_ex.sptd.Version = 0;
+ sptdwb_ex.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT_EX);
+ sptdwb_ex.sptd.ScsiStatus = 0;
+ 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 = 0;
+ sptdwb_ex.sptd.DataInTransferLength = sectorSize;
+ sptdwb_ex.sptd.DataDirection = SCSI_IOCTL_DATA_IN;
+ sptdwb_ex.sptd.TimeOutValue = 2;
+ 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 = 0;
+ sptdwb_ex.StorAddress.AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
+ sptdwb_ex.StorAddress.Path = 0;
+ sptdwb_ex.StorAddress.Target = 1;
+ sptdwb_ex.StorAddress.Lun = 0;
+ 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[0] = SCSIOP_READ_DATA_BUFF;
+ sptdwb_ex.sptd.Cdb[1] = 2; // Data mode
+ sptdwb_ex.sptd.Cdb[7] = (UCHAR)(sectorSize >> 8); // Parameter List length
+ sptdwb_ex.sptd.Cdb[8] = 0;
+ 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 == 0) && (status != 0)) {
+ 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 = 0;
+ sptdwb.sptd.TargetId = 1;
+ sptdwb.sptd.Lun = 0;
+ 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 = 2;
+ sptdwb.sptd.DataBuffer = dataBuffer;
+ sptdwb.sptd.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
+ sptdwb.sptd.Cdb[0] = SCSIOP_READ_DATA_BUFF;
+ sptdwb.sptd.Cdb[1] = 2; // Data mode
+ sptdwb.sptd.Cdb[7] = (UCHAR)(sectorSize >> 8); // Parameter List length
+ sptdwb.sptd.Cdb[8] = 0;
+ 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 == 0) && (status != 0)) {
+ PrintDataBuffer(dataBuffer,sptdwb.sptd.DataTransferLength);
+ }
+ }
+
+
+ if (pUnAlignedBuffer != NULL) {
+ free(pUnAlignedBuffer);
+ }
+ CloseHandle(fileHandle);
+}
+
+VOID
+PrintError(ULONG ErrorCode)
+{
+ CHAR errorBuffer[80];
+ ULONG count;
+
+ count = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ ErrorCode,
+ 0,
+ errorBuffer,
+ sizeof(errorBuffer),
+ NULL
+ );
+
+ if (count != 0) {
+ 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 = 0; Cnt < BufferLength; Cnt++) {
+ if ((Cnt) % 16 == 0) {
+ printf(" %03X ",Cnt);
+ }
+ printf("%02X ", DataBuffer[Cnt]);
+ if ((Cnt+1) % 8 == 0) {
+ printf(" ");
+ }
+ if ((Cnt+1) % 16 == 0) {
+ 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-1];
+ }
+
+ // subtract one page, as transfers do not always start on a page boundary
+ if (AdapterDescriptor->MaximumPhysicalPages > 1) {
+ trueMaximumTransferLength = AdapterDescriptor->MaximumPhysicalPages - 1;
+ } else {
+ trueMaximumTransferLength = 1;
+ }
+ // 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 ((ULONG)DeviceDescriptor->BusType < NUMBER_OF_BUS_TYPE_STRINGS) {
+ busType = BusTypeStrings[DeviceDescriptor->BusType];
+ } else {
+ busType = BusTypeStrings[NUMBER_OF_BUS_TYPE_STRINGS-1];
+ }
+
+ if ((DeviceDescriptor->ProductIdOffset != 0) &&
+ (DeviceDescriptor->ProductIdOffset != -1)) {
+ productId = (LPCSTR)(DeviceDescriptor);
+ productId += (ULONG_PTR)DeviceDescriptor->ProductIdOffset;
+ }
+ if ((DeviceDescriptor->VendorIdOffset != 0) &&
+ (DeviceDescriptor->VendorIdOffset != -1)) {
+ vendorId = (LPCSTR)(DeviceDescriptor);
+ vendorId += (ULONG_PTR)DeviceDescriptor->VendorIdOffset;
+ }
+ if ((DeviceDescriptor->ProductRevisionOffset != 0) &&
+ (DeviceDescriptor->ProductRevisionOffset != -1)) {
+ productRevision = (LPCSTR)(DeviceDescriptor);
+ productRevision += (ULONG_PTR)DeviceDescriptor->ProductRevisionOffset;
+ }
+ if ((DeviceDescriptor->SerialNumberOffset != 0) &&
+ (DeviceDescriptor->SerialNumberOffset != -1)) {
+ 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 != 0) {
+ 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 == 0) {
+ 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(1);
+ } 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 == 0) {
+ return;
+ }
+ printf("Sense Info -- consult SCSI spec for details\n");
+ printf("-------------------------------------------------------------\n");
+ for (i=0; 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 == 0) {
+ return;
+ }
+ printf("Sense Info -- consult SCSI spec for details\n");
+ printf("-------------------------------------------------------------\n");
+ for (i=0; 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 = {0};
+
+ BOOL ok = TRUE;
+ BOOL failed = TRUE;
+ ULONG i;
+
+ *AlignmentMask = 0; // default to no alignment
+ *SrbType = 0; // 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=0;i<4;i++) {
+
+ PVOID buffer = NULL;
+ ULONG bufferSize = 0;
+ ULONG returnedData;
+
+ STORAGE_PROPERTY_QUERY query = {0};
+
+ switch(i) {
+ case 0: {
+ query.QueryType = PropertyStandardQuery;
+ query.PropertyId = StorageAdapterProperty;
+ bufferSize = sizeof(STORAGE_DESCRIPTOR_HEADER);
+ buffer = &header;
+ break;
+ }
+ case 1: {
+ query.QueryType = PropertyStandardQuery;
+ query.PropertyId = StorageAdapterProperty;
+ bufferSize = header.Size;
+ if (bufferSize != 0) {
+ adapterDescriptor = LocalAlloc(LPTR, bufferSize);
+ if (adapterDescriptor == NULL) {
+ goto Cleanup;
+ }
+ }
+ buffer = adapterDescriptor;
+ break;
+ }
+ case 2: {
+ query.QueryType = PropertyStandardQuery;
+ query.PropertyId = StorageDeviceProperty;
+ bufferSize = sizeof(STORAGE_DESCRIPTOR_HEADER);
+ buffer = &header;
+ break;
+ }
+ case 3: {
+ query.QueryType = PropertyStandardQuery;
+ query.PropertyId = StorageDeviceProperty;
+ bufferSize = header.Size;
+
+ if (bufferSize != 0) {
+ 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);
+
+}
+
diff --git a/storage/tools/spti/src/spti.h b/storage/tools/spti/src/spti.h
new file mode 100644
index 00000000..3f3ee53c
--- /dev/null
+++ b/storage/tools/spti/src/spti.h
@@ -0,0 +1,97 @@
+/*++
+
+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-1]; // 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-1]; // 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
diff --git a/storage/tools/spti/src/spti.htm b/storage/tools/spti/src/spti.htm
new file mode 100644
index 00000000..17da4a11
--- /dev/null
+++ b/storage/tools/spti/src/spti.htm
Binary files differ
diff --git a/storage/tools/spti/src/spti.vcxproj b/storage/tools/spti/src/spti.vcxproj
new file mode 100644
index 00000000..7d29715b
--- /dev/null
+++ b/storage/tools/spti/src/spti.vcxproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{AD224B88-A7D7-4303-AF16-F972B5159493}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{385079F7-5826-4E2F-AF88-176A9338646C}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>spti</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>spti</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>spti</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>spti</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="spti.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/storage/tools/spti/src/spti.vcxproj.Filters b/storage/tools/spti/src/spti.vcxproj.Filters
new file mode 100644
index 00000000..7d986f7a
--- /dev/null
+++ b/storage/tools/spti/src/spti.vcxproj.Filters
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{F406A289-67B3-40DA-BF00-D802F47EC89A}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{018A4F52-238E-4856-BAF1-C38B0D6145F1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{5B9E60E4-CD1B-4C14-B6FD-2D55F070CEF5}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="spti.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file