Newsgroups : Borland : borland.public.delphi.nativeapi.win32 : 2006 Nov : Detecting removable media arrival/removal

www.cryer.info
Managed Newsgroup Archive

Detecting removable media arrival/removal

Subject:Detecting removable media arrival/removal
Posted by:"Ricardo Villela Coppola" (coppo..@csp.com.br)
Date:Tue, 7 Nov 2006 10:25:39

Hi folks!

I've been searching the NG for sometime now and found some threads about
detecting removable media arrival and removal but got sticked when the
device is left alone and only the media is removed/inserted. Looking for
this issue in the MSDN I learned that apparently WinXP does not receive
such kind of message. But Windows Explorer reacts to media exchange so I
imagine that there is a way to it. What should I do? Do I need a
kernel-driver in order to "see" this messages? I'm currently using this
code below:

unit FByMessages;

interface

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

type
    PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE;
    DEV_BROADCAST_DEVICEINTERFACE = record
      dbcc_size: DWORD;
      dbcc_devicetype: DWORD;
      dbcc_reserved: DWORD;
      dbcc_classguid: TGUID;
      dbcc_name: short;
    end;

   PDevBroadcastVolume = ^TDevBroadcastVolume;
   {$EXTERNALSYM DEV_BROADCAST_VOLUME}
   DEV_BROADCAST_VOLUME = packed record
     dbcv_size: DWORD;
     dbcv_devicetype: DWORD;
     dbcv_reserved: DWORD;
     dbcv_unitmask: DWORD;
     dbcv_flags: Word;
   end;
   TDevBroadcastVolume = DEV_BROADCAST_VOLUME;

   TWMDeviceChange = record
     Msg:    Cardinal;
     Event:  UINT;
     dwData: Pointer;
     Result: LongInt;
   end;

   TFormMessages = class(TForm)
     MemoMessages: TMemo;
     LabelMessages: TLabel;
   private
     { Private declarations }
     FRegInHnd: HDEVNOTIFY;
     FRegOutHnd: HDEVNOTIFY;
     dbi: PDevBroadcastDeviceInterface;
   protected
     procedure WmDeviceChange(var Message: TWMDeviceChange); message
WM_DEVICECHANGE;
   public
     { Public declarations }
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
   end;

var
   FormMessages: TFormMessages;

implementation

uses
   Math;

{$R *.dfm}

const
   {$EXTERNALSYM DBT_DEVTYP_OEM}
   DBT_DEVTYP_OEM = $00000000;                  { oem-defined device type }
   {$EXTERNALSYM DBT_DEVTYP_DEVNODE}
   DBT_DEVTYP_DEVNODE = $00000001;              { devnode number }
   {$EXTERNALSYM DBT_DEVTYP_VOLUME}
   DBT_DEVTYP_VOLUME = $00000002;               { logical volume }
   {$EXTERNALSYM DBT_DEVTYP_PORT}
   DBT_DEVTYP_PORT = $00000003;                 { serial, parallel }
   {$EXTERNALSYM DBT_DEVTYP_NET}
   DBT_DEVTYP_NET = $00000004;                  { network resource }
   {$EXTERNALSYM DBT_DEVTYP_DEVICEINTERFACE}
   DBT_DEVTYP_DEVICEINTERFACE = $00000005;      { device interface class }
   {$EXTERNALSYM DBT_DEVTYP_HANDLE}
   DBT_DEVTYP_HANDLE = $00000006;               { file system handle }
   {$EXTERNALSYM DBT_DEVNODES_CHANGED}
   DBT_DEVNODES_CHANGED = $0007;
   {$EXTERNALSYM DBT_QUERYCHANGECONFIG}
   DBT_QUERYCHANGECONFIG = $0017;
   {$EXTERNALSYM DBT_CONFIGCHANGED}
   DBT_CONFIGCHANGED = $0018;
   {$EXTERNALSYM DBT_CONFIGCHANGECANCELED}
   DBT_CONFIGCHANGECANCELED = $0019;
   {$EXTERNALSYM DBT_USERDEFINED}
   DBT_USERDEFINED = $FFF;
   {$EXTERNALSYM DBT_DEVICEARRIVAL}
   DBT_DEVICEARRIVAL = $8000;                   { system detected a new
device }
   {$EXTERNALSYM DBT_DEVICEQUERYREMOVE}
   DBT_DEVICEQUERYREMOVE = $8001;               { wants to remove, may
fail }
   {$EXTERNALSYM DBT_DEVICEQUERYREMOVEFAILED}
   DBT_DEVICEQUERYREMOVEFAILED = $8002;         { removal aborted }
   {$EXTERNALSYM DBT_DEVICEREMOVEPENDING}
   DBT_DEVICEREMOVEPENDING = $8003;             { about to remove, still
avail. }
   {$EXTERNALSYM DBT_DEVICEREMOVECOMPLETE}
   DBT_DEVICEREMOVECOMPLETE = $8004;            { device is gone }
   {$EXTERNALSYM DBT_DEVICETYPESPECIFIC}
   DBT_DEVICETYPESPECIFIC = $8005;              { type specific event }
   {$EXTERNALSYM DBT_CUSTOMEVENT}
   DBT_CUSTOMEVENT = $8006;                     { user-defined event }
   GUID_IO_MEDIA_ARRIVAL: TGUID = (D1:$d07433c0; D2:$a98e; D3:$11d2;
D4:($91, $7a, $00, $a0, $c9, $06, $8f, $f3));
   {$EXTERNALSYM GUID_IO_MEDIA_ARRIVAL}
   GUID_IO_MEDIA_REMOVAL: TGUID = (D1:$d07433c1; D2:$a98e; D3:$11d2;
D4:($91, $7a, $00, $a0, $c9, $06, $8f, $f3));
   {$EXTERNALSYM GUID_IO_MEDIA_REMOVAL}

