//dbdi is a DEV_BROADCAST_VOLUME
memset(&dbdi, 0, sizeof(dbdi));
dbdi.dbcv_size = sizeof(dbdi);
dbdi.dbcv_devicetype = DBT_DEVTYP_VOLUME;
dbdi.dbcv_unitmask = (1 << 3) | (1 << 5); //get drives D and F for testing
.. these are removable (cdrom and zip) drives on my system
//twiddling this value has not helped ...
dbdi.dbcv_flags = DBTF_MEDIA;
m_hDevNotify = RegisterDeviceNotification(m_hServiceStatus, &dbdi,
DEVICE_NOTIFY_SERVICE_HANDLE);
//always returns zero...
if(!m_hDevNotify)
DWORD dwErr = GetLastError();
dwErr is always 13, ERROR_INVALID_DATA.
Is there anyone on planet Earth who has successfully called this function
from inside a *service* EXE?
Reply-To:sporkme...@hotmail.com
> dbdi.dbcv_devicetype = DBT_DEVTYP_VOLUME;
> m_hDevNotify = RegisterDeviceNotification(m_hServiceStatus, &dbdi,
>DEVICE_NOTIFY_SERVICE_HANDLE);
>
> //always returns zero...
Read the PSK docs on RegisterDeviceNotification():
>The DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events are
>automatically broadcast to all top-level windows ...
>Volume notifications are also broadcast to top-level windows,
>so the function fails if dbch_devicetype is DBT_DEVTYP_VOLUME
Looks like this may be also true for services. Also, I don't think
setting dbcv_unitmask prior to registering will do anything.
Anyway, to receive media arrival/removal notifications in your service,
set dbcv_devicetype to DBT_DEVTYP_DEVICEINTERFACE and set dbcc_classguid
to GUID_DEVINTERFACE_CDROM, probably also register for
GUID_DEVINTERFACE_DISK. See winioctl.h for possible device interface
GUIDs.
Ralf.
for a service to receive any device events at all via its control
handler, the service must register a HandlerEx control handler
using RegisterServiceCtrlHandlerEx:
HandlerEx:
http://msdn.microsoft.com/library/en-us/dllproc/base/handlerex.asp
RegisterServiceCtrlHandlerEx:
http://msdn.microsoft.com/library/en-us/dllproc/base/registerservicectrlhandlerex.asp
to receive volume arrival and removal events, register for
device interface notification using the volume device interface
class GUID.
use a DEV_BROADCAST_DEVICEINTERFACE structure for the
NotificationFilter (dbcc_devicetype must be set to
DBT_DEVTYP_DEVICEINTERFACE), and set the dbcc_classguid field to
GUID_DEVINTERFACE_VOLUME.
on volume arrivals and removals, you service's HandlerEx routine
will receive SERVICE_CONTROL_DEVICEEVENT controls with an EventType
of DBT_DEVICEARRIVAL or DBT_DEVICEREMOVECOMPLETE. check the type
of the accompanying data structure to verify it is the expected
DBT_DEVTYP_DEVICEINTERFACE. the dbcc_name field of the
DEV_BROADCAST_DEVICEINTERFACE strcuture will specify a path that
can be used to access the volume (note that this path is always
supplied as a Unicode string, even for services compiled as ANSI.)
hope this helps,
jim.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Rufus DeDufus" <sporkme...@hotmail.com> wrote in message
news:vh4e62j...@corp.supernews.com...
"Jim Cavalaris [MS]" <jam...@online.microsoft.com> wrote in message
news:3f12f512$1...@news.microsoft.com...
> you cannot register for notification of DBT_DEVTYP_VOLUME events.
> RegisterDeviceNotification will always fail for this type of
> notification filter. DBT_DEVTYP_VOLUME type messages are
> automatically broadcast to top-level windows only, for compatibility
> with Windows 9x systems. they are not sent to NT services.
>
> for a service to receive any device events at all via its control
> handler, the service must register a HandlerEx control handler
> using RegisterServiceCtrlHandlerEx:
>
> HandlerEx:
> http://msdn.microsoft.com/library/en-us/dllproc/base/handlerex.asp
>
> RegisterServiceCtrlHandlerEx:
>
http://msdn.microsoft.com/library/en-us/dllproc/base/registerservicectrlhand
lerex.asp
>
> to receive volume arrival and removal events, register for
> device interface notification using the volume device interface
> class GUID.
>
> use a DEV_BROADCAST_DEVICEINTERFACE structure for the
> NotificationFilter (dbcc_devicetype must be set to
> DBT_DEVTYP_DEVICEINTERFACE), and set the dbcc_classguid field to
> GUID_DEVINTERFACE_VOLUME.
OK, this works by some miracle ( I used GUID_DEVCLASS_CDROM ) but the docs
page for RegisterDeviceNotification(),
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/
dev_broadcast_hdr_str.asp , says :
DBT_DEVTYP_DEVICEINTERFACE : Windows XP/2000 and Windows Me/98: This
value is not supported.
But it returns a valid handle on Win2K?!? This is why I did not try this
sooner.
Now, I cannot get messages when I remove the device. I have called
SetServiceStatus() with dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_HARDWAREPROFILECHANGE which should enable it to get that
message (this is also a little unclear in the docs) but still no message.
I am reduced to guessing if the GUID is right - I have used the GUID for
MEDIA and VOLUME as well as CDROM with the same outcome : nice looking
handle but media change does not get me a message. So, what could it be?
Device name? I have tried "d:", \\?\d:, "d:\" ... and on and on.
Any ideas? You got me one step further, I have a handle now.
Thanks,
Eric
PS Here is the current nonworking code snippet:
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_HARDWAREPROFILECHANGE;
....
m_status.dwCurrentState = SERVICE_START_PENDING;
m_hServiceStatus = RegisterServiceCtrlHandlerEx(m_szServiceName,
_HandlerEx, 0);
if (m_hServiceStatus == NULL)
{
LogEvent(_T("Handler not installed"));
return;
}
//this uses the dwControlsAccepted set earlier, yes ..
SetServiceStatus(SERVICE_START_PENDING);
//just a nice big block of bits, plenty big enuf
memset(&dbdi, 0, sizeof(dbdi));
DEV_BROADCAST_DEVICEINTERFACE * p = (DEV_BROADCAST_DEVICEINTERFACE *)&dbdi;
p->dbcc_size = sizeof(dbdi);
p->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
_tcscpy(p->dbcc_name, _T("d:\\"));
p->dbcc_classguid = GUID_DEVCLASS_VOLUME;
//this returns non-null handle
m_hDevNotify = RegisterDeviceNotification(m_hServiceStatus, p,
DEVICE_NOTIFY_SERVICE_HANDLE);
Eric
"Rufus DeDufus" <sporkme...@hotmail.com> wrote in message
news:vha05u4...@corp.supernews.com...
//dbdi is a DEV_BROADCAST_HANDLE ...
memset(&dbdi, 0, sizeof(dbdi));
dbdi.dbch_size = sizeof(dbdi);
dbdi.dbch_devicetype = DBT_DEVTYP_HANDLE;
dbdi.dbch_handle = CreateFile(_T("\\\\?\\c:"), FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 0);
m_hDevNotify = RegisterDeviceNotification(m_hServiceStatus, &dbdi,
DEVICE_NOTIFY_SERVICE_HANDLE);
Then down in HandlerEx():
DEV_BROADCAST_HANDLE * p = 0;
DebugBreak();
switch (dwOpcode)
{
case SERVICE_CONTROL_DEVICEEVENT:
p = (DEV_BROADCAST_HANDLE *)pvEvtData;
if(p->dbch_devicetype != DBT_DEVTYP_HANDLE)
return NO_ERROR;
if(IsEqualGUID(GUID_IO_MEDIA_REMOVAL, p->dbch_eventguid))
{
//do work ..
return NO_ERROR;
}
It was not in the *least* straightforward, and thanks for your help.
many device interface class GUID definitions were renamed in the
Windows XP DDK and later to use a GUID_DEVINTERFACE_* naming
convention. this was done specifically to avoid confusing these
with device setup classes (which have always had GUID_DEVCLASS_*
names). in previous versions of the DDK, GUID_DEVINTERFACE_CDROM
is defined as CdRomClassGuid.
the following docs should help explain the differences between
device setup classes and device interface classes.
Setup Classes Versus Interface Classes:
http://msdn.microsoft.com/library/en-us/install/hh/install/setup-cls_39wn.asp
Introduction to Device Interfaces:
http://msdn.microsoft.com/library/en-us/install/hh/install/setup-cls_8vs7.asp
hope this helps,
jim.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Rufus DeDufus" <sporkme...@hotmail.com> wrote in message
news:vha05u4...@corp.supernews.com...
> Thanks.
> Comments in the text.
>
i have followed up with the SDK documentation writers to address
this issue.
hope this helps,
jim.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Rufus DeDufus" <sporkme...@hotmail.com> wrote in message
news:vha05u4...@corp.supernews.com...
Eric
"Jim Cavalaris [MS]" <jam...@online.microsoft.com> wrote in message
news:3f1da673$1...@news.microsoft.com...
Jim, I am finding only
DEFINE_GUID(CdRomClassGuid, 0x53f56308L, 0xb6bf, 0x11d0, 0x94,
0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
in that file ... I take it this is what you mean - ?
Does anyone know how I can interrogate for that class GUID given the name of
the device or an open handle to it? For example, if I detect a drive F: on
the system, can I get the class GUID for that device?
Eric
many device interface class GUID definitions were renamed in the
Windows XP DDK and later to use a GUID_DEVINTERFACE_* naming
convention. this was done specifically to avoid confusing these
with device setup classes (which have always had GUID_DEVCLASS_*
names). in previous versions of the DDK, GUID_DEVINTERFACE_CDROM
is defined as CdRomClassGuid.
hope this helps,
jim.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Rufus DeDufus" <sporkme...@hotmail.com> wrote in message
news:vi0mkjc...@corp.supernews.com...
GetVolumeNameForVolumeMountPoint:
http://msdn.microsoft.com/library/en-us/fileio/base/getvolumenameforvolumemountpoint.asp
if you append a trailing path separator character ('\') to the
device interface path, you can pass it to
GetVolumeNameForVolumeMountPoint to retrieve the unique name for
that volume (in the form \\?\Volume{GUID}\).
you can then retrieve all existing drive letter mountpoints in the
system (GetLogicalDrives or GetLogicalDriveStrings may help here)
and use GetVolumeNameForVolumeMountPoint to find their unique volume
names as well.
GetLogicalDrives:
http://msdn.microsoft.com/library/en-us/fileio/base/getlogicaldrives.asp
GetLogicalDriveStrings:
http://msdn.microsoft.com/library/en-us/fileio/base/getlogicaldrivestrings.asp
compare the volume names of the drive letters with the volume name
corresponding to that device interface path, until you find one that
matches.
note that a volume (includes CD-ROM devices) may not necessarily be
mounted at any drive letter moint point at all, so you may not find
a match. to determine the non-drive letter mount points for a volume
see:
FindFirstVolumeMountPoint:
http://msdn.microsoft.com/library/en-us/fileio/base/findfirstvolumemountpoint.asp
Enumerating Mount Points:
http://msdn.microsoft.com/library/en-us/fileio/base/enumerating_mount_points.asp
hope this helps,
jim.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Rufus DeDufus" <sporkme...@hotmail.com> wrote in message
news:vi0n96r...@corp.supernews.com...
I am still unable to get this to work. Now I get a valid handle from
RegisterDeviceNotification() but no events are sent.
m_hServiceStatus = RegisterServiceCtrlHandlerEx(m_szServiceName, _HandlerEx,
0);
//good status handle here ..
//dbdi_buf is just a slab of bits big enuf for our work ...
memset(&dbdi_buf, 0, sizeof(dbdi_buf));
pdbdi = (DEV_BROADCAST_DEVICEINTERFACE*)&dbdi_buf;
pdbdi->dbcc_size = sizeof(dbdi_buf);
pdbdi->dbcc_classguid = GUID_DEVINTERFACE_CDROM;
pdbdi->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
//got a nice service handle going in ...
m_hDevNotify = RegisterDeviceNotification(m_hServiceStatus, pdbdi,
DEVICE_NOTIFY_SERVICE_HANDLE);
//...notify handle is good here ...
HandlerEx() has a switch for SERVICE_CONTROL_DEVICEEVENT. It is not hit when
I pop media in and out ..
I had let this go because I was getting some results on DBT_DEVTYP_HANDLE,
passing in a handle I had gotten from CreateFile(). This seemed to work - I
was getting messages for a CDROM - but I dropped it when I started getting
squirrely results on a ZIP drive. When I ejected a disk, I got a
GUID_IO_MEDIA_ARRIVAL (not REMOVAL), and when I stuffed a disk in, I got
nothing at all. So I ditched it ... got any more ideas?
Eric
PS. Does it care about service status when RegisterDeviceNotification() is
called? Mine is SERVICE_START_PENDING.
"Jim Cavalaris [MS]" <jam...@online.microsoft.com> wrote in message
news:3f1d980c$1...@news.microsoft.com...
> ... When I ejected a disk, I got a
> GUID_IO_MEDIA_ARRIVAL (not REMOVAL), and when I stuffed a disk in, I got
> nothing at all. So I ditched it ... got any more ideas?
Eh, should be MOUNT_VOLUME not MEDIA_ARRIVAL. And I got it when I EJECTED a
disk. Insertion of a disk got me nothing at all.
open a handle to the cd-rom device (using the cd-rom device interface)
and register for target device change notification using
RegisterDeviceNotification with a DEV_BROADCAST_HANDLE structure as
the NotificationFilter (DBT_DEVTYP_HANDLE).
once registered for target device change notifications, you should be
able to receive DBT_CUSTOMEVENT events (in addition to others such as
DBT_DEVICEQUERYREMOVE when the cd-rom device is being removed, etc.).
the data associated with DBT_CUSTOMEVENT events is a DEV_BROADCAST_HANDLE
structure, the dbch_eventguid member is valid and specifies a GUID
representing the custom event. for media arrival / removal notifications,
the dbch_eventguid member of this structure will specify
GUID_IO_MEDIA_ARRIVAL / GUID_IO_MEDIA_REMOVAL.
you were on the right track using the DBT_DEVTYP_HANDLE notifications
to receive the GUID_IO_MEDIA_ARRIVAL/REMOVAL notifications. not sure
why this wasn't working for the zip disk, but this should work for
cd-rom devices.
RegisterDeviceNotification does not currently check the status of the
calling service, so it will not fail, but i would recommend that you
wait until your service is fully started to register. if device events
occur after you have registered, but before your service is started, i
don't know that the SCM is guaranteed deliver those to you anyways.
hope this helps,
jim.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Rufus DeDufus" <sporkme...@hotmail.com> wrote in message
news:vi1k5qi...@corp.supernews.com...
Now, any idea how I can track attach/detach of network drives?
Can I trap "net use * \\computer\share" or "net use x: /del" ?
Thanks again BTW.
Eric
"Jim Cavalaris [MS]" <jam...@online.microsoft.com> wrote in message
news:3f216ec0$1...@news.microsoft.com...
> the cd-rom device interface corresponds to the cd-rom device itself,
> and is always enabled whether there is media present or not. to get
> media arrival/removal notifications, you need to register for target
> device notification [....]
you'll need to track this from a process that is running
as the user that creates the network drive letter mapping.
i believe that top-level windows created by a process running
under the same logon session as the user that creates the drive
letter mapping should receive WM_DEVICECHANGE DBT_DEVICEARRIVAL
and DBT_DEVICEREMOVECOMPLETE messages containing a
DEV_BROADCAST_VOLUME structure (DBT_DEVTYP_VOLUME) with the
DBTF_NET flag set in the dbcv_flags field (see dbt.h).
DBT_DEVTYP_VOLUME type WM_DEVICECHANGE messages are automatically
broadcast to top-level windows. you do not register for these
messages.
hope this helps,
jim.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Rufus DeDufus" <sporkme...@hotmail.com> wrote in message
news:vi2s80d...@corp.supernews.com...