8. Techniques for Testing WMI Driver Support
There are several tools you can use to test WMI support in your driver:
Wbemtest— The operating system includes the Wbemtest
tool, which provides a GUI you can use to query for WMI classes and
class instances, change property values, execute methods, and receive
event notifications. Connect to the root\wmi namespace to test your driver support.
Wmic— Microsoft Windows 7 operating system includes the Wmic, which provides a command shell you can use to issue WMI-related commands to test your driver.
Wmimofck— The wmimofck command can be used to check the syntax of your binary MOF files. You can also use the wmimofck –t command to generate a VBScript file. You can use this script to test your driver’s handling of WMI class instance queries. The wmimofck –w
command generates Web pages that can test querying and setting classes,
executing methods, and receiving events. Note that the Web pages do not
support executing methods that use complex parameters or return values
(such as an array of embedded classes). In such cases, you can use Wbemtest instead.
You can also test your driver’s WMI support by
writing a custom WMI client application, using the WMI user mode API.
For more information about this user mode API, which allows
applications to provide or consume WMI information, refer to the
Windows Management Instrumentation information in the Microsoft Windows
SDK documents.
A WMI client application performs the following tasks to test a driver:
It connects to WMI. To connect to WMI, the application calls the Component Object Model (COM) function, CoCreateInstance, to retrieve a pointer to the IWbemLocator interface. The application then calls the IWbemLocator::ConnectServer method to connect to WMI. From this call, the application receives a pointer to the IWbemServices interface.
It
accesses information in the driver. To access information and to
register for events, the application uses the methods of the IWbemServices interface.
8.1. WMI IRPs and the System Event Log
WMI
errors that occur strictly in kernel mode are logged to the system
event log. You can use the Event Viewer to examine the system event log.
The two main sources of such errors are malformed
replies to WMI requests and incorrect parameters to event
notifications. For example, if the driver returns a malformed WMIREGINFO data structure in response to an IRP_MN_REGINFO or IRP_MN_REGINFO_EX request, the system will log that to the system event log. The system would also log an invalid call to IoWMIWriteEvent and WmiFireEvent to issue a WMI event notification.
8.2. WMI WDM Provider Log
WMI errors that occur while being handled by the WMI WDM provider (wmiprov.dll) are logged to the log file for the WMI WDM Provider, wmiprov.log. This is a text file that can be found in %windir%\system32\wbem\logs\wmiprov.log. Errors, such as a bad or missing MOF resource for the driver, are logged here. In the case of a bad MOF resource, the file %windir%\system32\mofcomp.log might have additional information related to the error.
You can change the logging settings for all WMI providers by using the Wmimgmt.msc
application. You can disable or reenable logging, change the directory
where WMI log files are kept, as well as set the maximum size for such
files.
9. WMI Event Tracing
This discussion describes the WMI extensions to WDM
that Kernel Mode Drivers, as information providers, can use to provide
information to information consumers. Drivers typically provide
information that a consumer uses to determine the driver’s
configuration and resource usage. In addition to the WMI extensions to
WDM, a user mode API supports providers or consumers of WMI event
information.
The event tracing logger supports up to 32
instances. One of the instances is reserved for tracing the kernel. The
logger supports tracing a high event rate.
Trace events are defined in the same manner as other WMI events. WMI events are described in the MOF file.
The process by which Kernel Mode Drivers log
information is integrated into the existing WMI infrastructure. To log
trace events, a driver does the following:
Register as a WMI provider by calling IoWMIRegistrationControl.
Mark events as traceable by setting WMIREG_FLAG_TRACED_GUID in the Flags member of the WMIREGGUID structure that is passed when the driver registers events with WMI.
Specify one event as the control event for overall enabling/disabling of a set of trace events by setting WMIREG_FLAG_TRACE_CONTROL_GUID in the Flags member of the WMIREGGUID structure that is passed when the driver registers events with WMI.
Upon
receiving a request from WMI to enable events where the GUID matches
the trace control GUID, the driver should store the handle to the
logger. The value will be needed when writing an event. For information
about how to use this handle, see step 6. The logger handle value is
contained in the HistoricalContext member of the WNODE_HEADER portion of the WMI buffer that is part of the parameters in the enable events request.
Decide
whether the trace event will be sent to WMI event consumers or is
targeted for the WMI event logger only. This determines where the
memory for the EVENT_TRACE_HEADER structure should come from. This memory eventually is passed to IoWMIWriteEvent.
If
the event is a log event only, the memory is not deleted by WMI. In
this case, the driver should pass in a buffer on the stack or should be
reusing an allocated buffer for this purpose. For performance reasons,
the driver should minimize any unnecessary calls to allocate or free
memory. Failure to comply with this recommendation compromises the
integrity of the timing information contained in the log file.
If
the event is to be sent to both the logger and to WMI event consumers,
the memory must be allocated from a nonpaged pool. In this case, the
event is sent to the logger and then forwarded to WMI to be sent to WMI
event consumers who have requested notification of the event. The
memory for the event is then freed by WMI according to the behavior of IoWMIWriteEvent.
After the memory for the EVENT_TRACE_HEADER and any driver event data, if any, has been secured, the following information should be set:
Set the Size member to the size of (EVENT_TRACE_HEADER) plus the size of any additional driver event data that will be appended on to the end of EVENT_TRACE_HEADER.
Set the Flags member to WNODE_FLAG_TRACED_GUID to have the event sent to the logger. If the event is to be sent to WMI event consumers as well, set the WNODE_FLAG_LOG_WNODE. Note, it is not necessary to set WNODE_FLAG_TRACED_GUID if setting WNODE_FLAG_LOG_WNODE. If both are set, WNODE_FLAG_TRACED_GUID takes precedence and the event is not sent to WMI event consumers.
Set the Guid or the GuidPtr member. If using GuidPtr, set WNODE_FLAG_USE_GUID_PTR in the Flags member. Optionally, specify a value for TimeStamp. If the driver does not specify a TimeStamp value, the logger fills this in. If the driver does not want the logger to set the time stamp, it should set WNODE_FLAG_USE_TIMESTAMP in the Flags member.
Set any of the following EVENT_TRACE_HEADER members that have meaning to the driver—that is, Class.Type, Class.Level, and Class.Version.
Finally, cast the EVENT_TRACE_HEADER to a WNODE_HEADER and set the HistoricalContext value of the Wnode to the logger handle that was saved in the preceding step 4.
Call IoWMIWriteEvent with the pointer to the EVENT_TRACE_HEADER structure.
The driver should continue logging trace
events associated with the control GUID until the driver receives
notification to disable event logging via an IRP_MN_DISABLE_EVENTS request.