function DbtEventName(Event: DWORD): String;
begin
   case Event of
     DBT_CONFIGCHANGECANCELED   : Result := 'DBT_CONFIGCHANGECANCELED';
     DBT_CONFIGCHANGED          : Result := 'DBT_CONFIGCHANGED';
     DBT_CUSTOMEVENT            : Result := 'DBT_CUSTOMEVENT';
     DBT_DEVICEARRIVAL          : Result := 'DBT_DEVICEARRIVAL';
     DBT_DEVICEQUERYREMOVE      : Result := 'DBT_DEVICEQUERYREMOVE';
     DBT_DEVICEQUERYREMOVEFAILED: Result := 'DBT_DEVICEQUERYREMOVEFAILED';
     DBT_DEVICEREMOVECOMPLETE   : Result := 'DBT_DEVICEREMOVECOMPLETE';
     DBT_DEVICEREMOVEPENDING    : Result := 'DBT_DEVICEREMOVEPENDING';
     DBT_DEVICETYPESPECIFIC     : Result := 'DBT_DEVICETYPESPECIFIC';
     DBT_DEVNODES_CHANGED       : Result := 'DBT_DEVNODES_CHANGED';
     DBT_QUERYCHANGECONFIG      : Result := 'DBT_QUERYCHANGECONFIG';
     DBT_USERDEFINED            : Result := 'DBT_USERDEFINED';
   else
     Result := 'Unknown';
   end; // case Event
end; { DbtEventName }

function DbtDeviceType(Device: DWORD): String;
begin
   case Device of
     DBT_DEVTYP_DEVICEINTERFACE: Result := 'DBT_DEVTYP_DEVICEINTERFACE';
     DBT_DEVTYP_HANDLE         : Result := 'DBT_DEVTYP_HANDLE';
     DBT_DEVTYP_OEM            : Result := 'DBT_DEVTYP_OEM';
     DBT_DEVTYP_PORT           : Result := 'DBT_DEVTYP_PORT';
     DBT_DEVTYP_VOLUME         : Result := 'DBT_DEVTYP_VOLUME';
   else
     Result := 'Unknown';
   end; // case Device
end; { DbtDeviceType }

{ TFormMessages }

constructor TFormMessages.Create(AOwner: TComponent);
begin
   inherited;
   New(dbi);
   ZeroMemory(dbi, SizeOf(dbi^));
   dbi.dbcc_size := SizeOf(dbi^);
   dbi.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
   dbi.dbcc_classguid := GUID_IO_MEDIA_ARRIVAL;
   FRegInHnd := RegisterDeviceNotification(Application.Handle, dbi,
DEVICE_NOTIFY_WINDOW_HANDLE);

   if FRegInHnd = nil then
     ShowMessage(SysErrorMessage(GetLastError));

   dbi.dbcc_classguid := GUID_IO_MEDIA_REMOVAL;
   FRegOutHnd := RegisterDeviceNotification(Application.Handle, dbi,
DEVICE_NOTIFY_WINDOW_HANDLE);

   if FRegOutHnd = nil then
     ShowMessage(SysErrorMessage(GetLastError));
end;

destructor TFormMessages.Destroy;
begin
   UnregisterDeviceNotification(FRegOutHnd);
   UnregisterDeviceNotification(FRegInHnd);
   Dispose(dbi);
   inherited;
end;

procedure TFormMessages.WmDeviceChange(var Message: TWMDeviceChange);
const
   EventText: array[Boolean] of String = (' removido', ' inserido');
begin
   with Message, PDevBroadcastVolume(dwData)^, MemoMessages.Lines do
     case Event of
       DBT_DEVICEARRIVAL,
       DBT_DEVICEREMOVECOMPLETE:
         Add(Chr(Trunc(Log2(dbcv_unitmask * 1.0)) + Ord('A')) + ': ' +
             DbtDeviceType(dbcv_devicetype) +
             EventText[Event = DBT_DEVICEARRIVAL]);
     else
       Add(Format('Event: (%d) %s, Data: %p', [
         Event, DbtEventName(Event), dwData]));
     end; // case Event
end;

end.

==========================================================================

It detects device removal and arrival but not the media.

TIA.

--
Ricardo Villela Coppola (CSP Controle e Automação Ltda)

Replies:

www.cryer.info
Managed Newsgroup Archive