retrieve harddisk`s modell,serial,firmware (Windows only)

Share your advanced PureBasic knowledge/code with the community.
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

dell_jockey wrote: DiskId32 uses the function "ReadPhysicalDriveInNTWithZeroRights" (see http://www.winsim.com/diskid32/diskid32.cpp).
As I wrote in my former post: on one PC it failed, on another it worked. It's certainly not a generic solution, which is why I don't pursue this any further.
@dell_jockey: Bummer. Must be hard drive specific. Thanks for the attempt.
Thunder93 wrote: Has anyone fixed up the previous PB codes to retrieve entire WD’s serial numbers, for instance WD-WCAD13933140 instead of just WD-WCAD1393314…?
@Thunder93: I am also getting a 14-char string back as my WD serial number - are you sure this IS NOT correct? Where did you find the ending zero in your example above?
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Post by Thunder93 »

On another’s system, who has Western Digital's HDD for host drive, with PB code available in this topic it shows no end tailing 0, with DiskInfo32 aka DiskId32 utility, it shows 0.

I have a Western Digital's Hard Drive, and it’s set as secondary HDD, both PB code available here and DiskInfo32 both sees exactly the same, and its 15 character (and its ending is with a 3)…

Odd to say the least!
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

Straker wrote:
@dell_jockey: Bummer. Must be hard drive specific. Thanks for the attempt.
You're welcome anytime...
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
mskuma
Enthusiast
Enthusiast
Posts: 573
Joined: Sat Dec 03, 2005 1:31 am
Location: Australia

Post by mskuma »

Straker wrote:
Are you logged in as Admin when you run this code? I have the same problem but only when I am not as Admin (on W2k). This is an issue with the code (see Revolver's comments on the first page).

The problem can be solved by converting the following code from C++ to PB. This is from the original (2003) version of DISKID32.CPP - link: http://www.winsim.com/diskid32/diskid32.cpp.

Code: Select all

int ReadPhysicalDriveInNTWithZeroRights (void)
<snip>
I had the same issue, however the SCSI back door ( i.e. function ReadIdeDriveAsScsiDriveInNT() ) worked for me - not ZeroRights. I wonder if those who had the same non-admin issue had no success with the SCSI back door method? I can't recall what drive I had (have to check it). I am very interested in this as well. I think WMI doesn't have this serial number, so I'm inclined to see if a ReadIdeDriveAsScsiDriveInNT() port is the way to go for the non-admin case.
mskuma
Enthusiast
Enthusiast
Posts: 573
Joined: Sat Dec 03, 2005 1:31 am
Location: Australia

Post by mskuma »

After doing some research on WMI, I realised it is possible to get a HD serial number using a WMI string. Out of curiousity, I wonder if those having problem acquiring the HD serial as a non-admin are better off using WMI, e.g.

Code: Select all

Debug WMI("SELECT * FROM win32_physicalMedia, SerialNumber")
Maybe this example just gets the first drive & works on Win2k/XP only.. YMMV.

An excellent WMI code reference is >here< (very grateful to Droopy & DataMiner for providing that - thank you - note: I think the latest code posted Jul 28, 2005 by DataMiner is the working one), or maybe you can use Droopy's lib which has WMI support http://gansta93.free.fr/droopyslib/news.php#29052006

If it works for all cases, this would be easier than porting the SCSI back door method. I'll be giving this WMI method a go on another (non-admin) machine tomorrow - maybe someone here can try it on their non-admin setup & report here.
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

mskuma wrote: function ReadIdeDriveAsScsiDriveInNT() ) worked for me - not ZeroRights.
I'll have to give that a shot (or beg someone here to convert it).

I believe the issue with WMI is that it works with only SMART drives, or it is not available on Windows 98 or something. I can't remember right now. I just recall that bypassing WMI is the preferred way for older systems.

Thanks for keeping this alive. We are almost there....
Image Image
mskuma
Enthusiast
Enthusiast
Posts: 573
Joined: Sat Dec 03, 2005 1:31 am
Location: Australia

Post by mskuma »

I tried the WMI method on a non-admin account (XP Pro) and found the program crashed (ok on admin account). If I used an alternative WMI string, e.g. WMI("SELECT * FROM Win32_NetworkAdapterConfiguration, Description, IPAddress, DNSServerSearchOrder"), it didn't crash. Can't explain what's going on there. So I guess the SCSI back door method is the way to go. If I get a chance later, I'll try to convert that code to PB.
mskuma
Enthusiast
Enthusiast
Posts: 573
Joined: Sat Dec 03, 2005 1:31 am
Location: Australia

Post by mskuma »

I've ported the scheme (from diskid32, the "SCSI back door method") which seems to work for the non-admin user case (at least on my XP Pro machine). See what you think.

Of course, have to say a huge thanks to Rings for the original code (contributions from dmoc & others too I think), and of course thanks to the diskid32 author Lynn McGuire for making the diskid32 code available.

Code: Select all

; retrieve harddisk's model, serial, firmware (Windows only, may only cover Win2k/XP)
; original author Rings (posted Tue Jun 17, 2003) - requires admin rights
; -> added non-admin access using alternative method using so-called 
; -> "SCSI back door" method from diskid32.cpp (ported to PB4 by mskuma)

; IDE registers

Structure IDEREGS
  bFeaturesReg.b      ; Used for specifying SMART "commands".
  bSectorCountReg.b   ; IDE sector count register
  bSectorNumberReg.b  ; IDE sector number register
  bCylLowReg.b        ; IDE low order cylinder value
  bCylHighReg.b       ; IDE high order cylinder value
  bDriveHeadReg.b     ; IDE drive/head register
  bCommandReg.b       ; Actual IDE command.
  bReserved.b         ; reserved for future use.  Must be zero.
EndStructure

; SENDCMDINPARAMS contains the input parameters for the send command To drive function

Structure SENDCMDINPARAMS 
  cBufferSize.l       ; Buffer size in bytes
  irDriveRegs.IDEREGS ; Structure with drive register values
  bDriveNumber.b      ; Physical drive number to send command To (0,1,2,3)
  bReserved.b[3]      ; Reserved for future expansion
  dwReserved.l[4]     ; For future use
  bBuffer.b[1]        ; Input buffer  
EndStructure 

Structure DRIVERSTATUS 
  bDriveError.b 
  bIDEStatus.b 
  bReserved.b[2]
  dwReserved.l[2]
EndStructure 

Structure SENDCMDOUTPARAMS 
  cBufferSize.l 
  DStatus.DRIVERSTATUS      
  bBuffer.b[512]
EndStructure 

; following 2 structures relate to SCSI method

Structure SRB_IO_CONTROL
  HeaderLength.l 
  Signature.s{8} 
  Timeout.l
  ControlCode.l 
  ReturnCode.l
  Length.l
EndStructure

; The following struct defines the interesting part of the IDENTIFY buffer

Structure IDSECTOR
  wGenConfig.w
  wNumCyls.w
  wReserved.w
  wNumHeads.w
  wBytesPerTrack.w
  wBytesPerSector.w
  wSectorsPerTrack.w
  wVendorUnique.w[3]
  sSerialNumber.s{20}
  wBufferType.w
  wBufferSize.w
  wECCSize.w
  sFirmwareRev.s{8}
  sModelNumber.s{40}
  wMoreVendorUnique.w
  wDoubleWordIO.w
  wCapabilities.w
  wReserved1.w
  wPIOTiming.w
  wDMATiming.w
  wBS.w
  wNumCurrentCyls.w
  wNumCurrentHeads.w
  wNumCurrentSectorsPerTrack.w
  ulCurrentSectorCapacity.l
  wMultSectorStuff.w
  ulTotalAddressableSectors.l
  wSingleWordDMA.w
  wMultiWordDMA.w
  bReserved.b[128]
EndStructure

#DFP_RECEIVE_DRIVE_DATA = $7C088 

bin.SENDCMDINPARAMS 
bout.SENDCMDOUTPARAMS 

Procedure.s ChangeHighLowByte(Instring.s) 
  ;Change BIG-Little Endian 
  sdummy.s="" 
  L=Len(Instring) 
  For I=1 To L Step 2 
   If (I+1)<=L 
    sdummy.s=sdummy.s + Mid(Instring,I+1,1)+Mid(Instring,I,1)  
   EndIf 
  Next I 
  ProcedureReturn sdummy.s 
EndProcedure 

; try the original method

mvarCurrentDrive=0 ;If you have more hard-disks change it here 

hdh = CreateFile_("\\.\PhysicalDrive" + Str(mvarCurrentDrive),#GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE,0, #OPEN_EXISTING, 0, 0) 

If hdh <> #INVALID_HANDLE_VALUE

    bin\bDriveNumber = mvarCurrentDrive 
    bin\cBufferSize = 512 
    
    If (mvarCurrentDrive & 1) 
      bin\irDriveRegs\bDriveHeadReg = $B0 
    Else 
      bin\irDriveRegs\bDriveHeadReg = $A0 
    EndIf 
    bin\irDriveRegs\bCommandReg = $EC 
    bin\irDriveRegs\bSectorCountReg = 1 
    bin\irDriveRegs\bSectorNumberReg = 1 

   br=0 
   Result=DeviceIoControl_( hdh, #DFP_RECEIVE_DRIVE_DATA, bin, SizeOf(SENDCMDINPARAMS), bout, SizeOf(SENDCMDOUTPARAMS), @br, 0) 
   If br>0 
    hddfr = 55:hddln = 40          : 
    Modell.s=ChangeHighLowByte(PeekS(@bout\bBuffer[0]+hddfr-1 ,hddln  ) ) 
    hddfr = 21:hddln = 20          : 
    Serial.s=Trim(ChangeHighLowByte(PeekS(@bout\bBuffer[0]+hddfr-1 ,hddln  ) )) 
    hddfr = 47:hddln = 8          
    Firmware.s=ChangeHighLowByte(PeekS(@bout\bBuffer[0]+hddfr-1 ,hddln  ) ) 
    MessageRequester("PhysicalDrive: Info about your harddisk","vendor(Modell)="+Modell.s + Chr(13) +"serial="+Serial.s+ Chr(13)+"Firmwareversion="+Firmware ,0) 
   EndIf 
   
Else 
  Beep_(100,100) ; heard this = failed
EndIf 

; ----------------------------------------------------------------------------------

; *** try SCSI back door approach *** (should be all that's needed, YMMV)
; ported from "int ReadIdeDriveAsScsiDriveInNT (void)" routine in diskid32.cpp (freeware)
; http://www.winsim.com/diskid32/diskid32.html

; valid values for the bCommandReg member of IDEREGS

#IDE_ATAPI_IDENTIFY = $A1   ; Returns ID sector For ATAPI.
#IDE_ATA_IDENTIFY = $EC     ; Returns ID sector For ATA.

#FILE_DEVICE_SCSI = $0000001b
#IOCTL_SCSI_MINIPORT_IDENTIFY = ((#FILE_DEVICE_SCSI << 16) + $0501)
#IOCTL_SCSI_MINIPORT = $0004D008

#IDENTIFY_BUFFER_SIZE = 512
#SENDIDLENGTH = SizeOf(SENDCMDOUTPARAMS) + #IDENTIFY_BUFFER_SIZE

; start

bin2.SENDCMDINPARAMS 
bout2.SENDCMDOUTPARAMS

For controller = 0 To 16

  hScsiDriveIOCTL = CreateFile_("\\.\Scsi" + Str(controller) + ":",#GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE,0, #OPEN_EXISTING, 0, 0) 
  
  If hScsiDriveIOCTL <> #INVALID_HANDLE_VALUE
  
      drive.l = 0
      
      For drive = 0 To 2
      
          buffer = AllocateMemory(SizeOf(SRB_IO_CONTROL) + #SENDIDLENGTH)
        
          dummy.l = 0
        
          p.SRB_IO_CONTROL
          p\HeaderLength = SizeOf(SRB_IO_CONTROL)
          p\Timeout = 10000
          p\Length = #SENDIDLENGTH
          p\ControlCode = #IOCTL_SCSI_MINIPORT_IDENTIFY
          p\Signature = "SCSIDISK"
          
          bin2\irDriveRegs\bCommandReg = #IDE_ATA_IDENTIFY
          bin2\bDriveNumber = drive
          
          CopyMemory(@p, buffer, SizeOf(SRB_IO_CONTROL))
          CopyMemory(@bin2, buffer + SizeOf(SRB_IO_CONTROL), SizeOf(bin2))
        
          If (DeviceIoControl_(hScsiDriveIOCTL, #IOCTL_SCSI_MINIPORT, buffer, SizeOf(SRB_IO_CONTROL) + SizeOf(SENDCMDINPARAMS) - 1, buffer, SizeOf(SRB_IO_CONTROL) + #SENDIDLENGTH, @dummy, #Null))
        
              CopyMemory(buffer + SizeOf(SRB_IO_CONTROL), @bout2, SizeOf(SENDCMDOUTPARAMS))
              
              pId.IDSECTOR
              
              CopyMemory(@bout2\bBuffer, @pId, SizeOf(IDSECTOR))
              
              modelNumber.s = ChangeHighLowByte(pId\sModelNumber)
              serialNumber.s = Trim(ChangeHighLowByte(pId\sSerialNumber))
              firmware.s = ChangeHighLowByte(pId\sFirmwareRev)
              
              str.s = "model = " + modelNumber + Chr(13) + "serial = " + serialNumber + Chr(13) + "firmware = " + firmware
              
              MessageRequester("HD check using SCSI " + Str(controller), str)
               
          EndIf
        
      Next drive
  
  EndIf
       
Next controller
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

Great! I'll have to try it over the next few days. Hopefully, so will dell_jockey

Regarding, Thunder's observation regarding the serial number dropping the last 0 on the string, could this be an issue related to PB's "zero-terminated" string constraint?
Image Image
kinglestat
Enthusiast
Enthusiast
Posts: 746
Joined: Fri Jul 14, 2006 8:53 pm
Location: Malta
Contact:

Post by kinglestat »

works like a charm
excellent work
BUT
It doesnt work with SCSI drives

and would be even fantastic if it worked with USB drives and such stuff
what you guys think ?

KingLestat
User avatar
Rings
Moderator
Moderator
Posts: 1435
Joined: Sat Apr 26, 2003 1:11 am

Post by Rings »

SPAMINATOR NR.1
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

OK - I want to use the SCSI method from mskuma a couple of posts back, but in PB 3.94 (so I don't need to convert a big block of code), but I am having problems with the fixed string sizes in the 4.0 structures, e.g.

Code: Select all

Structure SRB_IO_CONTROL
  HeaderLength.l
  Signature.s{8}
  Timeout.l
  ControlCode.l
  ReturnCode.l
  Length.l
EndStructure 
I think the problem is that SizeOf() returns a different size if if Signature.s is not fixed. How did we handle this problem in 3.94?

Any help would be appreciated.
Image Image
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

This is working under 3.94 here, but I just did it very quickly so it could be bugged:

Code: Select all

; retrieve harddisk's model, serial, firmware (Windows only, may only cover Win2k/XP) 
; original author Rings (posted Tue Jun 17, 2003) - requires admin rights 
; -> added non-admin access using alternative method using so-called 
; -> "SCSI back door" method from diskid32.cpp (ported to PB4 by mskuma) 

; IDE registers 

Structure IDEREGS 
  bFeaturesReg.b      ; Used for specifying SMART "commands". 
  bSectorCountReg.b   ; IDE sector count register 
  bSectorNumberReg.b  ; IDE sector number register 
  bCylLowReg.b        ; IDE low order cylinder value 
  bCylHighReg.b       ; IDE high order cylinder value 
  bDriveHeadReg.b     ; IDE drive/head register 
  bCommandReg.b       ; Actual IDE command. 
  bReserved.b         ; reserved for future use.  Must be zero. 
EndStructure 

; SENDCMDINPARAMS contains the input parameters for the send command To drive function 

Structure SENDCMDINPARAMS 
  cBufferSize.l       ; Buffer size in bytes 
  irDriveRegs.IDEREGS ; Structure with drive register values 
  bDriveNumber.b      ; Physical drive number to send command To (0,1,2,3) 
  bReserved.b[3]      ; Reserved for future expansion 
  dwReserved.l[4]     ; For future use 
  bBuffer.b[1]        ; Input buffer  
EndStructure 

Structure DRIVERSTATUS 
  bDriveError.b 
  bIDEStatus.b 
  bReserved.b[2] 
  dwReserved.l[2] 
EndStructure 

Structure SENDCMDOUTPARAMS 
  cBufferSize.l 
  DStatus.DRIVERSTATUS      
  bBuffer.b[512] 
EndStructure 

; following 2 structures relate to SCSI method 

Structure SRB_IO_CONTROL 
  HeaderLength.l 
  Signature.b[8]
  Timeout.l 
  ControlCode.l 
  ReturnCode.l 
  Length.l 
EndStructure 

; The following struct defines the interesting part of the IDENTIFY buffer 

Structure IDSECTOR 
  wGenConfig.w 
  wNumCyls.w 
  wReserved.w 
  wNumHeads.w 
  wBytesPerTrack.w 
  wBytesPerSector.w 
  wSectorsPerTrack.w 
  wVendorUnique.w[3] 
  sSerialNumber.b[20]
  wBufferType.w 
  wBufferSize.w 
  wECCSize.w 
  sFirmwareRev.b[8]
  sModelNumber.b[40]
  wMoreVendorUnique.w 
  wDoubleWordIO.w 
  wCapabilities.w 
  wReserved1.w 
  wPIOTiming.w 
  wDMATiming.w 
  wBS.w 
  wNumCurrentCyls.w 
  wNumCurrentHeads.w 
  wNumCurrentSectorsPerTrack.w 
  ulCurrentSectorCapacity.l 
  wMultSectorStuff.w 
  ulTotalAddressableSectors.l 
  wSingleWordDMA.w 
  wMultiWordDMA.w 
  bReserved.b[128] 
EndStructure 

#DFP_RECEIVE_DRIVE_DATA = $7C088 

bin.SENDCMDINPARAMS 
bout.SENDCMDOUTPARAMS 

Procedure.s ChangeHighLowByte(Instring.s) 
  ;Change BIG-Little Endian 
  sdummy.s="" 
  L=Len(Instring) 
  For I=1 To L Step 2 
   If (I+1)<=L 
    sdummy.s=sdummy.s + Mid(Instring,I+1,1)+Mid(Instring,I,1)  
   EndIf 
  Next I 
  ProcedureReturn sdummy.s 
EndProcedure 

; try the original method 

mvarCurrentDrive=0 ;If you have more hard-disks change it here 

hdh = CreateFile_("\\.\PhysicalDrive" + Str(mvarCurrentDrive),#GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE,0, #OPEN_EXISTING, 0, 0) 

If hdh <> #INVALID_HANDLE_VALUE 

    bin\bDriveNumber = mvarCurrentDrive 
    bin\cBufferSize = 512 
    
    If (mvarCurrentDrive & 1) 
      bin\irDriveRegs\bDriveHeadReg = $B0 
    Else 
      bin\irDriveRegs\bDriveHeadReg = $A0 
    EndIf 
    bin\irDriveRegs\bCommandReg = $EC 
    bin\irDriveRegs\bSectorCountReg = 1 
    bin\irDriveRegs\bSectorNumberReg = 1 

   br=0 
   Result=DeviceIoControl_( hdh, #DFP_RECEIVE_DRIVE_DATA, bin, SizeOf(SENDCMDINPARAMS), bout, SizeOf(SENDCMDOUTPARAMS), @br, 0) 
   If br>0 
    hddfr = 55:hddln = 40          : 
    Modell.s=ChangeHighLowByte(PeekS(@bout\bBuffer[0]+hddfr-1 ,hddln  ) ) 
    hddfr = 21:hddln = 20          : 
    Serial.s=Trim(ChangeHighLowByte(PeekS(@bout\bBuffer[0]+hddfr-1 ,hddln  ) )) 
    hddfr = 47:hddln = 8          
    Firmware.s=ChangeHighLowByte(PeekS(@bout\bBuffer[0]+hddfr-1 ,hddln  ) ) 
    MessageRequester("PhysicalDrive: Info about your harddisk","vendor(Modell)="+Modell.s + Chr(13) +"serial="+Serial.s+ Chr(13)+"Firmwareversion="+Firmware ,0) 
   EndIf 
    
Else 
  Beep_(100,100) ; heard this = failed 
EndIf 

; ---------------------------------------------------------------------------------- 

; *** try SCSI back door approach *** (should be all that's needed, YMMV) 
; ported from "int ReadIdeDriveAsScsiDriveInNT (void)" routine in diskid32.cpp (freeware) 
; http://www.winsim.com/diskid32/diskid32.html 

; valid values for the bCommandReg member of IDEREGS 

#IDE_ATAPI_IDENTIFY = $A1   ; Returns ID sector For ATAPI. 
#IDE_ATA_IDENTIFY = $EC     ; Returns ID sector For ATA. 

#FILE_DEVICE_SCSI = $0000001b 
#IOCTL_SCSI_MINIPORT_IDENTIFY = ((#FILE_DEVICE_SCSI << 16) + $0501) 
#IOCTL_SCSI_MINIPORT = $0004D008 

#IDENTIFY_BUFFER_SIZE = 512 
#SENDIDLENGTH = SizeOf(SENDCMDOUTPARAMS) + #IDENTIFY_BUFFER_SIZE 

; start 

bin2.SENDCMDINPARAMS 
bout2.SENDCMDOUTPARAMS 

For controller = 0 To 16 

  hScsiDriveIOCTL = CreateFile_("\\.\Scsi" + Str(controller) + ":",#GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE,0, #OPEN_EXISTING, 0, 0) 
  
  If hScsiDriveIOCTL <> #INVALID_HANDLE_VALUE 
  
      drive.l = 0 
      
      For drive = 0 To 2 
      
          buffer = AllocateMemory(SizeOf(SRB_IO_CONTROL) + #SENDIDLENGTH) 
        
          dummy.l = 0 
        
          p.SRB_IO_CONTROL 
          p\HeaderLength = SizeOf(SRB_IO_CONTROL) 
          p\Timeout = 10000 
          p\Length = #SENDIDLENGTH 
          p\ControlCode = #IOCTL_SCSI_MINIPORT_IDENTIFY 
          PokeS(@p\Signature, "SCSIDISK" )
          
          bin2\irDriveRegs\bCommandReg = #IDE_ATA_IDENTIFY 
          bin2\bDriveNumber = drive 
          
          CopyMemory(@p, buffer, SizeOf(SRB_IO_CONTROL)) 
          CopyMemory(@bin2, buffer + SizeOf(SRB_IO_CONTROL), SizeOf(bin2)) 
        
          If (DeviceIoControl_(hScsiDriveIOCTL, #IOCTL_SCSI_MINIPORT, buffer, SizeOf(SRB_IO_CONTROL) + SizeOf(SENDCMDINPARAMS) - 1, buffer, SizeOf(SRB_IO_CONTROL) + #SENDIDLENGTH, @dummy, #Null)) 
        
              CopyMemory(buffer + SizeOf(SRB_IO_CONTROL), @bout2, SizeOf(SENDCMDOUTPARAMS)) 
              
              pId.IDSECTOR 
              
              CopyMemory(@bout2\bBuffer, @pId, SizeOf(IDSECTOR)) 
              
              modelNumber.s = ChangeHighLowByte(PeekS(@pId\sModelNumber,SizeOf(IDSECTOR\sModelNumber)))
              serialNumber.s = Trim(ChangeHighLowByte(PeekS(@pId\sSerialNumber,SizeOf(IDSECTOR\sSerialNumber))) )
              firmware.s = ChangeHighLowByte(PeekS(@pId\sFirmwareRev, SizeOf(IDSECTOR\sFirmwareRev)))
              
              str.s = "model = " + modelNumber + Chr(13) + "serial = " + serialNumber + Chr(13) + "firmware = " + firmware 
              
              MessageRequester("HD check using SCSI " + Str(controller), str) 
                
          EndIf 
        
      Next drive 
  
  EndIf 
        
Next controller 
[EDIT] Bug fixed, sorry!
Last edited by netmaestro on Thu May 03, 2007 7:07 pm, edited 1 time in total.
BERESHEIT
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

Awesome! Thanks netmaestro. Works perfectly. And thanks mskuma for the code!
Image Image
ricky
New User
New User
Posts: 8
Joined: Fri Sep 07, 2012 9:27 am
Location: Suisse

Re: retrieve harddisk`s modell,serial,firmware (Windows only

Post by ricky »

Hello,

sorry to up this topic, but I have a problem. I modify the original script, to create ma modified script. But I have an error and I not understand.

Code: Select all


mvarCurrentDrive = 0 ;If you have more hard-disks change it here

NbParametres = CountProgramParameters()

If NbParametres <> 3 
  End -1
EndIf

Fonction$ = ProgramParameter(0)
Resultat$ = ProgramParameter(1)
Path$ = ProgramParameter(2)

If Resultat$ <> ""
  mvarCurrentDrive = Val(Resultat$)
EndIf  

If Path$ = ""
  Path$ = "C:\HDD.txt"
EndIf 

If Val(Fonction$) = 1 
  SNHDD (mvarCurrentDrive, Path$)
Else
  End -2
EndIf

Procedure.s ChangeHighLowByte(Instring.s)
;Change BIG-Little Endian
sdummy.s=""
L=Len(Instring)
  For I=1 To L Step 2
   If (I+1)<=L
    sdummy.s=sdummy.s + Mid(Instring,I+1,1)+Mid(Instring,I,1) 
   EndIf
  Next I
ProcedureReturn sdummy.s
EndProcedure

Procedure SNHDD (CurrentDrive, File$)
   
  Structure IDEREGS
      bFeaturesReg.b
      bSectorCountReg.b
      bSectorNumberReg.b
      bCylLowReg.b
      bCylHighReg.b
      bDriveHeadReg.b
      bCommandReg.b
      bReserved.b
    EndStructure
    
  Structure SENDCMDINPARAMS
      cBufferSize.l
      irDriveRegs.IDEREGS
      bDriveNumber.b
      bReserved.b[3]
      dwReserved.l[4]
  EndStructure
  
  Structure  DRIVERSTATUS
      bDriveError.b
      bIDEStatus.b
      bReserved.b[2]
      dwReserved.l[2]
    EndStructure
    
  Structure  SENDCMDOUTPARAMS
      cBufferSize.l
      DStatus.DRIVERSTATUS     
      bBuffer.b[512]
  EndStructure  
  
#DFP_RECEIVE_DRIVE_DATA = $7C088

bin.SENDCMDINPARAMS
bout.SENDCMDOUTPARAMS
  
  
hdh = CreateFile_("\\.\PhysicalDrive" + Str(CurrentDrive),#GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE,0, #OPEN_EXISTING, 0, 0)
  If hdh 
          bin\bDriveNumber = CurrentDrive
          bin\cBufferSize = 512
         
          If (CurrentDrive & 1)
            bin\irDriveRegs\bDriveHeadReg = $B0
          Else
            bin\irDriveRegs\bDriveHeadReg = $A0
          EndIf
          bin\irDriveRegs\bCommandReg = $EC
          bin\irDriveRegs\bSectorCountReg = 1
          bin\irDriveRegs\bSectorNumberReg = 1
     
         br=0
         Result=DeviceIoControl_( hdh, #DFP_RECEIVE_DRIVE_DATA, bin, SizeOf(SENDCMDINPARAMS), bout, SizeOf(SENDCMDOUTPARAMS), @br, 0)
         If br>0
          hddfr = 55:hddln = 40          :
          Modell.s=ReplaceString(ChangeHighLowByte(PeekS(@bout\bBuffer[0]+hddfr-1 ,hddln  ) ),"  ","") + ":"
          Modell.s=ReplaceString(Modell.s," :","")
          hddfr = 21:hddln = 20          :
          Serial.s=ReplaceString(Trim(ChangeHighLowByte(PeekS(@bout\bBuffer[0]+hddfr-1 ,hddln  ) ))," ","")
          hddfr = 47:hddln = 8         
          Firmware.s=ReplaceString(ChangeHighLowByte(PeekS(@bout\bBuffer[0]+hddfr-1 ,hddln  ) )," ","")
          
          DeleteFile(File$)
  
          If OpenFile(0, File$)    ; Ouvre un fichier existant ou en crée un nouveau s'il n'existait pas
            FileSeek(0, Lof(0))         ; Place le pointeur à la fin du fichier en utilisant le résultat de Lof() 
            WriteStringN(0, Serial.s + ":"+ Modell.s + ":"+ Firmware.s)
            CloseFile(0)
          EndIf
  
          End 1
         EndIf
  Else
    End 0
  EndIf
EndProcedure
My error in the syntax check is : Line 24: SNHDD() is not a function, array, list, map or macro
Thanks for your help
Post Reply