From: T.Masuda on
I want to know how to get flash media insertion/removal events in user mode
applications. I tried to get WM_DEVICECHANGE message, but I couldn't get any
events when I inserted/removed flash medias.
Does anyone know about that ? Any information will be welcome.

Thanks in advance.

Takashi Masuda
From: Uwe Sieber on
T.Masuda wrote:
> I want to know how to get flash media insertion/removal events in user mode
> applications. I tried to get WM_DEVICECHANGE message, but I couldn't get any
> events when I inserted/removed flash medias.
> Does anyone know about that ? Any information will be welcome.

You have to register for GUID_IO_MEDIA_ARRIVAL and GUID_IO_MEDIA_REMOVAL
for each drive to get these events for. It's a bit tricky...


HANDLE hDiskDevice = CreateFile(szDevPath, 0, FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

DEV_BROADCAST_HANDLE dbh = {0};

dbh.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
dbh.dbch_handle = Medias[i].hDiskDevice;
dbh.dbch_devicetype = DBT_DEVTYP_HANDLE;

memcpy( &(dbh.dbch_eventguid), &(GUID_IO_MEDIA_ARRIVAL),
sizeof(struct _GUID));
hNotifyRemoval = RegisterDeviceNotification(
hMessageWindow, &dbh,
DEVICE_NOTIFY_WINDOW_HANDLE);

Same thing for GUID_IO_MEDIA_REMOVAL.

szDevPath is the device path the the disk to watch, something like
this (without trailing backslash!):
\\?\usbstor#disk&ven_multi&prod_flash_reader&rev_1.00#058f0o1111a&0#{GUID}

You can get it by means of a SetupDi-Enumeration. I've shown this here:
http://www.codeproject.com/useritems/RemoveDriveByLetter.asp

The handle to the disks must stay open. For removable drives as
USB drives are, this of course prevents the preparation for save
removal. Therefore it must be closed when this is requested by
DBT_DEVICEQUERYREMOVE. If the removal fails you get an
DBT_DEVICEQUERYREMOVEFAILED and you can reopen the handle. The
handle is the same as before by some Windows magic, so there is
no need to register again.

You should also register for GUID_DEVINTERFACE_DISK in case the
drive is removed by surprise, so you can unregister and close
the handle.


You get more WM_DEVICECHANGE messages then:

switch ( wParam ) {
case DBT_CUSTOMEVENT: {
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*)lParam;
if ( dbh->dbch_devicetype == DBT_DEVTYP_HANDLE ) {
DEV_BROADCAST_HANDLE* dbhnd =
(DEV_BROADCAST_HANDLE*)lParam;
if ( IsEqualGUID(GUID_IO_MEDIA_ARRIVAL,
dbhnd->dbch_eventguid ) ) {
// media arrived
}
if ( IsEqualGUID(GUID_IO_MEDIA_REVMOVAL,
dbhnd->dbch_eventguid ) ) {
// media removed
}
}
}
case DBT_DEVICEREMOVECOMPLETE: {
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*)lParam;
if ( dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE ) {
DEV_BROADCAST_DEVICEINTERFACE* dbi =
(DEV_BROADCAST_DEVICEINTERFACE*)lParam;
if ( IsEqualGUID(GUID_DEVINTERFACE_DISK,
dbi->dbcc_classguid) ) {
// disk removed, devpath found in dbi->dbcc_name
}
}
}
}


Greetings from Germany

Uwe



From: T.Masuda on
Thanks a lot. Your advice is very helpful.

Takashi Masuda

"Uwe Sieber" wrote:

> T.Masuda wrote:
> > I want to know how to get flash media insertion/removal events in user mode
> > applications. I tried to get WM_DEVICECHANGE message, but I couldn't get any
> > events when I inserted/removed flash medias.
> > Does anyone know about that ? Any information will be welcome.
>
> You have to register for GUID_IO_MEDIA_ARRIVAL and GUID_IO_MEDIA_REMOVAL
> for each drive to get these events for. It's a bit tricky...
>
>
> HANDLE hDiskDevice = CreateFile(szDevPath, 0, FILE_SHARE_READ |
> FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
>
> DEV_BROADCAST_HANDLE dbh = {0};
>
> dbh.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
> dbh.dbch_handle = Medias[i].hDiskDevice;
> dbh.dbch_devicetype = DBT_DEVTYP_HANDLE;
>
> memcpy( &(dbh.dbch_eventguid), &(GUID_IO_MEDIA_ARRIVAL),
> sizeof(struct _GUID));
> hNotifyRemoval = RegisterDeviceNotification(
> hMessageWindow, &dbh,
> DEVICE_NOTIFY_WINDOW_HANDLE);
>
> Same thing for GUID_IO_MEDIA_REMOVAL.
>
> szDevPath is the device path the the disk to watch, something like
> this (without trailing backslash!):
> \\?\usbstor#disk&ven_multi&prod_flash_reader&rev_1.00#058f0o1111a&0#{GUID}
>
> You can get it by means of a SetupDi-Enumeration. I've shown this here:
> http://www.codeproject.com/useritems/RemoveDriveByLetter.asp
>
> The handle to the disks must stay open. For removable drives as
> USB drives are, this of course prevents the preparation for save
> removal. Therefore it must be closed when this is requested by
> DBT_DEVICEQUERYREMOVE. If the removal fails you get an
> DBT_DEVICEQUERYREMOVEFAILED and you can reopen the handle. The
> handle is the same as before by some Windows magic, so there is
> no need to register again.
>
> You should also register for GUID_DEVINTERFACE_DISK in case the
> drive is removed by surprise, so you can unregister and close
> the handle.
>
>
> You get more WM_DEVICECHANGE messages then:
>
> switch ( wParam ) {
> case DBT_CUSTOMEVENT: {
> DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*)lParam;
> if ( dbh->dbch_devicetype == DBT_DEVTYP_HANDLE ) {
> DEV_BROADCAST_HANDLE* dbhnd =
> (DEV_BROADCAST_HANDLE*)lParam;
> if ( IsEqualGUID(GUID_IO_MEDIA_ARRIVAL,
> dbhnd->dbch_eventguid ) ) {
> // media arrived
> }
> if ( IsEqualGUID(GUID_IO_MEDIA_REVMOVAL,
> dbhnd->dbch_eventguid ) ) {
> // media removed
> }
> }
> }
> case DBT_DEVICEREMOVECOMPLETE: {
> DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*)lParam;
> if ( dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE ) {
> DEV_BROADCAST_DEVICEINTERFACE* dbi =
> (DEV_BROADCAST_DEVICEINTERFACE*)lParam;
> if ( IsEqualGUID(GUID_DEVINTERFACE_DISK,
> dbi->dbcc_classguid) ) {
> // disk removed, devpath found in dbi->dbcc_name
> }
> }
> }
> }
>
>
> Greetings from Germany
>
> Uwe
>
>
>
>
From: Uwe Sieber on

