Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Just starting out? Need help? Post your questions and find answers here.
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by ZX80 »

Hello, everyone.

Does anyone know why the code in this (by mskuma) thread may not enumerate / display devices correctly in Windows XP ?
I'll duplicate it here with minor changes since I don't need a fingerprint. I'm just looking for certain equipment. This code does not enumerate all connected equipment and truncates the lines. :?

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 EnumHardwareDevices()
  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
  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 PeekS(*buffer)
     
    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
  EndIf
  
  ; Cleanup
  SetupDiDestroyDeviceInfoList_(hDevInfo)
EndProcedure


; testing
EnumHardwareDevices()
Can anyone check this and fix it ?
Thank you.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by RASHAD »

If you are running the snippet with PB 6.1+
PB 6.1+ don't support XP anymore
Egypt my love
fryquez
Enthusiast
Enthusiast
Posts: 391
Joined: Mon Dec 21, 2015 8:12 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by fryquez »

This should fix x64 compatibility, but error handling should be added still.

Code: Select all

EnableExplicit
; 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 Align #PB_Structure_AlignC
  cbSize.l
  ClassGuid.GUID
  DevInst.l;    // DEVINST handle
  Reserved.i;
EndStructure
   
Procedure EnumHardwareDevices()
  Protected hDevInfo, DataT, i, buffersize.l, *buffer
  Protected DeviceInfoData.SP_DEVINFO_DATA
  Protected devicesList.s
  
  ; Create a HDEVINFO with all present devices
  hDevInfo = SetupDiGetClassDevs_(#Null,0, 0, #DIGCF_PRESENT | #DIGCF_ALLCLASSES)
    
  If hDevInfo = #INVALID_HANDLE_VALUE
    ProcedureReturn
  EndIf
  
  ; Enumerate through all devices in Set
  DeviceInfoData\cbSize = SizeOf(SP_DEVINFO_DATA)
    
  While SetupDiEnumDeviceInfo_(hDevInfo, i, @DeviceInfoData) 
    
    *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
     
     
    If (*buffer)
      Debug PeekS(*buffer)
      devicesList + PeekS(*buffer) ; build a string for purposes of doing a hash later
      FreeMemory(*buffer)
    EndIf
     
    i+1  ; increment to next device
  Wend
  
  Debug #CRLF$ + "Count:" + Str(i)
  
  ; finish up
  If ( GetLastError_() <> #NO_ERROR And GetLastError_() <> #ERROR_NO_MORE_ITEMS )
    ; Insert error handling here
    ProcedureReturn
  EndIf
  
  ; Cleanup
  SetupDiDestroyDeviceInfoList_(hDevInfo)
EndProcedure


; testing
EnumHardwareDevices()
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by ZX80 »

RASHAD, thank you very much !
I know about it. I run it on PB, version 5.73 (x86). The OS is also 32-bit.

fryquez, thank you for your reply and your attempt, but...
Unfortunately... it didn't help. I don't know for sure... maybe the reason is in my OS ?
If anyone else is using this OS or has access to it, could you run this code and report the result here.

Thank you !

P.S. The main problem with this code is that the hardware strings are not fully displayed (truncated).
For example, I'm looking for serial port numbers (I'm interested in exactly what's in parentheses), but all I see is this:
"Serial Port". :?

Who knows why ?
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by ZX80 »

I know there is a special system API function for this... such as EnumPorts and it works well, but... Why does the above code not work correctly ?
PeDe
Enthusiast
Enthusiast
Posts: 278
Joined: Sun Nov 26, 2017 3:13 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by PeDe »

Hello ZX80,

I have tested the code from fryquez with PB v5.73 and XP. The output of 'Serial Port' here on a German system is 'Kommunikationsanschluss'. I think nothing is cut off, the output is the same on other systems, e.g. Windows 7.

The output of the serial port with port name is the 'Friendly Name', as shown here in my example code (German):
https://www.purebasic.fr/german/viewtop ... 81#p366381

Code: Select all

[Debug] sName: COM1
[Debug] sDescription: Kommunikationsanschluss
[Debug] sManufacturer: (Standardanschlusstypen)
[Debug] sFriendlyName: Kommunikationsanschluss (COM1)
Peter
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by ZX80 »

Thank you very much for your test, Peter.

But I have to disagree with you.
Computer management -> device manager -> Ports (COM and LPT) shows me:
"Printer Port (LPT1)"
"Serial Port (COM1)"
Yes, this is also not the language of my system and I brought it to an international form, but in this case it doesn’t matter, doesn't it ?
I am sure that this is a standard and no matter what location you are in, the brackets will always be present, and inside them the port number.
This is exactly what my question is. I want to know what equipment is currently connected. The registry is a bad help here.
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by ZX80 »

Does NOT find ports that are already open
One of the reasons why the EnumPorts is not used.

Peter, thanks for sharing the code.
Last edited by ZX80 on Thu Aug 22, 2024 2:14 pm, edited 1 time in total.
PeDe
Enthusiast
Enthusiast
Posts: 278
Joined: Sun Nov 26, 2017 3:13 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by PeDe »

ZX80 wrote: Thu Aug 22, 2024 1:35 pm But I have to disagree with you.
Computer management -> device manager -> Ports (COM and LPT) shows me:
If I look at the output from the processor, for example, there are also differences here:

Device Manager - Processors:
4 x Inter(R) Celeron(R) CPU J1900 @ 1.99 GHz

Code:
4 x [Debug] Intel processor

I think the descriptions are simply different.

Peter
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by ZX80 »

Peter, I think that one way or another, the API takes information from the registry.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\1 shows the following data:
FriendlyName (REG_SZ) - Serial Port (COM1)
I see the same name in the device manager. Then why doesn't the code show it completely ?
fryquez
Enthusiast
Enthusiast
Posts: 391
Joined: Mon Dec 21, 2015 8:12 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by fryquez »

You use #SPDRP_DEVICEDESC for Property, maybe you want #SPDRP_FRIENDLYNAME.

Code: Select all

#SPDRP_FRIENDLYNAME = $0C
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by ZX80 »

fryquez, I think you have a 100 percent hit :!:

But...
I get a very short list of devices. There are so few devices that provide a friendly string ? :shock:
What to do next ? Do I need to check each device twice ?
If it can return a friendly name, then print it, otherwise what DEVICEDESC returns. Right ?

P.S. At the moment I don't have access to a Windows XP computer, but I tested this (your amendment) on another system with a "USB-SERIAL CH340 (COM3)" controller. And it very much seems that what you said is #true !

#SPDRP_DEVICEDESC returns the string: USB-SERIAL CH340
#SPDRP_FRIENDLYNAME returns the string: USB-SERIAL CH340 (COM3)


Thank you !
PeDe
Enthusiast
Enthusiast
Posts: 278
Joined: Sun Nov 26, 2017 3:13 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by PeDe »

ZX80 wrote: Thu Aug 22, 2024 2:36 pm P.S. At the moment I don't have access to a Windows XP computer,
The code works compiled with PB v6.04 with Windows 2000 and XP. The output of the list with 'FriendlyName' is very short under W2k, slightly longer with XP on the same PC.

Peter
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: Rebirth oldest theme - "Enumerate hardware devices (Windows)"

Post by ZX80 »

Peter, thank you very much again for the results of your testing. I thought so. Now I'm thinking about how I can combine these two device property requests to ultimately get exactly the same picture as in the device manager. I would like to avoid unnecessary steps (request it twice). But I think there is no other way.
Post Reply