.net - C#/Native: Reading HDD Serial Using SCSI PassThrough -
i have written 3 different methods make use of native createfile
, deviceiocontrol
calls in order retrieve hdd serial number (not model number). first 1 uses s.m.a.r.t.
, second 1 uses storage query
, third 1 uses scsi passthrough
. of code based on content of this thread (with fixes , improvements).
here results using diskid32 utility:
trying read drive ids using physical access admin rights drive model number________________: [st975xxxxx] drive serial number_______________: [ 6ws2xxxx] trying read drive ids using physical access 0 rights product id = [st975xxxxx] serial number = [6ws2xxxx] trying read drive ids using smart drive model number________________: [st975xxxxx] drive serial number_______________: [ 6ws2xxxx]
now, here results using methods:
s.m.a.r.t. = 6ws2xxxx storage query = 6ws2xxxx scsi passthrough = st975xxxxx
well... houston have problem here. first 2 methods correct serial number. last 1 model number bad. now, here code:
--- method --- internal static string getharddiskserialscsipassthrough(safefilehandle devicehandle) { intptr bufferpointer = intptr.zero; string serial = string.empty; uint32 bytesreturned; scsipassthroughbuffered bspt = new scsipassthroughbuffered(); bspt.spt.length = (uint16)marshal.sizeof(bspt.spt); bspt.spt.commanddescriptorblocklength = 16; bspt.spt.datain = 0x1; bspt.spt.datatransferlength = 64; bspt.spt.databufferoffset = new intptr(marshal.sizeof(bspt) - 64); bspt.spt.timeoutvalue = 60; bspt.spt.commanddescriptorblock = new byte[] { 0x12, 0x1, 0x80, 0x0, 64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; int32 buffersize = marshal.sizeof(bspt); try { bufferpointer = marshal.allochglobal(buffersize); marshal.structuretoptr(bspt, bufferpointer, true); if (deviceiocontrol(devicehandle, 0x4d004, bufferpointer, (uint32)buffersize, bufferpointer, (uint32)buffersize, out bytesreturned, intptr.zero) && (bytesreturned > 0)) { scsipassthroughbuffered result = (scsipassthroughbuffered)marshal.ptrtostructure(bufferpointer, typeof(scsipassthroughbuffered)); serial = encoding.ascii.getstring(result.buffer, 0, result.buffer.length).replace("\0", string.empty).trim(); } } { marshal.freehglobal(bufferpointer); } return serial; } --- structures --- [structlayout(layoutkind.sequential)] private struct scsipassthrough { public uint16 length; public byte scsistatus; public byte pathid; public byte targetid; public byte logicalunitnumber; public byte commanddescriptorblocklength; public byte senseinfolength; public byte datain; public uint32 datatransferlength; public uint32 timeoutvalue; public intptr databufferoffset; public uint32 senseinfooffset; [marshalas(unmanagedtype.byvalarray, sizeconst = 16)] public byte[] commanddescriptorblock; } [structlayout(layoutkind.sequential)] private struct scsipassthroughbuffered { public scsipassthrough spt; public uint32 filler; [marshalas(unmanagedtype.byvalarray, sizeconst = 64)] public byte[] buffer; }
what doing wrong? maybe using wrong cdb?
your code runs ok me, i.e. returns same data other methods described in referenced thread. change had make from:
serial = encoding.ascii.getstring(result.buffer, 0, result.buffer.length) .replace("\0", string.empty) .trim();
to:
serial = encoding.ascii.getstring(result.buffer, 0, result.buffer.length) .substring(intptr.size) .replace("\0", string.empty) .trim();
Comments
Post a Comment