Page 2 of 8

What about SATA Drives?

Posted: Sun Mar 07, 2004 6:44 pm
by dagcrack
And what about SATA (Serial ATA) HardDrives ?

Posted: Sun Mar 07, 2004 6:49 pm
by dagcrack
What If I have more than 1 harddrive (I do)...
I havent seen the source yet, Im very busy, but I just compiled it very quick and detected the first harddrive only..

Posted: Sun Mar 07, 2004 8:00 pm
by Rings
if you so busy, sit down , take the source, study it.
......after that replace the names of the drives with your own new needed .

Posted: Sun Mar 07, 2004 9:30 pm
by Shannara
If any client installs WMI, no matter what version of Windows they run, the above code should work.

Posted: Sat Mar 13, 2004 1:41 pm
by blueznl
would make a nice collection... how to identify a machine...

- harddisk serial numbers
- cpu serial numbers
- mac adresses
- bios checksum (can this still be done under nt / xp?)
- ip address (not the most reliable thing)
- what next? :-)

Posted: Sat Aug 28, 2004 6:20 pm
by Max.²
I extended Rings' snippet a bit so it reads also the S.M.A.R.T. data of an harddisk (if the HDD is capable of).

The values are held in two structures.

bAttrValue is the current value of an attribute. Attribute means certain monitoring parameter, like temperature, read errors and such.

bWorstValue is speaking for itself.

bRawValue is the value translated; for example, for Attribute 194 my system reports "104" as current value, "7" as worst (O_o), "0" as threshold and "39" as raw value. The "39" is "39 °C", as we are talking about temperatures.

bWarrantyThreshold is the value defined by the vendor and the actual value should never be below.

Though standardized to a certain amount, SMART is supported differently by vendors sometimes or special attributes are added and such. Also, different revisions of the ATA specification extend the original SMART features.

To confirm the values or get a hint what they mean, go to http://www.passmark.com and download their SMART tool (free for personal use).

This snippet works with NT based systems; to get it to work win Win 98/ME & Co, have a look at one of the previous postings, where SMARTVSD is used instead of PhysicalDrive.

Code: Select all

Structure DRIVEATTRIBUTE
  bAttrID.b
  wStatusFlags.w
  bAttrValue.b
  bWorstValue.b
  bRawValue.b[6]
  bReserved.b
EndStructure

Structure ATTRTHRESHOLD
  bAttrID.b
  bWarrantyThreshold.b
  bReserved.b[10]
EndStructure
Do not copy and paste the structures; they are already in the code below and reason for posting them seperatly is to get you a pointer.

The code below first reads basic harddisk info (as posted with Rings' snippet), the next call fills the ATTRTHRESHOLD structure and the last call fills the DRIVEATTRIBUTE structure.

Feel free to ask. I hope I can answer. ;)

Code: Select all

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 

Structure DRIVEATTRIBUTE
  bAttrID.b
  wStatusFlags.w
  bAttrValue.b
  bWorstValue.b
  bRawValue.b[6]
  bReserved.b
EndStructure

Structure ATTRTHRESHOLD
  bAttrID.b
  bWarrantyThreshold.b
  bReserved.b[10]
EndStructure

