Enumerate hardware devices (Windows)
Posted: Mon Jun 26, 2006 3:10 am
Code updated For 5.20+
I was interested to see if it's possible to do a 'machine fingerprint' (i.e. detect a machine's hardware add/remove changes) via listing up hardware devices periodically, so I came up with this.
Improvement suggestions welcome.
I was interested to see if it's possible to do a 'machine fingerprint' (i.e. detect a machine's hardware add/remove changes) via listing up hardware devices periodically, so I came up with this.
Code: Select all
; How to enumerate hardware devices by using SetupDi calls
; mskuma 26 June 2006
; adapted from http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q259695
; (Windows only)
#DIGCF_PRESENT = $00000002
#DIGCF_ALLCLASSES = $00000004
#SPDRP_DEVICEDESC = $00000000
Structure SP_DEVINFO_DATA
cbSize.l
ClassGuid.GUID
DevInst.l; // DEVINST handle
Reserved.l;
EndStructure
Procedure.s FingerprintMachineByEnumHardwareDevices()
hDevInfo.l = 0
DeviceInfoData.SP_DEVINFO_DATA
i.l = 0
devicesList.s = ""
; Create a HDEVINFO with all present devices
hDevInfo = SetupDiGetClassDevs_(#Null,0, 0, #DIGCF_PRESENT | #DIGCF_ALLCLASSES)
If hDevInfo = #INVALID_HANDLE_VALUE
ProcedureReturn "0"
EndIf
; Enumerate through all devices in Set
DeviceInfoData\cbSize = SizeOf(SP_DEVINFO_DATA)
While SetupDiEnumDeviceInfo_(hDevInfo, i, @DeviceInfoData)
DataT.l
*buffer = #Null
buffersize.l = 0
; Call function with null to begin with,
; then use the returned buffer size (doubled)
; to allocate the buffer. Keep calling until
; success Or an unknown failure.
;
; Double the returned buffersize to correct
; For underlying legacy CM functions that
; Return an incorrect buffersize value on
; DBCS/MBCS systems.
While Not SetupDiGetDeviceRegistryProperty_(hDevInfo,@DeviceInfoData,#SPDRP_DEVICEDESC,@DataT,*buffer,buffersize,@buffersize)
If (GetLastError_() = #ERROR_INSUFFICIENT_BUFFER)
; Allocate the buffer size, using twice the size to avoid problems on W2k MBCS systems per KB 888609
*buffer = AllocateMemory(buffersize*2)
Else
; Insert error handling here
Break
EndIf
Wend
Debug "Device: " + PeekS(*buffer) ; just for checking
devicesList + PeekS(*buffer) ; build a string for purposes of doing a hash later
If (*buffer)
FreeMemory(*buffer)
EndIf
i+1 ; increment to next device
Wend
; finish up
If ( GetLastError_() <> #NO_ERROR And GetLastError_() <> #ERROR_NO_MORE_ITEMS )
; Insert error handling here
ProcedureReturn "0"
EndIf
; Cleanup
SetupDiDestroyDeviceInfoList_(hDevInfo)
ProcedureReturn MD5Fingerprint(@devicesList,Len(devicesList))
EndProcedure
; testing
Debug "Fingerprint = " + FingerprintMachineByEnumHardwareDevices()