[Compuware Corporation] [Compuware NuMega home page]                [NuMega Lab]
[teal]

 [DriverStudio]    [Image][Image]
   Home                       [Image]
 [Driver Products]                          Using WDM Callback Objects
   DriverStudio          Suppose you have a kernel mode driver that wants to provide notification
   DriverBundle          of an event to other drivers, but the driver has no way of knowing which
   Previews              other drivers in the system might be interested in being notified. In
   Compatibility         other words, the driver would like to broadcast a message to whichever
 [Downloads]             drivers are ready to receive it. For example, suppose a driver wants to
 Wizards                  inform related drivers that it has modified some registry setting, but
   Utilities             the driver doesn't know which of those related drivers are currently
   NT source             running.
 examples
   VxD source            WDM provides a little known mechanism for implementing exactly this kind
 examples                 of communication between drivers. The mechanism uses a system entity
   WDM source            somewhat ambiguously named a callback object. A callback object is
 examples                 essentially a named object associated with a list of function addresses.
 [Resources]             A driver can notify the callback, which causes the system to call each of
                          the functions on the callback's function list. Other drivers can add or
 Technical papers         remove function addresses from the callback's function list.
   Useful links
   Technical tips        To create a callback object, a driver calls ExCreateCallback:
 [Support]  
 Support
   Knowledge base        NTSTATUS
   Problem               ExCreateCallback(
 submission                       OUT PCALLBACK_OBJECT *CallbackObject,
   Product                       IN POBJECT_ATTRIBUTES ObjectAttributes,
 registration                     IN BOOLEAN Create,
   Release notes                 IN BOOLEAN AllowMultipleCallbacks
 [Shop NuMega]                   );
 Buy it!
   Price list            The system uses the name in the object attributes structure to create a
   How to buy            named callback object. There is a branch of the object directory named
   Sales offices         "Callback," and this is where callback objects are normally created. The
                          calling driver must specify the full object path when initializing the
                          object attributes. A successful call to ExCreateCallback sets
 [Y2K Compliance]         *CallbackObject to a pointer to a system callback object that the driver
                          can later use to notify the callback.

 [More information]       This same service is used by other drivers that want to be called when
                          the object is notified. Such drivers set parameter Create to FALSE.

                          To register a function to be called when the callback is notified, a
                          driver calls ExRegisterCallback, whose prototype is as follows:

                          PVOID
                          ExRegisterCallback(
                                  IN PCALLBACK_OBJECT CallbackObject,
                                  IN PCALLBACK_FUNCTION CallbackFunction,
                                  IN PVOID CallbackContext
                                  );

                          For this call, CallbackObject is the object pointer obtained from an
                          earlier call to ExCreateCallback, and CallbackFunction is the address of
                          the function to be called when the callback is notified. The callback
                          function must have the following prototype:

                          VOID CallbackFunction (
                                  IN PVOID CallbackContext,
                                  IN PVOID Argument1,
                                  IN PVOID Argument2
                                  );

                          To notify the callback, i.e. to cause all registered callback functions
                          to be called, a driver calls ExNotifyCallback:

                          VOID
                          ExNotifyCallback(
                                  IN PCALLBACK_OBJECT CallbackObject,
                                  IN PVOID Argument1,
                                  IN PVOID Argument2
                                  );

                          To remove a function from the list of functions to be called when a
                          callback is notified, a driver calls ExUnregisterCallback. This parameter
                          to this function is the value returned from the call to
                          ExRegisterCallback.

                          You can view the callback objects that exist on your system (Windows 98
                          or Windows 2000) using a tool like Winobj, or by using the objdir command
                          in SoftICE. You will probably see these three callbacks, which are
                          created by the system: SetSystemTime, SuspendHibernateSystem, and
                          SetSystemInformation.

                          Any driver can register a function to be called when the system notifies
                          these callback objects. For example, if you wanted to get notification of
                          whenever the system time was changed, you would add this code to your
                          driver:

                          At global scope:

                          PVOID gUnregisterToken=0;

                          VOID MySetTimeFunction(PVOID ctx, PVOID arg1, PVOID arg2)
                          {
                                  DbgPrint("The set time function was called\n");
                          }

                          During initialization:

                                  NTSTATUS status;
                          OBJECT_ATTRIBUTES Oa;
                                  UNICODE_STRING CallbackName;
                                  PCALLBACK_OBJECT pSetTimeCallback;

                                  RtlInitUnicodeString(&CallbackName,L"\\Callback\\SetSystemTime");

                                  InitializeObjectAttributes(
                                          &Oa,
                                          &CallbackName,
                                          OBJ_CASE_INSENSITIVE,
                                          NULL,
                                          NULL
                                          );

                                  status = ExCreateCallback(&pSetTimeCallback, &Oa, FALSE, FALSE);
                                  if ( NT_SUCCESS(status)  && pSetTimeCallback )
                                  {
                                          gUnregisterToken =
                                                  ExRegisterCallback(
                          pSetTimeCallback,
                          MySetTimeFunction,
                          NULL);
                                  }

                          In your unload or remove routine:

                                  if ( gUnregisterToken )
                                          ExUnregisterCallback(gUnregisterToken);

                          Two final notes about callbacks:

                             * Compuware's DriverWorks class library will provide a class that
                               wraps up callback functionality in an easy to use C++ class.
                             * The callback services exist on NT 4.0, but are stubbed out.

  DriverCentral  DriverStudio  Free downloads  Resources  Support and
                          Services  Shop NuMega
     Compuware NuMega  Tel: +1 603 578-8400  Updated: 9 August 1999 
                      Problems? Contact our webmaster.
