Page 4 of 8
Posted: Wed Apr 05, 2006 8:47 pm
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?
Posted: Wed Apr 05, 2006 9:43 pm
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!
Posted: Thu Apr 06, 2006 9:48 am
by dell_jockey
Straker wrote:
@dell_jockey: Bummer. Must be hard drive specific. Thanks for the attempt.
You're welcome anytime...
Posted: Wed May 31, 2006 12:02 pm
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.
Posted: Wed May 31, 2006 12:40 pm
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.
Posted: Wed May 31, 2006 2:32 pm
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....
Posted: Wed May 31, 2006 11:14 pm
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.
Posted: Thu Jun 01, 2006 2:01 am
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
Posted: Thu Jun 01, 2006 4:09 pm
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?
Posted: Wed Jan 31, 2007 4:44 pm
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
Posted: Tue Feb 27, 2007 1:05 pm
by Rings
Posted: Thu May 03, 2007 6:12 pm
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.
Posted: Thu May 03, 2007 6:45 pm
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!
Posted: Thu May 03, 2007 7:05 pm
by Straker
Awesome! Thanks netmaestro. Works perfectly. And thanks mskuma for the code!
Re: retrieve harddisk`s modell,serial,firmware (Windows only
Posted: Thu Mar 21, 2013 4:52 pm
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