Newsgroups : Borland : borland.public.delphi.nativeapi.win32 : 2006 Nov : 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)