Code for reading the serial number of usb hdd (USB mobile hard disk Information)
Code, model, and split of the serial number of the usb hdd.
Visual Studio 2010 is successfully compiled.
The Code uses the related code in smartata. c In CrystalDiskInfo:
The following connection explains why scsi-related code requires data conversion from a usb ic.
The implementation code is as follows:
// DiskInfo.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <winioctl.h>#include <stddef.h>#include <memory.h>#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)typedef struct _IDENTIFY_DEVICE{WORDGeneralConfiguration;//0WORDLogicalCylinders;//1ObsoleteWORDSpecificConfiguration;//2WORDLogicalHeads;//3 ObsoleteWORDRetired1[2];//4-5WORDLogicalSectors;//6 ObsoleteDWORDReservedForCompactFlash;//7-8WORDRetired2;//9CHARSerialNumber[20];//10-19WORDRetired3;//20WORDBufferSize;//21 Obsolete//WORDObsolute4;//22CHARFirmwareRev[8];//23-26CHARModel[40];//27-46WORDMaxNumPerInterupt;//47WORDReserved1;//48WORDCapabilities1;//49WORDCapabilities2;//50DWORDObsolute5;//51-52WORDField88and7064;//53WORDObsolute6[5];//54-58WORDMultSectorStuff;//59DWORDTotalAddressableSectors;//60-61WORDObsolute7;//62WORDMultiWordDma;//63WORDPioMode;//64WORDMinMultiwordDmaCycleTime;//65WORDRecommendedMultiwordDmaCycleTime;//66WORDMinPioCycleTimewoFlowCtrl;//67WORDMinPioCycleTimeWithFlowCtrl;//68WORDReserved2[6];//69-74WORDQueueDepth;//75WORDSerialAtaCapabilities;//76WORDSerialAtaAdditionalCapabilities;//77WORDSerialAtaFeaturesSupported;//78WORDSerialAtaFeaturesEnabled;//79WORDMajorVersion;//80WORDMinorVersion;//81WORDCommandSetSupported1;//82WORDCommandSetSupported2;//83WORDCommandSetSupported3;//84WORDCommandSetEnabled1;//85WORDCommandSetEnabled2;//86WORDCommandSetDefault;//87WORDUltraDmaMode;//88WORDTimeReqForSecurityErase;//89WORDTimeReqForEnhancedSecure;//90WORDCurrentPowerManagement;//91WORDMasterPasswordRevision;//92WORDHardwareResetResult;//93WORDAcoustricManagement;//94WORDStreamMinRequestSize;//95WORDStreamingTimeDma;//96WORDStreamingAccessLatency;//97DWORDStreamingPerformance;//98-99ULONGLONGMaxUserLba;//100-103WORDStremingTimePio;//104WORDReserved3;//105WORDSectorSize;//106WORDInterSeekDelay;//107WORDIeeeOui;//108WORDUniqueId3;//109WORDUniqueId2;//110WORDUniqueId1;//111WORDReserved4[4];//112-115WORDReserved5;//116DWORDWordsPerLogicalSector;//117-118WORDReserved6[8];//119-126WORDRemovableMediaStatus;//127WORDSecurityStatus;//128WORDVendorSpecific[31];//129-159WORDCfaPowerMode1;//160WORDReservedForCompactFlashAssociation[7];//161-167WORDDeviceNominalFormFactor;//168WORDDataSetManagement;//169WORDAdditionalProductIdentifier[4];//170-173WORDReserved7[2];//174-175CHARCurrentMediaSerialNo[60];//176-205WORDSctCommandTransport;//206WORDReservedForCeAta1[2];//207-208WORDAlignmentOfLogicalBlocks;//209DWORDWriteReadVerifySectorCountMode3;//210-211DWORDWriteReadVerifySectorCountMode2;//212-213WORDNvCacheCapabilities;//214DWORDNvCacheSizeLogicalBlocks;//215-216WORDNominalMediaRotationRate;//217WORDReserved8;//218WORDNvCacheOptions1;//219WORDNvCacheOptions2;//220WORDReserved9;//221WORDTransportMajorVersionNumber;//222WORDTransportMinorVersionNumber;//223WORDReservedForCeAta2[10];//224-233WORDMinimumBlocksPerDownloadMicrocode;//234WORDMaximumBlocksPerDownloadMicrocode;//235WORDReserved10[19];//236-254WORDIntegrityWord;//255}IDENTIFY_DEVICE;typedef enum _COMMAND_TYPE{CMD_TYPE_PHYSICAL_DRIVE = 0,CMD_TYPE_SCSI_MINIPORT,CMD_TYPE_SILICON_IMAGE,CMD_TYPE_SAT,// SAT = SCSI_ATA_TRANSLATIONCMD_TYPE_SUNPLUS,CMD_TYPE_IO_DATA,CMD_TYPE_LOGITEC,CMD_TYPE_JMICRON,CMD_TYPE_CYPRESS,CMD_TYPE_PROLIFIC,// Not imprementCMD_TYPE_CSMI,// CSMI = Common Storage Management InterfaceCMD_TYPE_CSMI_PHYSICAL_DRIVE, // CSMI = Common Storage Management Interface CMD_TYPE_WMI,CMD_TYPE_DEBUG}COMMAND_TYPE;// retrieve the properties of a storage device or adapter.typedef enum _STORAGE_QUERY_TYPE { PropertyStandardQuery = 0, PropertyExistsQuery, PropertyMaskQuery, PropertyQueryMaxDefined} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;// retrieve the properties of a storage device or adapter.typedef struct _STORAGE_PROPERTY_QUERY { STORAGE_PROPERTY_ID PropertyId; STORAGE_QUERY_TYPE QueryType; UCHAR AdditionalParameters[1];} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;#defineFILE_DEVICE_SCSI0x0000001b#defineIOCTL_SCSI_MINIPORT_IDENTIFY((FILE_DEVICE_SCSI << 16) + 0x0501)#defineIOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS((FILE_DEVICE_SCSI << 16) + 0x0502)#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS((FILE_DEVICE_SCSI << 16) + 0x0503)#define IOCTL_SCSI_MINIPORT_ENABLE_SMART((FILE_DEVICE_SCSI << 16) + 0x0504)#define IOCTL_SCSI_MINIPORT_DISABLE_SMART((FILE_DEVICE_SCSI << 16) + 0x0505)#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER#define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)//// Define values for pass-through DataIn field.//#define SCSI_IOCTL_DATA_OUT 0#define SCSI_IOCTL_DATA_IN 1#define SCSI_IOCTL_DATA_UNSPECIFIED 2//// Define the SCSI pass through structure.//typedef struct _SCSI_PASS_THROUGH {USHORT Length;UCHAR ScsiStatus;UCHAR PathId;UCHAR TargetId;UCHAR Lun;UCHAR CdbLength;UCHAR SenseInfoLength;UCHAR DataIn;ULONG DataTransferLength;ULONG TimeOutValue;ULONG_PTR DataBufferOffset;ULONG SenseInfoOffset;UCHAR Cdb[16];}SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS {SCSI_PASS_THROUGH Spt;ULONG Filler; // realign buffers to double word boundaryUCHAR SenseBuf[32];UCHAR DataBuf[512];} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;static void dump_buffer(const char* title, const unsigned char* buffer, int len){ int i = 0; int j; printf ("\n-- %s --\n", title); if (len > 0) { printf ("%8.8s ", " "); for (j = 0; j < 16; ++j) { printf (" %2X", j); } printf (" "); for (j = 0; j < 16; ++j) { printf ("%1X", j); } printf ("\n"); } while (i < len) { printf("%08x ", i); for (j = 0; j < 16; ++j) { if ((i + j) < len) printf (" %02x", (int) buffer[i +j]); else printf (" "); } printf (" "); for (j = 0; j < 16; ++j) { if ((i + j) < len) printf ("%c", isprint (buffer[i + j]) ? buffer [i + j] : '.'); else printf (" "); } printf ("\n"); i += 16; } printf ("-- DONE --\n");}void ChangeByteOrder(PCHAR szString, USHORT uscStrSize){USHORT i;CHAR temp;for (i = 0; i < uscStrSize; i+=2){temp = szString[i];szString[i] = szString[i+1];szString[i+1] = temp;}}BOOL DoIdentifyDeviceSat(HANDLE physicalDriveId, BYTE target, IDENTIFY_DEVICE* data, COMMAND_TYPE type){BOOLbRet;HANDLEhIoCtrl;DWORDdwReturned;DWORDlength;SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;if(data == NULL){printf("Data\n");returnFALSE;}ZeroMemory(data, sizeof(IDENTIFY_DEVICE));hIoCtrl = physicalDriveId;if(hIoCtrl == INVALID_HANDLE_VALUE){printf("Handle\n");returnFALSE;}ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));sptwb.Spt.Length = sizeof(SCSI_PASS_THROUGH);sptwb.Spt.PathId = 0;sptwb.Spt.TargetId = 0;sptwb.Spt.Lun = 0;sptwb.Spt.SenseInfoLength = 24;sptwb.Spt.DataIn = SCSI_IOCTL_DATA_IN;sptwb.Spt.DataTransferLength = IDENTIFY_BUFFER_SIZE;sptwb.Spt.TimeOutValue = 2;sptwb.Spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf);sptwb.Spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseBuf);if(type == CMD_TYPE_SAT){sptwb.Spt.CdbLength = 12;sptwb.Spt.Cdb[0] = 0xA1;//ATA PASS THROUGH(12) OPERATION CODE(A1h)sptwb.Spt.Cdb[1] = (4 << 1) | 0; //MULTIPLE_COUNT=0,PROTOCOL=4(PIO Data-In),Reservedsptwb.Spt.Cdb[2] = (1 << 3) | (1 << 2) | 2;//OFF_LINE=0,CK_COND=0,Reserved=0,T_DIR=1(ToDevice),BYTE_BLOCK=1,T_LENGTH=2sptwb.Spt.Cdb[3] = 0;//FEATURES (7:0)sptwb.Spt.Cdb[4] = 1;//SECTOR_COUNT (7:0)sptwb.Spt.Cdb[5] = 0;//LBA_LOW (7:0)sptwb.Spt.Cdb[6] = 0;//LBA_MID (7:0)sptwb.Spt.Cdb[7] = 0;//LBA_HIGH (7:0)sptwb.Spt.Cdb[8] = target;sptwb.Spt.Cdb[9] = 0xEC;//COMMAND}else if(type == CMD_TYPE_SUNPLUS){sptwb.Spt.CdbLength = 12;sptwb.Spt.Cdb[0] = 0xF8;sptwb.Spt.Cdb[1] = 0x00;sptwb.Spt.Cdb[2] = 0x22;sptwb.Spt.Cdb[3] = 0x10;sptwb.Spt.Cdb[4] = 0x01;sptwb.Spt.Cdb[5] = 0x00; sptwb.Spt.Cdb[6] = 0x01; sptwb.Spt.Cdb[7] = 0x00; sptwb.Spt.Cdb[8] = 0x00;sptwb.Spt.Cdb[9] = 0x00;sptwb.Spt.Cdb[10] = target; sptwb.Spt.Cdb[11] = 0xEC; // ID_CMD}else if(type == CMD_TYPE_IO_DATA){sptwb.Spt.CdbLength = 12;sptwb.Spt.Cdb[0] = 0xE3;sptwb.Spt.Cdb[1] = 0x00;sptwb.Spt.Cdb[2] = 0x00;sptwb.Spt.Cdb[3] = 0x01;sptwb.Spt.Cdb[4] = 0x01;sptwb.Spt.Cdb[5] = 0x00; sptwb.Spt.Cdb[6] = 0x00; sptwb.Spt.Cdb[7] = target;sptwb.Spt.Cdb[8] = 0xEC; // ID_CMDsptwb.Spt.Cdb[9] = 0x00;sptwb.Spt.Cdb[10] = 0x00; sptwb.Spt.Cdb[11] = 0x00;}else if(type == CMD_TYPE_LOGITEC){sptwb.Spt.CdbLength = 10;sptwb.Spt.Cdb[0] = 0xE0;sptwb.Spt.Cdb[1] = 0x00;sptwb.Spt.Cdb[2] = 0x00;sptwb.Spt.Cdb[3] = 0x00;sptwb.Spt.Cdb[4] = 0x00;sptwb.Spt.Cdb[5] = 0x00; sptwb.Spt.Cdb[6] = 0x00; sptwb.Spt.Cdb[7] = target; sptwb.Spt.Cdb[8] = 0xEC; // ID_CMDsptwb.Spt.Cdb[9] = 0x4C;}else if(type == CMD_TYPE_JMICRON){sptwb.Spt.CdbLength = 12;sptwb.Spt.Cdb[0] = 0xDF;sptwb.Spt.Cdb[1] = 0x10;sptwb.Spt.Cdb[2] = 0x00;sptwb.Spt.Cdb[3] = 0x02;sptwb.Spt.Cdb[4] = 0x00;sptwb.Spt.Cdb[5] = 0x00; sptwb.Spt.Cdb[6] = 0x01; sptwb.Spt.Cdb[7] = 0x00; sptwb.Spt.Cdb[8] = 0x00;sptwb.Spt.Cdb[9] = 0x00;sptwb.Spt.Cdb[10] = target; sptwb.Spt.Cdb[11] = 0xEC; // ID_CMD}else if(type == CMD_TYPE_CYPRESS){sptwb.Spt.CdbLength = 16;sptwb.Spt.Cdb[0] = 0x24;sptwb.Spt.Cdb[1] = 0x24;sptwb.Spt.Cdb[2] = 0x00;sptwb.Spt.Cdb[3] = 0xBE;sptwb.Spt.Cdb[4] = 0x01;sptwb.Spt.Cdb[5] = 0x00; sptwb.Spt.Cdb[6] = 0x00; sptwb.Spt.Cdb[7] = 0x01; sptwb.Spt.Cdb[8] = 0x00;sptwb.Spt.Cdb[9] = 0x00;sptwb.Spt.Cdb[10] = 0x00; sptwb.Spt.Cdb[11] = target;sptwb.Spt.Cdb[12] = 0xEC; // ID_CMDsptwb.Spt.Cdb[13] = 0x00;sptwb.Spt.Cdb[14] = 0x00;sptwb.Spt.Cdb[15] = 0x00;}else{return FALSE;}length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf) + sptwb.Spt.DataTransferLength;bRet = DeviceIoControl(hIoCtrl, IOCTL_SCSI_PASS_THROUGH, &sptwb, sizeof(SCSI_PASS_THROUGH),&sptwb, length,&dwReturned, NULL);CloseHandle(hIoCtrl);if(bRet == FALSE || dwReturned != length){returnFALSE;}memcpy(data, sptwb.DataBuf, sizeof(IDENTIFY_DEVICE));returnTRUE;}int main(int argc, char *argv[]) {HANDLE hDevice=NULL;STORAGE_PROPERTY_QUERYsQuery;STORAGE_DEVICE_DESCRIPTOR*pDescriptor;char *model, *firmware, *serialnumber;char usb_hdd_model[41], usb_hdd_firmware[9], usb_hdd_Serialnumber[21];IDENTIFY_DEVICE identify = {0};char pcbData[4096];int dwLen = 4096;DWORDdwRet;BOOLbRet;hDevice=CreateFileA("\\\\.\\PhysicalDrive1",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);if(hDevice==INVALID_HANDLE_VALUE){ fprintf(stderr, "CreateFile()\n");exit(1);}memset(pcbData, 0, 4096);sQuery.PropertyId = StorageDeviceProperty;sQuery.QueryType = PropertyStandardQuery;bRet = DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &sQuery, sizeof(STORAGE_PROPERTY_QUERY), pcbData,dwLen,&dwRet,NULL);if(bRet){pDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pcbData;if(pDescriptor->BusType == BusTypeUsb){printf("USB-Type\n");}if(pDescriptor->ProductIdOffset){model = (char*)pDescriptor + pDescriptor->ProductIdOffset;printf("Model: %s\n", model);}if(pDescriptor->ProductRevisionOffset){firmware = (char*)pDescriptor + pDescriptor->ProductRevisionOffset;printf("Firmware: %s\n", firmware);}if(pDescriptor->SerialNumberOffset){serialnumber = (char*)pDescriptor + pDescriptor->SerialNumberOffset;printf("Serial number: %s\n", serialnumber);}}/*CMD_TYPE_SAT,// SAT = SCSI_ATA_TRANSLATIONCMD_TYPE_SUNPLUS,CMD_TYPE_IO_DATA,CMD_TYPE_LOGITEC,CMD_TYPE_JMICRON,CMD_TYPE_CYPRESS,*/if(DoIdentifyDeviceSat(hDevice, 0xa0, &identify, CMD_TYPE_SAT)){printf("0xA0-CMD_TYPE_SAT-Return ok");}else if(DoIdentifyDeviceSat(hDevice, 0xa0, &identify, CMD_TYPE_SUNPLUS)){printf("0xA0-CMD_TYPE_SUNPLUS-Return ok");}else if(DoIdentifyDeviceSat(hDevice, 0xa0, &identify, CMD_TYPE_IO_DATA)){printf("0xA0-CMD_TYPE_IO_DATA-Return ok");}else if(DoIdentifyDeviceSat(hDevice, 0xa0, &identify, CMD_TYPE_LOGITEC)){printf("0xA0-CMD_TYPE_LOGITEC-Return ok");}else if(DoIdentifyDeviceSat(hDevice, 0xa0, &identify, CMD_TYPE_JMICRON)){printf("0xA0-CMD_TYPE_JMICRON-Return ok");}else if(DoIdentifyDeviceSat(hDevice, 0xb0, &identify, CMD_TYPE_SAT)){printf("0xB0-CMD_TYPE_SAT-Return ok");}else if(DoIdentifyDeviceSat(hDevice, 0xb0, &identify, CMD_TYPE_SUNPLUS)){printf("0xB0-CMD_TYPE_SUNPLUS-Return ok");}else if(DoIdentifyDeviceSat(hDevice, 0xb0, &identify, CMD_TYPE_IO_DATA)){printf("0xB0-CMD_TYPE_IO_DATA-Return ok");}else if(DoIdentifyDeviceSat(hDevice, 0xb0, &identify, CMD_TYPE_LOGITEC)){printf("0xB0-CMD_TYPE_LOGITEC-Return ok");}else if(DoIdentifyDeviceSat(hDevice, 0xb0, &identify, CMD_TYPE_JMICRON)){printf("0xB0-CMD_TYPE_JMICRON-Return ok");}else{printf("Return ng\n");}#define debug 0#if debugdump_buffer("data", (const unsigned char *)&identify, sizeof(IDENTIFY_DEVICE));#endifmemcpy(usb_hdd_model, identify.Model, 40);ChangeByteOrder(usb_hdd_model, 40);usb_hdd_model[40]='\0';memcpy(usb_hdd_firmware, identify.FirmwareRev, 8);ChangeByteOrder(usb_hdd_firmware, 8);usb_hdd_firmware[8]='\0';memcpy(usb_hdd_Serialnumber, identify.SerialNumber, 20);ChangeByteOrder(usb_hdd_Serialnumber, 20);usb_hdd_Serialnumber[20]='\0';printf("\nUSB-HDD Model name: %s", usb_hdd_model);printf("\nUSB-HDD Firmware Rev: %s", usb_hdd_firmware);printf("\nUSB-HDD Serial number: %s", usb_hdd_Serialnumber);return 0;}