Device Interface Notifications

Device interface notification is the mechanism used to alert applications, services, and device drivers to the appearance and disappearance of device interfaces. It is the Microsoft® Windows® CE equivalent to the Plug and Play event system on Windows-based desktop platforms.

AdvertiseInterface tells the device manager to notify all interested parties of the availability or the removal of a device interface. It does not load or unload any drivers. Drivers that use AdvertiseInterface should also advertise when the interface goes away.

There are different ways that you can advertise a device interface to interested applications or drivers. The following list shows the ways you can advertise a device interface:

  • You can define the interface in the IClass value of the registry key used to activate the device.
  • You can define the IClass value in the Active key by a device driver's Init function.
  • You can define the IClass value in the REGINI parameter to ActivateDeviceEx. This amounts to something other than the driver in question making statements concerning that driver's ability to conform to some interface; it also requires knowing in advance the instance information for the driver that is about to be loaded.
  • Your device can explicitly call AdvertiseInterface for the interfaces that it supports.

All of the above variants cause the Device Manager APIs to send notifications for all of the driver's defined interfaces after the driver is loaded and initialized, and then again after the driver is unloaded.

Use RequestDeviceNotifications and StopDeviceNotifications to register and deregister for device interface notifications. When you are not interested in receiving notifications, call StopDeviceNotifications, and then close the message queue with CloseMsgQueue.

Message queues are operating system (OS) objects that are useful for device notifications. They implement FIFO queues in shared memory space. An open handle to a message queue can be waited on with WaitForSingleObject or WaitForMultipleObjects. Aside from the WaitForSingleObject and WaitForMultipleObject calls, you must manipulate message queues only by the message queue functions. For example, you cannot call CloseHandle on a message queue handle. The following table shows the message queue functions.

Function Description
CloseMsgQueue Closes a currently open message queue.
CreateMsgQueue Creates or opens a user-defined message queue.
GetMsgQueueInfo Returns information about a message queue.
OpenMsgQueue Opens a handle to an existing message queue based on a message queue handle.
ReadMsgQueue Reads a single message from a message queue.
WriteMsgQueue Writes a single message to a message queue.

The following code example shows a simple use of CreateMsgQueue, RequestDeviceNotifications, WaitForSingleObject, and StopDeviceNotifications.

#include <windows.h>
#include <msgqueue.h>

#include <pnp.h>

typedef union {
  DEVDETAIL d;
  char pad[sizeof(DEVDETAIL)+MAX_DEVCLASS_NAMELEN];
} MYDEV;

void EnumerateDevices (HANDLE h)
{
  MYDEV detail;
  DWORD flags;
  DWORD size;

  SetLastError(0);

  while (ReadMsgQueue(h, &detail, sizeof(detail), &size, 1, &flags) == TRUE)
    printf("Device notification: %S %s, f=0x%x\n", detail.d.szName, detail.d.fAttached ? "appeared" : "was removed", flags);

  printf("Leaving Enumerate, error = %d\n", GetLastError());
}

main ()
{
  GUID guid = {0};    // or any known and relevant device interface GUID
  HANDLE hq, hn;
  MSGQUEUEOPTIONS msgopts;

  msgopts.dwFlags = MSGQUEUE_VARIABLESIZE | MSGQUEUE_MSGSIZE;
  msgopts.dwMaxMessages = 0; //?
  msgopts.cbMaxMessage = sizeof(MYDEV);
  msgopts.cbMaxMsgQueue = 0; //?
  msgopts.dwDesiredAccess = GENERIC_READ;
  msgopts.dwShareMode = 0;
  msgopts.dwCreationDisposition = CREATE_NEW;
  hq = CreateMsgQueue(NULL, &msgopts);

  printf("Created message queue, h = %08X\n", hq);
  if (hq == 0) return 0;

  hn = RequestDeviceNotifications(&guid, hq, TRUE);

  printf("Registered for notifications, h = %08X\n", hn);

  EnumerateDevices(hq);

  printf("Completed initial notification pass.\n");

  // do whatever
  while (WaitForSingleObject(hq, 80000) == WAIT_OBJECT_0)
    EnumerateDevices(hq);

  printf("Commencing final enumeration\n");
  EnumerateDevices(hq);
  printf("Done.\n");

  StopDeviceNotifications(hn);
  CloseMsgQueue(hq);

  return 0;
}

See Also

Driver Loading Model | Registry Enumerator | Device Interface Classes

 Last updated on Tuesday, May 18, 2004

© 1992-2003 Microsoft Corporation. All rights reserved.