Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

USB non HID device name

Posted on 2006-11-21
10
3,119 Views
Last Modified: 2012-06-21
I need to know a device and driver name of a connected USB-storage stick/card. For HID class devices I can use TJvHIDController (JEDI) but for non-HID devices I haven't found no help. I use WM_DEVICECHANGE message for DBT_DeviceArrival/DBT_DeviceRemoveComplete to get a driver letter but I need the name...
0
Comment
Question by:JacekH
  • 4
  • 3
  • 2
  • +1
10 Comments
 
LVL 4

Expert Comment

by:Meldrachaun
ID: 17991227
It looks like the TJclSCManager (JEDI) component may be what you need.
0
 

Author Comment

by:JacekH
ID: 17991289
Well, it looks that JclSCManager controls windows services and has no info about DBT devices.... If I'm wrong please give a short example how can I use it to read a USB device name.
0
 
LVL 9

Expert Comment

by:bernani
ID: 17992291
Hi,

Maybe sth like this (found on a french group)

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type

 PDEV_BROADCAST_HDR = ^TDEV_BROADCAST_HDR;
 TDEV_BROADCAST_HDR = packed record
   dbch_size : DWORD;
   dbch_devicetype : DWORD;
   dbch_reserved : DWORD;
  end;

  PDEV_BROADCAST_VOLUME = ^TDEV_BROADCAST_VOLUME;
  TDEV_BROADCAST_VOLUME = packed record
   dbcv_size : DWORD;
   dbcv_devicetype : DWORD;
   dbcv_reserved : DWORD;
   dbcv_unitmask : DWORD;
   dbcv_flags : WORD;
  end;

type
  TForm1 = class(TForm)
   Memo1: TMemo;

  private
    { Déclarations privées }
  procedure WMDeviceChange(var Msg: TMessage);     message WM_DEVICECHANGE;
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;
  GetDriveLetter : string;
implementation

{$R *.dfm}

// Capture Event Wind WMDeviceChange
procedure TForm1.WMDeviceChange(var Msg: TMessage);
var
    VolName, FileSysName : Array[0..Max_Path]Of Char;
    VolSerial, FileMaxLen, FileFlags : DWord;
    S : string;
begin

// Check ifi DBT_DEVICEARRIVAL = $8000
// If yes, only to handle storage divices of type 0=DeviceTypeOEM

  if Msg.wParam =$8000 then begin
          if PDEV_BROADCAST_HDR( Msg.LParam )^.dbch_devicetype <>2 then exit;
          if PDEV_BROADCAST_VOLUME( Msg.LParam )^.dbcv_flags <>0 then exit;

 S := 'Device connected' +#13+#10+#13+#10;
// Letter Device
 str(ln(PDEV_BROADCAST_VOLUME( Msg.LParam )^.dbcv_unitmask)/ln(2)+Ord('A'):2:0,GetDriveLetter);
 S := S + 'DeviceID :'+#9+#9+ char(strtoint(GetDriveLetter)) + ':\' + #13+#10;