#DFP_RECEIVE_DRIVE_DATA = $7C088
#DFP_SEND_DRIVE_COMMAND = $7c084
#SMART_ENABLE_SMART_OPERATIONS = $d8
#SMART_CYL_LOW = $4F
#SMART_CYL_HI = $C2
#IDE_EXECUTE_SMART_FUNCTION = $b0
#SMART_READ_ATTRIBUTE_VALUES = $d0
#SMART_READ_ATTRIBUTE_THRESHOLDS = $d1



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 


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  
        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  ) ) 
        Debug "Model: "+Modell.s 
        Debug "Serial: "+Serial.s
        Debug  "Firmware: "+Firmware.s 
       EndIf 

       bin\irDriveRegs\bFeaturesReg = #SMART_ENABLE_SMART_OPERATIONS
       bin\irDriveRegs\bSectorCountReg = 1
       bin\irDriveRegs\bSectorNumberReg = 1
       bin\irDriveRegs\bCylLowReg = #SMART_CYL_LOW
       bin\irDriveRegs\bCylHighReg = #SMART_CYL_HI
       bin\irDriveRegs\bCommandReg = #IDE_EXECUTE_SMART_FUNCTION
       bin\bDriveNumber = mvarCurrentDrive
       If (mvarCurrentDrive & 1) 
          bin\irDriveRegs\bDriveHeadReg = $B0 
        Else 
          bin\irDriveRegs\bDriveHeadReg = $A0 
       EndIf 
       br=0 
       Result=DeviceIoControl_( hdh, #DFP_SEND_DRIVE_COMMAND, bin, SizeOf(SENDCMDINPARAMS), bout, SizeOf(SENDCMDOUTPARAMS), @br, 0) 
       Debug hdh
       Debug GetLastError_()
       Debug Result
       If br>0 
        Debug "#SMART_ENABLE_SMART_OPERATIONS successful"
       EndIf
       
       bin\irDriveRegs\bFeaturesReg = #SMART_READ_ATTRIBUTE_THRESHOLDS
       br=0 
       Result=DeviceIoControl_( hdh, #DFP_RECEIVE_DRIVE_DATA, bin, SizeOf(SENDCMDINPARAMS), bout, SizeOf(SENDCMDOUTPARAMS), @br, 0) 
       If br>0 
        Debug "#SMART_READ_ATTRIBUTE_THRESHOLDS successful"
        i=0
        *pTA.ATTRTHRESHOLD = @bout\bBuffer[0]+2
        While *pTA\bAttrID & $FF <> 0
          Debug "Attribute "+Str(*pTA\bAttrID & $FF)
          Debug *pTA\bWarrantyThreshold & $FF
          *pTA.ATTRTHRESHOLD = *pTA.ATTRTHRESHOLD + SizeOf(ATTRTHRESHOLD)
        Wend
       EndIf

       
       bin\irDriveRegs\bFeaturesReg = #SMART_READ_ATTRIBUTE_VALUES
       br=0 
       Result=DeviceIoControl_( hdh, #DFP_RECEIVE_DRIVE_DATA, bin, SizeOf(SENDCMDINPARAMS), bout, SizeOf(SENDCMDOUTPARAMS), @br, 0) 
       If br>0 
        Debug "#SMART_READ_ATTRIBUTE_VALUES successful"
        i=0
        *pDA.DRIVEATTRIBUTE = @bout\bBuffer[0]+2
        While *pDA\bAttrID & $FF <> 0
          Debug "Attribute "+Str(*pDA\bAttrID & $FF)
          Debug *pDA\bAttrValue & $FF
          Debug *pDA\bWorstValue & $FF
          Debug (*pDA\bRawValue[0] & $FF) + (*pDA\bRawValue[1] & $FF) * 256
          Debug ""
          *pDA.DRIVEATTRIBUTE = *pDA.DRIVEATTRIBUTE + SizeOf(DRIVEATTRIBUTE)
        Wend
       EndIf

Else 
  Beep_(100,100) 
EndIf 
[/code]

Posted: Tue May 17, 2005 12:30 am
by Phant0m``
Are any of the codes posted in this topic more suited for Western Digital's Hard Drives running Windows XP systems?

Posted: Tue May 17, 2005 10:28 am
by Max.
Phant0m`` wrote:Are any of the codes posted in this topic more suited for Western Digital's Hard Drives running Windows XP systems?
Dunno what your problem is; I am using only WD drives on XP.

Posted: Tue May 17, 2005 10:55 am
by Phant0m``

Code: Select all

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

Procedure.s ChangeHighLowByte(Instring.s) 
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 

mvarCurrentDrive=0
#VER_PLATFORM_WIN32_WINDOWS=1 
VersionInfo.OSVERSIONINFO 
  
VersionInfo\dwOSVersionInfoSize = SizeOf(OSVERSIONINFO) 
res=GetVersionEx_(VersionInfo) 
If res 
 If VersionInfo\dwPlatformId=#VER_PLATFORM_WIN32_WINDOWS
  hdh=CreateFile_("\\.\SMARTVSD",#GENERIC_READ,#FILE_SHARE_READ,0,#OPEN_EXISTING,0,0)
 Else
  hdh=CreateFile_("\\.\PhysicalDrive"+Str(mvarCurrentDrive),#GENERIC_READ|#GENERIC_WRITE,#FILE_SHARE_READ|#FILE_SHARE_WRITE,0,#OPEN_EXISTING,0,0)  
 EndIf 
EndIf

If hdh
        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 = 21:hddln = 20
        ;;;For an XP user, especially, this is the spot it 'should' goto.
        Else
        ;;;With one system running WinXP Home and using WD Hard drive, this is where she ends up...
        End
       EndIf
EndIf
I'm thinking maybe this code isn't suited for Partitioned drive split up into two.

Posted: Tue May 17, 2005 11:04 am
by Max.
Phant0m`` wrote: I'm thinking maybe this code isn't suited for Partitioned drive split up into two.
You mean, you got a partitioned Western Digital hard disk drive and the code stops here:

Code: Select all

        ;;;With one system running WinXP Home and using WD Hard drive, this is where she ends up...
        End
?

Posted: Tue May 17, 2005 11:05 am
by Phant0m``
WD in a raid 0 array, :/

Posted: Tue May 17, 2005 11:05 am
by Phant0m``
That is correct Max..

Posted: Tue May 17, 2005 1:07 pm
by Max.
Phant0m`` wrote:WD in a raid 0 array, :/
From a bit of browsing the internet, this seems to be the problem then.

I found one hint that you need to use an ASPI driver which is not required for normal operation to get it to work with SCSI and RAID controllers.

Adaptec provides one here:
http://www.adaptec.com/worldwide/suppor ... =ASPI-4.70

I can not try it due to lack of a raid controller (raid-0... shiver... last time I did set up was 10 years ago. Now I am a bit to cowardous for that :wink: ), but if you try it would be nice to get some report.

Posted: Tue May 17, 2005 1:12 pm
by Phant0m``
Thanks Max.

I'll keep you posted.. :)

Posted: Wed May 18, 2005 1:08 am
by Phant0m``
Nope, didn't work.

The system using Promise 2+0 Stripe/RAID0 SCSI Driver