Board index » cppbuilder » Detecting media insertion/removal

Detecting media insertion/removal


2006-06-28 02:58:05 AM
cppbuilder111
I have an application that reads and writes data to a Compact Flash card via
USB card reader. The cards are not formatted on the PC and do not use FAT
or NTFS. However, I can read/write to them by accessing \\.\PhysicalDrivex
My problem is that the application needs to detect when the user
inserts/removes a CF card. Everything I've read says that a WM_DEVICECHANGE
message is sent when this happens. However, my application only sees this
message when the card reader is inserted/removed - no message appears to be
sent when the actual CF card is inserted into the reader.
Can anyone help?
 
 

Re:Detecting media insertion/removal

Just a thought: Maybe you could store a list of devices that are on the
system, then whenever you receive a WM_DEVICECHANGE message, look to see
what is not already in your list (inserts) or what in your list is no longer
available (removed).
 

Re:Detecting media insertion/removal

"poojo hackma" wrote...
Quote
Just a thought: Maybe you could store a list of devices that are on the
system, then whenever you receive a WM_DEVICECHANGE message, look to see
what is not already in your list (inserts) or what in your list is no
longer available (removed).
Unfortunately that wouldn't work - to give you an example:
Someone plugs a USB card reader into their PC, resulting in 4 new drives
appearing and a whole load of WM_DEVICECHANGE messages arriving at my
application. My application detects the new drives, but because there is no
media inserted in any of the reader slots, doesn't do anything.
Next, a Compact Flash card is inserted into the reader. This is what I need
to detect but I get no messages from Windows :(
At this point my application should be processing what's on the card, but
because it doesn't know a card has been inserted, does nothing...
After processing, the user removes the card. Again I'm hoping to get a
WM_DEVICECHANGE telling me the card has been removed but nothing arrives.
Finally the user removes the card reader from the PC. This does trigger the
message and my application detects the 4 drives disappearing.
My current solution is to put a button on my form saying something like
"Rescan Drives", but it would be nice if it would do it automatically.
MikeW
 

{smallsort}

Re:Detecting media insertion/removal

As far as I know, what you are seeing is normal, the WM_DEVICECHANGE
message is only sent when the hardware device i.e. your reader / writer is
inserted or removed, not the media. This is the behaviour that I have
observed.
It's a dirty hack but you could spawn a thread and use it to attempt a write
operation on a certain device - if it fails then you can assume that the
card is not present, if it successes that it's there and you can read and
write to it. Just a thought.
HTH Mike
"Mike Wynne" < XXXX@XXXXX.COM >wrote in message
Quote

"poojo hackma" wrote...
>Just a thought: Maybe you could store a list of devices that are on the
>system, then whenever you receive a WM_DEVICECHANGE message, look to see
>what is not already in your list (inserts) or what in your list is no
>longer available (removed).
 

Re:Detecting media insertion/removal

"Mike Wynne" < XXXX@XXXXX.COM >wrote in message
Quote
Unfortunately that wouldn't work - to give you an example:
<snip>
Are you calling RegisterDeviceNotification() at all? The OS sends only
basic device notifications by default. You have to manually register for
more advanced events.
Gambit
 

Re:Detecting media insertion/removal

"Remy Lebeau (TeamB)" wrote...
Quote
Are you calling RegisterDeviceNotification() at all? The OS sends only
basic device notifications by default. You have to manually register for
more advanced events.
I think this is at the heart of my problem. I do include a
RegisterDeviceNotification() at initialisation but I'm not 100% sure what I
should be registering for. My code includes:
HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
memset(&NotificationFilter, 0, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = GUID_DEVCLASS_DISKDRIVE;
hDevNotify = RegisterDeviceNotification( Application->Handle,
&NotificationFilter,
DEVICE_NOTIFY_WINDOW_HANDLE);
Though this doesn't make any difference. I can comment it out and still get
exactly the same messages arriving. Maybe I should be registering
DBT_DEVTYP_VOLUME - though since these cards are not FAT or NTFS formatted I
don't know if that would work?
Thanks,
MikeW
 

Re:Detecting media insertion/removal

"Mike Wynne" < XXXX@XXXXX.COM >wrote in message
Quote
Though this doesn't make any difference. I can comment it out
and still get exactly the same messages arriving. Maybe I should
. be registering DBT_DEVTYP_VOLUME - though since these
cards are not FAT or NTFS formatted I don't know if that
would work?
Did you try it yet? You did say that the reader is creating new drive
letters for the media. Drive letters represent volumes, afterall.
Gambit
 

Re:Detecting media insertion/removal

"Remy Lebeau (TeamB)" wrote...
Quote
Did you try it yet? You did say that the reader is creating new drive
letters for the media. Drive letters represent volumes, afterall.
I tried the following initialisation code:
HDEVNOTIFY hDevNotify;
DEV_BROADCAST_VOLUME NotificationFilter;
memset( &NotificationFilter, 0, sizeof(NotificationFilter) );
NotificationFilter.dbcv_size = sizeof(DEV_BROADCAST_VOLUME);
NotificationFilter.dbcv_devicetype = DBT_DEVTYP_VOLUME;
NotificationFilter.dbcv_unitmask=0x0f;
NotificationFilter.dbcv_flags=DBTF_MEDIA;
hDevNotify = RegisterDeviceNotification( Application->Handle,
&NotificationFilter,
DEVICE_NOTIFY_WINDOW_HANDLE);
However the RegisterDeviceNotification() fails with error code 13, which I
believe is "Invalid Data". What am I doing wrong?
Thanks,
MikeW
 

Re:Detecting media insertion/removal

"Mike Wynne" < XXXX@XXXXX.COM >wrote in message
Quote
NotificationFilter.dbcv_unitmask=0x0f;
You said earlier that the reader adds 4 new drive letters to your system.
Assuming that you have a C drive for the hard drive, and maybe D for a
CD/DVD drive, then the reader would be adding drives E-H. But in your
bitmask, you are asking for device events for drives A-D instead. So your
reader drives will never report the requested events. You need to adjust
your bitmask accordingly.
Gambit
 

Re:Detecting media insertion/removal

"Remy Lebeau (TeamB)" wrote...
Quote
You said earlier that the reader adds 4 new drive letters to your system.
Assuming that you have a C drive for the hard drive, and maybe D for a
CD/DVD drive, then the reader would be adding drives E-H. But in your
bitmask, you are asking for device events for drives A-D instead. So your
reader drives will never report the requested events. You need to adjust
your bitmask accordingly.
My original mask was 0xffff to make sure I had every drive covered, but
since the RegisterDeviceNotification() fails with invalid data, I reduced it
to cover drives I absolutely knew existed (Just in case this was the reason
it was failing). It still failed with invalid data...
MikeW
 

Re:Detecting media insertion/removal

OK, I just found this:
groups.google.co.uk/group/microsoft.public.platformsdk.base/browse_frm/thread/a428cb9bd0ecf7a0/204e48bfc5681a05
So it looks like DEV_BROADCAST_VOLUME is a dead end...
MikeW
 

Re:Detecting media insertion/removal

OK, I had another attempt with this code:
#define WM_DEVICE WM_USER+125
LPITEMIDLIST ppidl;
if (SHGetSpecialFolderLocation(Application->Handle , CSIDL_DRIVES, &ppidl)
== NOERROR)
{
SHChangeNotifyEntry shCNE;
shCNE.pidl = ppidl;
shCNE.fRecursive = TRUE;
nID = SHChangeNotifyRegister(Application->Handle,
SHCNRF_InterruptLevel | SHCNRF_ShellLevel,
SHCNE_MEDIAINSERTED |SHCNE_MEDIAREMOVED
| SHCNE_DRIVEREMOVED |SHCNE_DRIVEADD,
WM_DEVICE,
1,
&shCNE);
}
But still, my application doesn't recieve any WM_DEVICE messages on
insert/eject. I get the feeling I'm missing something really obvious...
MikeW
 

Re:Detecting media insertion/removal

Mike Wynne wrote:
Quote
groups.google.co.uk/group/microsoft.public.platformsdk.base/browse_frm/thread/a428cb9bd0ecf7a0/204e48bfc5681a05

So it looks like DEV_BROADCAST_VOLUME is a dead end...
Did you read further down (message 4), where they go on to talk about
CDs?
The last message has several points that sound likely, including....
<paraphrased>
"Under XP, not all media show up as drives, but may be added paths, so
would not get the notifications."
"it's also possible to register for pnp events as a service, and
receive SERVICE_CONTROL_DEVICEEVENT service controls to your
services's HandlerEx routine"
I also wonder if the device driver fails to report the media changes?
 

Re:Detecting media insertion/removal

"Bob Gonder" wrote...
Quote
"it's also possible to register for pnp events as a service, and
receive SERVICE_CONTROL_DEVICEEVENT service controls to your
services's HandlerEx routine"
This is what I'm trying next...
Quote
I also wonder if the device driver fails to report the media changes?
If I format one of the cards to FAT, then remove and reinsert the card,
explorer automatically opens a window to the card. Surely Explorer is
registering for some event or other? (Unless it just polls all connected
drives several times a second)
Thanks for the input,
MikeW