Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

RegisterDeviceNotification() from within a service

1,320 views
Skip to first unread message

Rufus DeDufus

unread,
Jul 14, 2003, 12:54:06 AM7/14/03
to
I have been trying and failing to use RegisterDeviceNotification() from
within a service on Win2K. I am calling it as prescribed to connect to
removable media:

//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


Ralf Buschmann

unread,
Jul 14, 2003, 1:52:22 PM7/14/03
to
On Sun, 13 Jul 2003 21:54:06 -0700, "Rufus DeDufus"
<sporkme...@hotmail.com> wrote:

> 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.

Jim Cavalaris [MS]

unread,
Jul 14, 2003, 2:23:14 PM7/14/03
to
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/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...

Rufus DeDufus

unread,
Jul 16, 2003, 3:31:53 AM7/16/03
to
Thanks.
Comments in the text.


"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);

Rufus DeDufus

unread,
Jul 16, 2003, 3:47:43 AM7/16/03
to
By the way, how do I get a device class interface GUID starting with, say
"d:" ?

Eric


"Rufus DeDufus" <sporkme...@hotmail.com> wrote in message

news:vha05u4...@corp.supernews.com...

Rufus DeDufus

unread,
Jul 17, 2003, 3:26:05 AM7/17/03
to
For the sake of the search engines and others who need the answer, here it
is ... no error checking ...

//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.


Jim Cavalaris [MS]

unread,
Jul 22, 2003, 4:01:16 PM7/22/03
to
GUID_DEVCLASS_CDROM is the GUID representing the device setup class
for CD-ROM devices, not the device interface class. the device
interface class GUID that is registered for CD-ROM devices is
GUID_DEVINTERFACE_CDROM, which should be defined in winioctl.h.
this is the GUID you should use with RegisterDeviceNotification
to register for DBT_DEVTYP_DEVICEINTERFACE arrival and removal
events for CD-ROM devices. you do not need to specify any special
SERVICE_ACCEPT_* flags to receive device events, just make sure
you have registered a HandlerEx type handler, as i mentioned
previously. also, do not copy any string in the dbcc_name field; this
field is only used when you receive a notification event, to describe
the device interface that the event is for.

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.
>

Jim Cavalaris [MS]

unread,
Jul 22, 2003, 5:02:42 PM7/22/03
to
the MSDN documentaion for DEV_BROADCAST_HDR is currently incorrect.
the DBT_DEVTYP_DEVICEINTERFACE and DBT_DEVTYP_HANDLE values
_are_ supported for Windows XP/2000 and later, and Windows 98/Me
(they are not supported for Windows 95).

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...

Rufus DeDufus

unread,
Jul 23, 2003, 3:32:36 AM7/23/03
to
Thanks, twice.

Eric

"Jim Cavalaris [MS]" <jam...@online.microsoft.com> wrote in message

news:3f1da673$1...@news.microsoft.com...

Rufus DeDufus

unread,
Jul 24, 2003, 6:10:01 PM7/24/03
to

"Jim Cavalaris [MS]" <jam...@online.microsoft.com> wrote in message
news:3f1d980c$1...@news.microsoft.com...

> GUID_DEVCLASS_CDROM is the GUID representing the device setup class
> for CD-ROM devices, not the device interface class. the device
> interface class GUID that is registered for CD-ROM devices is
> GUID_DEVINTERFACE_CDROM, which should be defined in winioctl.h.
> this is the GUID you should use with RegisterDeviceNotification
> to register for DBT_DEVTYP_DEVICEINTERFACE arrival and removal
> events for CD-ROM devices. [ .....]

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 - ?

Rufus DeDufus

unread,
Jul 24, 2003, 6:20:59 PM7/24/03
to

"Jim Cavalaris [MS]" <jam...@online.microsoft.com> wrote in message
news:3f1d980c$1...@news.microsoft.com...

> GUID_DEVCLASS_CDROM is the GUID representing the device setup class
> for CD-ROM devices, not the device interface class. the device
> interface class GUID that is registered for CD-ROM devices is
> GUID_DEVINTERFACE_CDROM, which should be defined in winioctl.h.
> this is the GUID you should use with RegisterDeviceNotification
> to register for DBT_DEVTYP_DEVICEINTERFACE arrival and removal
> events for CD-ROM devices.

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


Jim Cavalaris [MS]

unread,
Jul 24, 2003, 6:38:04 PM7/24/03
to
yes, that's it.

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...

Jim Cavalaris [MS]

unread,
Jul 24, 2003, 7:47:12 PM7/24/03
to
one way is to match the volume name for the volume represented by
the device interface path to the volume name of all drive letter
mount points in the system using GetVolumeNameForVolumeMountPoint API.

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...

Rufus DeDufus

unread,
Jul 25, 2003, 2:34:03 AM7/25/03
to
He's baaaaack ..... :-o

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...

Rufus DeDufus

unread,
Jul 25, 2003, 3:42:51 AM7/25/03
to

"Rufus DeDufus" <sporkme...@hotmail.com> wrote in message
news:vi1k5qi...@corp.supernews.com...

> He's baaaaack ..... :-o

> ... 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.


Jim Cavalaris [MS]

unread,
Jul 25, 2003, 1:51:44 PM7/25/03
to
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 (DBT_DEVTYP_HANDLE) separately on any such device
that you need to receive custom events for.

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...

Rufus DeDufus

unread,
Jul 25, 2003, 1:57:58 PM7/25/03
to
Thanks.

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 [....]


Jim Cavalaris [MS]

unread,
Jul 25, 2003, 2:30:42 PM7/25/03
to
network drive mappings are not devices, so PnP
(RegisterDeviceNotification) knows nothing about them.
also, on Windows XP and later, network drive mappings only
exist relative to a particular logon session, so they would
not exist for any service (even services running under user
accounts have a separate logon sessions from any interactive
user logged on with the same user account).

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...

0 new messages