unit mr.drv.usb.notifier; interface uses System.Classes, Winapi.Windows, Winapi.Messages, mr.drv.usb; const DBT_DEVTYP_DEVICEINTERFACE = $00000005; // device interface class DBT_DEVICEARRIVAL = $8000; // system detected a new device DBT_DEVICEQUERYREMOVE = $8001; DBT_DEVICEQUERYREMOVEFAILED= $8002; DBT_DEVICEREMOVEPENDING = $8003; DBT_DEVICEREMOVECOMPLETE = $8004; // device is gone DBT_DEVICETYPESPECIFIC = $8005; type TusbNotifyEvent = procedure( APath: string; ADriverClass: TUsbDriverClass) of object; PDevBroadcastHdr = ^DEV_BROADCAST_HDR; DEV_BROADCAST_HDR = packed record dbch_size : DWORD; dbch_devicetype: DWORD; dbch_reserved : DWORD; end; PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE; DEV_BROADCAST_DEVICEINTERFACE = record dbcc_size : DWORD; dbcc_devicetype: DWORD; dbcc_reserved : DWORD; dbcc_classguid : TGUID; dbcc_name : char; end; type TusbNotifier = class private fDeviceInterface : string; fDriverClass : TUsbDriverClass; fNotifyHandle : HDEVNOTIFY; FWindowHandle : HWND; FOnUSBArrival : TusbNotifyEvent; FOnUSBRemove : TusbNotifyEvent; procedure WndProc(var Msg: TMessage); function USBRegister: Boolean; protected procedure WMDeviceChange(var Msg: TMessage); dynamic; public constructor Create( ADeviceInterface: string; ADriverClass: TUsbDriverClass); destructor Destroy; override; public property OnUSBArrival : TusbNotifyEvent read FOnUSBArrival write FOnUSBArrival; property OnUSBRemove : TusbNotifyEvent read FOnUSBRemove write FOnUSBRemove; property DeviceInterface: string read fDeviceInterface; end; implementation uses Vcl.Forms, System.SysUtils; { TusbNotifier } // ================================================================================================ // constructor // // '{CDDE880F-898A-4DAB-B0EA-51FBA32C1D82}' [trinity.inf] // ================================================================================================ constructor TusbNotifier.Create( ADeviceInterface: string; ADriverClass: TUsbDriverClass); begin inherited Create; fDeviceInterface := ADeviceInterface; fDriverClass := ADriverClass; fWindowHandle := AllocateHWnd(WndProc); UsbRegister end; // ================================================================================================ // destructor // ================================================================================================ destructor TusbNotifier.Destroy; begin if fNotifyHandle <> nil then UnregisterDeviceNotification( fNotifyHandle); DeallocateHWnd( fWindowHandle); inherited end; // ================================================================================================ // UsbRegister // ================================================================================================ function TusbNotifier.USBRegister: Boolean; var dbi : DEV_BROADCAST_DEVICEINTERFACE; size : Integer; begin size := SizeOf(DEV_BROADCAST_DEVICEINTERFACE); ZeroMemory(@dbi, Size); dbi.dbcc_size := Size; dbi.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE; dbi.dbcc_classguid := StringToGUID( fDeviceInterface); dbi.dbcc_reserved := 0; dbi.dbcc_name := #0; fNotifyHandle := RegisterDeviceNotification( fWindowHandle, @dbi, DEVICE_NOTIFY_WINDOW_HANDLE); result := fNotifyHandle <> nil end; // ================================================================================================ // WndProc // ================================================================================================ procedure TusbNotifier.WndProc(var Msg: TMessage); begin if Msg.Msg = WM_DEVICECHANGE then begin try WMDeviceChange(Msg) except Application.HandleException(Self) end end else Msg.Result := DefWindowProc( fWindowHandle, Msg.Msg, Msg.wParam, Msg.lParam) end; // ================================================================================================ // WM Device Change // ================================================================================================ procedure TusbNotifier.WMDeviceChange(var Msg: TMessage); var devType : Integer; devHdr : PDevBroadcastHdr; begin if (Msg.wParam = DBT_DEVICEARRIVAL) or (Msg.wParam = DBT_DEVICEREMOVECOMPLETE) then begin devHdr := PDevBroadcastHdr( Msg.lParam); devType := devHdr^.dbch_devicetype; if devType = DBT_DEVTYP_DEVICEINTERFACE then begin // USB Device var x := PDevBroadcastDeviceInterface( Msg.LParam); var p := PChar( @x.dbcc_name); var s := ''; while p^ <> #0 do begin s := s + p^; INC(p) end; if Msg.wParam = DBT_DEVICEARRIVAL then begin if Assigned( fOnUSBArrival) then FOnUSBArrival( s, fDriverClass) end else begin if Assigned( fOnUSBRemove) then FOnUSBRemove( s, fDriverClass) end end end end; end.