• SCSI Pass-Through Interface Tool


    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 - 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 
    /*++ 
     
    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]
    ", argv[0] ); 
           printf("Examples:
    "); 
           printf("    spti g:       (open the disk class driver in SHARED READ/WRITE mode)
    "); 
           printf("    spti Scsi2:   (open the miniport driver for the 3rd host adapter)
    "); 
           printf("    spti Tape0 w  (open the tape class driver in SHARED WRITE mode)
    "); 
           printf("    spti i: c     (open the CD-ROM class driver in SHARED READ mode)
    "); 
           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.
    ", argv[2]); 
                    puts("	r = read"); 
                    puts("	w = write"); 
                    puts("	c = 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
    ", 
                   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
    ", errorCode); 
            PrintError(errorCode); 
            CloseHandle(fileHandle); 
            return; 
        } 
     
        printf("
    " 
               "            *****     Detected Alignment Mask    *****
    " 
               "            *****             was %08x       *****
    
    
    ", 
               alignmentMask); 
     
        // 
        // Send SCSI Pass Through 
        // 
     
        puts("            ***** MODE SENSE -- return all pages *****"); 
        puts("            *****      with SenseInfo buffer     *****
    "); 
     
        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 *****
    "); 
        printf("            *****    without SenseInfo buffer    *****
    
    "); 
     
        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      *****
    "); 
        printf("            *****   DataInBufferLength = 0  *****
    
    "); 
     
        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      *****
    "); 
        printf("            *****   bad DataBufferOffset -- should fail    *****
    
    "); 
     
        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                  *****
    "); 
        printf("            *****     return caching mode sense page        *****
    
    "); 
     
        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         *****
    "); 
         
        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         *****
    "); 
     
        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
    ", errorBuffer); 
        } else { 
            printf("Format message failed.  Error: %d
    ", 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
    "); 
        printf("      ---------------------------------------------------------------
    "); 
        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("
    "); 
              } 
           } 
        printf("
    
    "); 
    } 
     
    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("
                ***** STORAGE ADAPTER DESCRIPTOR DATA *****"); 
        printf("              Version: %08x
    " 
               "            TotalSize: %08x
    " 
               "MaximumTransferLength: %08x (bytes)
    " 
               " MaximumPhysicalPages: %08x
    " 
               "  TrueMaximumTransfer: %08x (bytes)
    " 
               "        AlignmentMask: %08x
    " 
               "       AdapterUsesPio: %s
    " 
               "     AdapterScansDown: %s
    " 
               "      CommandQueueing: %s
    " 
               "  AcceleratedTransfer: %s
    " 
               "             Bus Type: %s
    " 
               "    Bus Major Version: %04x
    " 
               "    Bus Minor Version: %04x
    ", 
               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("
    
    "); 
    } 
     
    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-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("
                ***** STORAGE DEVICE DESCRIPTOR DATA *****"); 
        printf("              Version: %08x
    " 
               "            TotalSize: %08x
    " 
               "           DeviceType: %08x
    " 
               "   DeviceTypeModifier: %08x
    " 
               "       RemovableMedia: %s
    " 
               "      CommandQueueing: %s
    " 
               "            Vendor Id: %s
    " 
               "           Product Id: %s
    " 
               "     Product Revision: %s
    " 
               "        Serial Number: %s
    " 
               "             Bus Type: %s
    " 
               "       Raw Properties: %s
    ", 
               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("
    
    "); 
    } 
     
    _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
    "); 
           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
    
    
    ", 
              psptwb->spt.DataTransferLength); 
           PrintDataBuffer((PUCHAR)psptwb,length); 
           } 
    } 
     
    VOID 
    PrintSenseInfo(PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb) 
    { 
        UCHAR i; 
     
        printf("Scsi status: %02Xh
    
    ",psptwb->spt.ScsiStatus); 
        if (psptwb->spt.SenseInfoLength == 0) { 
           return; 
           } 
        printf("Sense Info -- consult SCSI spec for details
    "); 
        printf("-------------------------------------------------------------
    "); 
        for (i=0; i < psptwb->spt.SenseInfoLength; i++) { 
           printf("%02X ",psptwb->ucSenseBuf[i]); 
           } 
        printf("
    
    "); 
    } 
     
    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
    " 
                  "DataIn buffer length: %Xh
    
    
    ", 
              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
    
    ",psptwb_ex->spt.ScsiStatus); 
        if (psptwb_ex->spt.SenseInfoLength == 0) { 
           return; 
           } 
        printf("Sense Info -- consult SCSI spec for details
    "); 
        printf("-------------------------------------------------------------
    "); 
        for (i=0; i < psptwb_ex->spt.SenseInfoLength; i++) { 
           printf("%02X ",psptwb_ex->ucSenseBuf[i]); 
           } 
        printf("
    
    "); 
    } 
     
    _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 *****
    "); 
        } else { 
            PrintAdapterDescriptor(adapterDescriptor); 
            *AlignmentMask = adapterDescriptor->AlignmentMask; 
            *SrbType = adapterDescriptor->SrbType; 
        } 
     
        if (deviceDescriptor == NULL) { 
            printf("   ***** No device descriptor supported on the device  *****
    "); 
        } else { 
            PrintDeviceDescriptor(deviceDescriptor); 
        } 
     
        failed = FALSE; 
     
    Cleanup: 
        if (adapterDescriptor != NULL) { 
            LocalFree( adapterDescriptor ); 
        } 
        if (deviceDescriptor != NULL) { 
            LocalFree( deviceDescriptor ); 
        } 
        return (!failed); 
     
    } 
  • 相关阅读:
    cocos2dx3.0戳青蛙游戏(打地鼠)
    深入理解Tomcat系列之五:Context容器和Wrapper容器
    linux下拷贝隐藏文件
    8.8.1 运行计划
    UVALive
    堆排序实现
    C语言中的signal函数
    uboot和内核分区的改动
    Android缩放动画
    .Net 自定义应用程序配置
  • 原文地址:https://www.cnblogs.com/shangdawei/p/3164060.html
Copyright © 2020-2023  润新知