Instead of the device path a physical drive string might work
too, like this:
'\\.\PHYSICALDRIVE2'

The number you get by IOCTL_STORAGE_GET_DEVICE_NUMBER for the
storage volume opened with '\\.\X:'.

I've not tried this but I expect that it works too.


Uwe




T.Masuda wrote:
> Thanks a lot. Your advice is very helpful.
>
> Takashi Masuda
>
> "Uwe Sieber" wrote:
>
>> T.Masuda wrote:
>>> I want to know how to get flash media insertion/removal events in user mode
>>> applications. I tried to get WM_DEVICECHANGE message, but I couldn't get any
>>> events when I inserted/removed flash medias.
>>> Does anyone know about that ? Any information will be welcome.
>> You have to register for GUID_IO_MEDIA_ARRIVAL and GUID_IO_MEDIA_REMOVAL
>> for each drive to get these events for. It's a bit tricky...
>>
>>
>> HANDLE hDiskDevice = CreateFile(szDevPath, 0, FILE_SHARE_READ |
>> FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
>>
>> DEV_BROADCAST_HANDLE dbh = {0};
>>
>> dbh.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
>> dbh.dbch_handle = Medias[i].hDiskDevice;
>> dbh.dbch_devicetype = DBT_DEVTYP_HANDLE;
>>
>> memcpy( &(dbh.dbch_eventguid), &(GUID_IO_MEDIA_ARRIVAL),
>> sizeof(struct _GUID));
>> hNotifyRemoval = RegisterDeviceNotification(
>> hMessageWindow, &dbh,
>> DEVICE_NOTIFY_WINDOW_HANDLE);
>>
>> Same thing for GUID_IO_MEDIA_REMOVAL.
>>
>> szDevPath is the device path the the disk to watch, something like
>> this (without trailing backslash!):
>> \\?\usbstor#disk&ven_multi&prod_flash_reader&rev_1.00#058f0o1111a&0#{GUID}
>>
>> You can get it by means of a SetupDi-Enumeration. I've shown this here:
>> http://www.codeproject.com/useritems/RemoveDriveByLetter.asp
>>
>> The handle to the disks must stay open. For removable drives as
>> USB drives are, this of course prevents the preparation for save
>> removal. Therefore it must be closed when this is requested by
>> DBT_DEVICEQUERYREMOVE. If the removal fails you get an
>> DBT_DEVICEQUERYREMOVEFAILED and you can reopen the handle. The
>> handle is the same as before by some Windows magic, so there is
>> no need to register again.
>>
>> You should also register for GUID_DEVINTERFACE_DISK in case the
>> drive is removed by surprise, so you can unregister and close
>> the handle.
>>
>>
>> You get more WM_DEVICECHANGE messages then:
>>
>> switch ( wParam ) {
>> case DBT_CUSTOMEVENT: {
>> DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*)lParam;
>> if ( dbh->dbch_devicetype == DBT_DEVTYP_HANDLE ) {
>> DEV_BROADCAST_HANDLE* dbhnd =
>> (DEV_BROADCAST_HANDLE*)lParam;
>> if ( IsEqualGUID(GUID_IO_MEDIA_ARRIVAL,
>> dbhnd->dbch_eventguid ) ) {
>> // media arrived
>> }
>> if ( IsEqualGUID(GUID_IO_MEDIA_REVMOVAL,
>> dbhnd->dbch_eventguid ) ) {
>> // media removed
>> }
>> }
>> }
>> case DBT_DEVICEREMOVECOMPLETE: {
>> DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*)lParam;
>> if ( dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE ) {
>> DEV_BROADCAST_DEVICEINTERFACE* dbi =
>> (DEV_BROADCAST_DEVICEINTERFACE*)lParam;
>> if ( IsEqualGUID(GUID_DEVINTERFACE_DISK,
>> dbi->dbcc_classguid) ) {
>> // disk removed, devpath found in dbi->dbcc_name
>> }
>> }
>> }
>> }
>>
>>
>> Greetings from Germany
>>
>> Uwe
>>
>>
>>
>>