// VolumeName + FileSystem + Device Serial Number
 If GetVolumeInformation(pchar(char(strtoint(GetDriveLetter))+':\'),VolName,Max_Path,@VolSerial, FileMaxLen, FileFlags,FileSysName,Max_Path) then
S := S +
       'Volume Name :' +#9+#9+ VolName +#13+#10
       'Filesystem :' +#9+ FileSysName +#13+#10
       'Serial Number :' +#9+#9+ IntToStr(VolSerial)+#13+#10;
// Size and free device space
 S := S +
'Total Sie :' +#9+#9+ FloatToStrF(DiskSize(strtoint(GetDriveLetter)-64)div 1024, ffNumber, 18, 0) + ' Ko' + #13+#10;
S :=
S + 'Available :' +#9+#9+ FloatToStrF(DiskFree(strtoint(GetDriveLetter)-64) div 1024, ffNumber, 18, 0) + ' Ko';

Memo1.text:=S;
Beep;             // When connecting
end;

// Check if DBT_DEVICEREMOVECOMPLETE = $8004
// Yes, handle only device of type 0=DeviceTypeOEM

  if Msg.wParam =$8004 then begin
          if PDEV_BROADCAST_HDR( Msg.LParam )^.dbch_devicetype <>2 then exit;
          if PDEV_BROADCAST_VOLUME( Msg.LParam )^.dbcv_flags <>0 then exit;

// Disconnect
S := 'Device disconnected.' +#13+#10+#13+#10;
// Letter device "DeviceID"
str(ln(PDEV_BROADCAST_VOLUME( Msg.LParam )^.dbcv_unitmask)/ln(2)+Ord('A'):2:0,GetDriveLetter);
 S := S + 'DeviceID :' +#9+#9+ char(strtoint(GetDriveLetter)) + ':\' + #13+#10;
 Memo1.text:=S;
 Beep; // Disconnected
end;

end;

end.

// Could be improved but it's functionnal and the report in the memo looks sth like this:


Device connected

DeviceID :            I:\
VolumeName :Maxtor-III  -----> to get a driver letter but I need the name...
FileSystem : NTFS
Serial Number :      2430142829
Total Size       : 26.973.134 Ko
Available        : 5.290.909 Ko

Hope this help.
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 9

Expert Comment

by:bernani
ID: 17993628
Hi

Forgot to say:

To use, compile the code above (it's only a form with a TMemo) and launch you app. When this one is open, connect and disconnect a USB device to see the messages displayed in the memo.

0
 

Author Comment

by:JacekH
ID: 17993810
Bernani,

That's not a solution. I can get a volume name. But I need a DEVICE name, not volume. When you connect a memory stick you can see a device name (as a New hardware found notification in a system tray) and that's what I need. I need a device name for __non_HID__ devices. HID devices are covered by JvHIDController component from JEDI project.

Jacek
0
 
LVL 11

Assisted Solution

by:robert_marquardt
robert_marquardt earned 200 total points
ID: 17994089
This is problematic because i am not sure if this is stored in the registry.
The name comes either from the device itself or from the INF file of the driver and is probably only accessed by the New Hardware Wizard on first plug.

Getting the string from the INF file is possible with the Setup API (the conversion is part of TJvHIDController), but i never used the functions.
Getting the string from the device is hard because the only way is the USBVIEW way which is an example of the Windows DDK.
I have an example available. Get the modules scapi and win32api from http://jedi-apilib.sf.net
In scapi there is the example USBVIEW which should help you along.

Unfortunately it may not possible to completel solve your problem because the functions of the Setup API and the Config Manager API are badly designed and buggy.
Even New Hardware Wizards of the different Windows versions do not show the same string from the device.
0
 

Author Comment

by:JacekH
ID: 17995170
Robert,
It looks that's very close to what I need. With SafeRemoval demo I get GUIDs I can use to read from registry CurrentControlSet - USBSTOR. I'll check tonight. Thank you, I'll let you know.

Jacek
0
 
LVL 9

Accepted Solution

by:
bernani earned 100 total points
ID: 17995662
Hi,

Sorry, I misunderstood your question

The values of the string returned by the HardwareID key in the Registry under

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USBSTOR\Disk&Ven_Maxtor&Prod_6Y160P0&Rev_YAR4\10000E0009572FC4&0

USBSTOR\DiskMaxtor__6Y160P0_________YAR4
USBSTOR\DiskMaxtor__6Y160P0_________
USBSTOR\DiskMaxtor__
USBSTOR\Maxtor__6Y160P0_________Y
Maxtor__6Y160P0_________Y
USBSTOR\GenDisk
GenDisk

or the value returned by FriendlyName wich gives in the example Maxtor 6Y160P0 USB Device      

are HID Class device name. OK.

What are the values returned in the subkeys of  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PerHwIdStorage ? HID class device related too ?

Thanks



0
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 17995861
I doubt it. It seems at least partly prefilled. I have Iomega entries there and i never connected an Iomega device to my computer.
It is bus related. All entries under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum are called bus (even if they are virtual like USBSTOR).
I have no HID entries there.
0
 

Author Comment

by:JacekH
ID: 18001792
Solved. I splitted points:

1. robert - thanks for your link for API lib and USB View. It gave me the main idea.
2. bernani - thanks for "FriendlyName" key name. I forgot about it.

For now I can read a device name. It's a mixed solution. From API Lib (robert info) I can read USB buses and GUIDs to build a tree like a "Safely remove device" (Windows Tray). This is an idea - I haven't coded it yet. Now I use reading registry to get a device name - just a simple procedure (pasted belowe) without BUS name. Using WMDeviceChange message I read a drive letter (PDevBroadcastVolume). A drive letter is used in my function to get a Device name. Now it's for USB drives only. Thanks to all.

Jacek

Here's my solution:

function ReadFriendlyName(const  ADriveLetter: Char): String;
var
  Reg: TRegistry;
  MountedDevices, USBKeys, USBSubKeys: TStrings;
  Index, HashPos: Integer;
  BuffSize: Integer;
  BinValue: String;
  ParentID: String;
  i, j: Integer;
begin
  Result := '';
  Reg := TRegistry.Create;
  try // 0
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    // Read mounted devices IDs
    if Reg.OpenKeyReadOnly('SYSTEM\MountedDevices') then
    begin // 1
      MountedDevices := TStringList.Create;
      try // 2
        Reg.GetValueNames(MountedDevices);
        Index := MountedDevices.IndexOf('\DosDevices\' + ADriveLetter + ':');
        if Index >= 0 then
        begin //3
          BuffSize := Reg.GetDataSize(MountedDevices.Strings[Index]);
          SetLength(BinValue, BuffSize);
          Reg.ReadBinaryData(MountedDevices.Strings[Index], BinValue[1], BuffSize);
          ParentID := '';
          for i := 1 to Length(BinValue) do
            if BinValue[i] <> #0 then
              ParentID := ParentID + BinValue[i];
          HashPos := Pos('#', ParentID);
          ParentID := Copy(ParentID, HashPos + 1, Length(ParentID) - HashPos);
          HashPos := Pos('#', ParentID);
          ParentID := Copy(ParentID, HashPos + 1, Length(ParentID) - HashPos);
          HashPos := Pos('RM#', ParentID);
          ParentID := Copy(ParentID, 1, HashPos - 2); // final Parent ID Prefix
          Reg.CloseKey;
          // Read USBSTOR Device Keys
          if Reg.OpenKeyReadOnly('SYSTEM\CurrentControlSet\Enum\USBSTOR') then
          begin // 4
            USBKeys := TStringList.Create;
            try // 5
              Reg.GetKeyNames(USBKeys);
              for i := 0 to USBKeys.Count - 1 do
              begin //6
                if Result <> '' then Break;
                Reg.CloseKey;
                // Read Device subkeys (serials)
                if Reg.OpenKeyReadOnly('SYSTEM\CurrentControlSet\Enum\USBSTOR' +
                      '\' + USBKeys[i]) then
                begin // 7
                  USBSubKeys := TStringList.Create;
                  try // 8
                    Reg.GetKeyNames(USBSubKeys);
                    for j := 0 to USBSubKeys.Count - 1 do
                    begin // 9
                      Reg.CloseKey;
                      // Read Device (serial) ParentIDPrefix
                      if Reg.OpenKeyReadOnly('SYSTEM\CurrentControlSet\Enum\USBSTOR' +
                        '\' + USBKeys[i] + '\' + USBSubKeys[j]) then
                      begin // 10
                        if Reg.ReadString('ParentIdPrefix') = ParentID then
                        begin
                          Result := Reg.ReadString('FriendlyName');
                          Break;
                        end;
                      end; // end 10
                    end; // end 9
                  finally // try 8
                    Reg.CloseKey;
                    USBSubKeys.Free;
                  end; // try 8
                end; // end 7
              end; // end 6
            finally // try 5
              USBKeys.Free;
              Reg.CloseKey;
            end; // try 5
          end; // end 4
        end; // end 3
      finally // try 2
        MountedDevices.Free;
        Reg.CloseKey;
      end; // try 2
    end; // end 1
  finally // try 0
     Reg.Free;
  end; // try 0
end;
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question