The WMI Architecture

< BACK  NEXT >
[oR]

The WMI architecture consists of five layers:

  • A source of WMI data (e.g., a device driver) designated the data provider

  • A central repository of WMI data that implements a CIM-compliant data store, based on the CIM object model (CIMOM)

  • A WMI provider (e.g., the WDM WMI provider) that provides the necessary linkage between a WMI data source and the data store

  • A consumer (or client) of the WMI data

  • A protocol (e.g., COM) that presents the data store to a consumer

The WMI provider for WDM consists of two parts:

  • A user-mode Win32 DLL that provides linkage between a user-mode client

  • A set of kernel-mode services that invoke and respond to driver code. An IRP, IRP_MJ_SYSTEM_CONTROL, is the mechanism by which these services make requests of the driver for WMI data.

A diagram of the WMI architecture is shown in Figure 13.2.

Figure 13.2. WMI architecture.
graphics/13fig02.gif

Providing WMI Support in a WDM Driver

In order to supply WMI data, a driver must perform the following steps:

  1. Provide a MOF description of the data, methods, and events that will be provided and generated by the driver.

  2. Compile the MOF source file (.MOF) using the mofcomp.exe tool provided with the DDK. This tool produces a platform-independent binary file (.BMF) for the next step.

  3. Include the compiled MOF data within the resource section of the driver binary.

  4. Provide an IRP_MJ_SYSTEM_CONTROL dispatch routine within the driver code. When received, the minor subcode field of the IRP specifies the exact kind of WMI request.

  5. Register as a provider of WMI data using IoWmiRegistrationControl.

  6. Process the IRP_MJ_SYSTEM_CONTROL IRP with minor subcode IRM_MN_REGINFO. The IRP for such a request contains an action code (in Parameters.WMI.DataPath) that is either WMIREGISTER or WMIUPDATE. The action code forms a third dispatch level for such an IRP. (Major, minor, and action code form the three dispatch levels.)

  7. Process the action code WMIREGISTER by providing information about the data and event blocks defined within the MOF description.

  8. Process the action code WMIUPDATE by invoking helper functions declared with WMILIB.h.

Each of these eight steps is described in more detail below.

MOF Syntax

MOF syntax follows the standard structure of RPC interface definitions described by the Interface Definition Language (IDL). The basic form is

 [ATTRIUBUTES and QUALIFIERS] ENTITY TYPE and NAME {      [DATA ITEM QUALIFIERS] DATA TYPE and NAME;      ... }; 

The definitions can be nested, much as a structure is defined within a structure. The entity type can consist of such keywords as class, string, or boolean. The basic MOF description starts with a class name, which is case insensitive and must be unique within the entire WMI namespace. Classes can inherit the definitions of a base class, just as in C++.

 [ // Class qualifiers ] class HiResCamera : Camera { // Data definitions added by HiResCamera }; 

A derived class name is uniquely qualified by its base class name and thus the name "HiResCamera" need only be unique beneath the base class of Camera.

Class qualifiers are listed in Table 13.1 and three of these attributes are required for a WMI-compliant driver: Provider, WMI, and Guid.

Each data definition constitutes an item within the class, complete with its own set of item qualifiers, listed in Table 13. 2. The list of MOF-legal data types is described in Table 13.3.

The MOF syntax requires two items within a class definition: Instance-Name and Active. These two items are managed internally by WMI and, therefore, should not be considered data that is part of the driver itself. The data types of InstanceName and Active are string and boolean, respectively.

Table 13.1. Class Qualifiers for WMI MOF Definition
Class Qualifier Description
Dynamic Data for the MOF block is supplied at runtime on a per instance basis of the class.
Static Data for the MOF block is included as part of the WMI database.
Provider("WmiProv") Required. Indicates that the provider of this class is WMI-compliant.
WMI Required. Indicates WMI class.
Description("text") Documentation or comment which can be made available to clients of the class.
Guid("guid") The unique 128-bit number identifying the class.
Locale("MS\lcid") The locale (language) ID for which the Description text is supplied.
WmiExpense(cost) The collection cost in CPU cycles for data described and collected by the class.

Table 13.2. MOF Data Item Qualifiers
Data Item Qualifier Description
key This data item uniquely identifies class instance.
read WMI client can read the item.
write WMI client can write the item.
BitMap List of string names representing "bit names" corresponding to bit positions within BitValues. The string list is enclosed within braces ({,}) immediately after the BitMap keyword.
BitValues Bit positions corresponding to the names specified by BitMap. The bit list is enclosed within braces immediately after the BitValues keyword.
ValueMap List of string names representing the enumerated values within Values. The string list is enclosed within braces immediately after the ValueMap keyword.
Values List of values corresponding to the names specified by ValueMap. The value list is enclosed within braces immediately after the Values keyword.
WmiDataId(ItemId) Required. Specifies the location of the data item within the MOF data block. The first item has ID of 1, the fourth has ID of 4.
WmiSizeIs("ItemName") Specifies another "ItemName" that indicates the number of elements for this array item (valid only for array data items).
WmiScale(ScaleFactor) Specifies the magnitude (base 10) for the report of this data item. For example, with ScaleFactor = 3, a data item of value 7 would indicate 7000.
WmiTimeStamp Indicates the 64-bit item value is a 100 nanosecond tick count since 01/01/1601.
WmiComplexity("Level") A comment potentially used by clients in deciding whether to expose this item. Possible values are "Novice," "Advanced," "Expert," "Wizard."
WmiVolatility(Interval) Specifies the interval in milliseconds for the frequency of updates to the item.
WmiEventTrigger("ItemName") For an event block, specifies another ItemName that defines the value at which this event item triggers.
WmiEventRate("ItemName") For an event block, specifies another ItemName that defines the frequency at which this event item fires.

Table 13.3. MOF Data Types
Data Type Description sizeof
string Counted Unicode string 12
boolean TRUE or FALSE (zero or nonzero) 1
sint8 Signed 8-bit integer 1
uint8 Unsigned 8-bit integer 1
sint16 Signed 16-bit integer 2
uint16 Unsigned 16-bit integer 2
sint32 Signed 32-bit integer 4
uint32 Unsigned 32-bit integer 4
sint64 Signed 64-bit integer 8
uint64 Unsigned 64-bit integer 8
datetime Unicode string holding date & time: "yyyymmddhhmmss: utc" where = microseconds utc = GMT (UTC) minute offset

Example MOF Class Definition

The following is a simple example of a completed MOF class definition:

 [WMI, guid("12345678-1234-5678-9ABC-123456789ABC"),      Dynamic, Provider("WMIProv"),      WmiExpense(1),      Locale("MS\\0x409"),      Description("Example class")] class W2KDriverBook_Missile { // Required item definitions - unused by driver     [key, read] string InstanceName;     [read] boolean Active; // Property: Total Launches     [read,     WmiDataId(1),     WmiScale(0),     Description("Total Missile Launches")]     uint32 TotalLaunches; 
 //The number of silos in the SiloStatus array     [read,     WmiDataId(2) ]      uint32 SiloCount; //SiloStatus Array     [read,      WmiDataId(3),      WmiSizeIs("SiloCount") ]      uint8 SiloStatus[]; }; 

Compiling the MOF Source

To compile the MOF source, the tool mofcomp.EXE, located in the system32 directory, is used. Two switches are needed for WDM driver development.

  • -B:filename.bmf

  • -WMI

The -B switch instructs the MOF compiler to place the binary results into the specified filename, which is then inserted into the driver's resource area. The -WMI switch forces a second pass on the MOF input to validate compliance with WMI. For the example MOF file listed above, the command line

 mofcomp -B:Example.bmf -WMI Example.MOF 

successfully compiles the definitions.

Once the binary MOF (.bmf) file is created, the driver must include a source resource file (.RC) into the project (makefile) with the following line:

 MofResource MOFDATA Example.bmf 

When the driver loads into system memory, its resource section is placed into RAM and is accessible to the driver. The resource name, specified by the .bmf filename, is announced in response to the WMI IRP request WMIREGISTER.

Handling WMI IRP Requests

The first step a driver must take to handle WMI requests is to register itself with the I/O Manager as a WMI participant. This is performed with the IoWMIRegistrationControl function, described in Table 13.4. Initially, a driver should perform the Action of WMIREG_ACTION_REGISTER, presumably during the AddDevice routine. Similarly, during RemoveDevice, the Action WMIREG_ACTION_DEREGISTER is performed.

Once registered for WMI action, a driver must respond to the IRP Dispatch function for the major code IRP_MJ_SYSTEM_CONTROL. This IRP request supplies one of several minor subcodes, listed in Table 13.5. The IRP stack's Parameters' union contains a WMI structure, defined in Table 13.6. This WMI structure supplies data for the request (input and output).

Table 13.4. IoWMIRegistrationControl Function Prototype
NTSTATUS IoWMIRegistrationControl IRQL == PASSIVE_LEVEL
Parameter Description
IN PDEVICE_OBJECT pDeviceObject Pointer to Device object
IN ULONG Action WMIREG_ACTION_REGISTER
WMIREG_ACTION_DEREGISTER
WMIREG_ACTION_REREGISTER
WMIREG_ACTION_UPDATE_GUIDS
WMIREG_ACTION_BLOCK_IRPS
Return value Success or failure code

Table 13.5. IRP_MJ_SYSTEM_CONTROL Minor Functions
IRP_MJ_SYSTEM_CONTROL
Minor Function Subcodes Description
IRP_MN_QUERY_ALL_DATA Request for all instances of a data block
IRP_MN_QUERY_SINGLE_INSTANCE Request for a specific instance
IRP_MN_CHANGE_SINGLE_INSTANCE Request to modify all data of a specific instance
IRP_MN_CHANGE_SINGLE_ITEM Request to modify one datum
IRP_MN_ENABLE_EVENTS Informs driver that a data consumer has requested event notification
IRP_MN_DISABLE_EVENTS Data consumer no longer wishes notification of events
IRP_MN_ENABLE_COLLECTION Request to begin collection of "expensive" instrument data
IRP_MN_DISABLE_COLLECTION Request to stop collecting
IRP_MN_REGINFO Query or modify a driver's registration information
IRP_MN_EXECUTE_METHOD Invokes a method defined in the MOF data block

Classes and Instances

A data block described as a class within the MOF syntax declares a class data block. No instances of the class exist (i.e., no data space is reserved) until such time as the driver registers the data block, typically performed within the DpWmiQueryReginfo function, described below.

While typically only one instance of a class is appropriate, some circumstances suggest the existence of an array of instances to best model the data being collected. For example, suppose the Missile driver collects data for each of the three engines powering the rocket. The fuel used by one engine may be separate data from that used by another. If each missile engine is described by a separate instance of a MOF Missile_Engine class, each query or update of data requires an additional instance index to fully qualify the request.

Table 13.6. Parameters. WMI Structure Definition
struct WMI
Field Description
ProviderId Pointer to target Device object
DataPath GUID of MOF data block
BufferSize Size of the Buffer
Buffer Buffer whose contents are minor function code specific

Of course, the fuel level of each engine could also be kept as an array of values within a single instance. Thus, the decision to use multiple instances of data blocks is dictated by whether or not all the entries within the block should be stacked, one per instance.

WMILIB

Responding to WMI IRP requests is facilitated by a kernel-mode DLL, WMILIB. The heart of this library support is a routine, WmiSystemControl, described in Table 13.7. The function receives as input a data structure of type WMILIB_CONTEXT, described in Table 13.8, which is primarily a list of function pointers that get, set, or otherwise control MOF items. The functions are provided by the driver, and if not supplied, should be set to NULL.

The GuidList member of the WMILIB_CONTEXT structure is an array of structures of type WMIGUIDREGINFO, one array element for each MOF data block class exposed by the driver. The WMIGUIDREGINFO structure is described in Table 13.9.

WmiSystemControl returns a disposition status that describes how the IRP was handled.

Table 13.7. WmiSystemControl Function Prototype
NTSTATUS WmiSystemControl IRQL == PASSIVE_LEVEL
Parameter Description
IN PWMILIB_CONTEXT WmiLibInfo Pointer to WMILIB_CONTEXT structure, provided and initialized by driver
IN PDEVICE_OBJECT pDeviceObject Driver's Device Object
IN PIRP pIrp Pointer to IRP of request
OUT PSYSCTL_IRP_DISPOSITION IrpProcessed
pIrpDisposition IrpNotCompleted
IrpNotWmi
IrpForward
Return value Success or failure code

Table 13.8. WMILIB_CONTEXT Structure Definition
struct WMILIB_CONTEXT
Field Description
ULONG GuidCount Number of MOF data blocks registered by driver
PWMIGUIDREGINFO GuidList Array of GUIDs and instance counts
PWMI_QUERY_REGINFO QueryWmiRegInfo Function pointer to driver-supplied routine, DpWmiQueryReginfo
PWMI_QUERY_DATABLOCK QueryWmiDataBlock Function pointer to driver-supplied routine, DpWmiQueryDataBlock
PWMI_SET_DATABLOCK SetWmiDataBlock Function pointer to driver-supplied routine, DpWmiSetDataBlock (may be NULL)
PWMI_SET_DATAITEM SetWmiDataItem Function pointer to driver-supplied routine, DpWmiSetDataItem (may be NULL)
PWMI_EXECUTE_METHOD ExecuteWmiMethod Function pointer to driver-supplied routine, DpWmiExecuteMethod (may be NULL)
PWMI_FUNCTION_CONTROL WmiFunctionControl Function pointer to driver-supplied routine, DpWmiFunctionControl (may be NULL)

On the surface, WmiSystemControl does little more than dispatch the minor subcode of IRP_MJ_SYSTEM_CONTROL to the appropriate driver-supplied DpWmiXxx routine. The real advantage of WMILIB is that it handles the complete WMI protocol, leaving the driver with only the necessary task of MOF data-specific handling.

Table 13.9. WMIGUIDREGINFO Structure Definition
struct WMIGUIDREGINFO
Field Description
LPCGUID Guid Pointer to GUID that identifies block
ULONG InstanceCount Number of instances to create
ULONG Flags Characteristics of block:
WMIREG_FLAG_INSTANCE_PDO
WMIREG_FLAG_EVENT_ONLY_GUID
WMIREG_FLAG_EXPENSIVE
WMIREG_FLAG_REMOVE_GUID

Each dispatch function pointed to by an entry within WMILIB_CONTEXT is a unique function signature (prototype) with various responsibilities. These DpWmi functions are described in further detail below.

With the exception of DpWmiQueryReginfo, each of these routines completes its normal work by invoking WmiCompleteRequest, described in Table 13.10. This WMILIB function marks the IRP as "complete" and finishes the WMI protocol sequence.

DpWmiQueryReginfo

The DpWmiQueryReginfo function, supplied by the driver, is described in Table 13.11. It is invoked by WMILIB when the requesting IRP contains the minor subcode IRP_MN_REGINFO with action code (Parameters.WMI.DataPath) equal to WMIREGISTER or WMIUPDATE. The prime purpose of this driver routine is to register one or more instances of data class.

The implementation of this function should include code to implement the driver's strategy for the naming of data block instances. The RegFlags parameter includes a bit, WMIREG_FLAG_INSTANCE_BASENAME, which allows WMI to automatically append an instance counter number to the base name specified by InstanceName. Otherwise, the driver can implement its own naming strategy. It is noteworthy that these instance names are persistent (sticky) across boots of the OS. The names are registered in the CIMOM store.

Yet another driver strategy is to use the PDO name for the instance base name. To utilize this strategy, a driver sets the RegFlags' bit WMI_FLAG_ INSTANCE_PDO.

Table 13.10. WmiCompleteRequest Function Prototype
NTSTATUS WmiCompleteRequest IRQL <= DISPATCH_LEVEL
Parameter Description
IN PDEVICE_OBJECT pDeviceObject Pointer to driver's device object
IN PIRP pIrp Pointer to IRP of request
IN NTSTATUS Status Final status to return in IRP
IN ULONG BufferUsed If buffer was too small for request, this value holds what was required; otherwise, holds bytes used.
IN CCHAR PriorityBoost Same as IoCompleteRequest Priority- Boost, usually a fixed value

Table 13.11. DpWmiQueryRegInfo Function Prototype
NTSTATUS DpWmiQueryReginfo IRQL == PASSIVE_LEVEL
Parameter Description
IN PDEVICE_OBJECT pDeviceObject Pointer to driver's device object
OUT PULONG pRegFlags Registration flags set by driver for all registered MOF data blocks
OUT PUNICODE_STRING InstanceName When RegFlags has bit WMIREG_FLAG_INSTANCE_ BASENAME set, InstanceName is used as base with instance counter appended. WMI frees this string with a call to ExFreePool.
OUT PUNICODE_STRING *pRegistryPath Same string passed to driver's DriverEntry
OUT PUNICODE_STRING MofResourceName String containing name of MOF .bmf file
OUT PDEVICE_OBJECT *pPDO PDO to use for generation of physical device instance names (only if RegFlags WMIREG_FLAG_ INSTANCE_PDO set)
Return value STATUS_SUCCESS

DpWmiQueryDataBlock

The DpWmiQueryDataBlock function is described in Table 13.12. It is invoked by WMILIB when the requesting IRP contains the minor subcode IRP_MN_QUERY_DATA_BLOCK or IRP_MN_QUERY_ALL_DATA. The purpose of this driver routine is to return the instance(s) data requested.

DpWmiSetDataBlock

The DpWmiSetDataBlock function is described in Table 13.13. It is invoked by WMILIB when the requesting IRP contains the minor subcode IRP_MN_CHANGE_SINGLE_INSTANCE. The purpose of this driver routine is to modify the specified instance data. As defined, only one instance can be changed at one time, but when multiple instances exist, the InstanceIndex value of zero remains undefined.

DpWmiSetDataItem

The DpWmiSetDataItem function is described in Table 13.14. It is invoked by WMILIB when the requesting IRP contains the minor subcode IRP_MN_ CHANGE_SINGLE_ITEM. The purpose of this driver routine is to modify the specified data item within the specified instance data.

Table 13.12. DpWmiQueryDataBlock Function Prototype
NTSTATUS DpWmiQueryDataBlock IRQL == PASSIVE_LEVEL
Parameter Description
IN PDEVICE_OBJECT pDeviceObject Pointer to driver's device object
IN PIRP pIrp Pointer to IRP of WMI request
IN ULONG GuidIndex Index into WMILIB_CONTEXT structure's GuidList, identifying data block
IN ULONG InstanceIndex Specific data instance being queried (0 if all instances being queried)
IN ULONG InstanceCount Number of instances being queried
IN OUT PULONG InstanceLengthArray Array of ULONGs specifying length of each instance being returned
IN ULONG BufferAvail Size of Buffer
OUT PUCHAR Buffer Buffer to receive instance data
Return value STATUS_SUCCESS
STATUS_BUFFER_TOO_SMALL
STATUS_WMI_GUID_NOT_FOUND
STATUS_WMI_INSTANCE_NOT_ FOUND

Table 13.13. DpWmiSetDataBlock Function Prototype
NTSTATUS DpWmiSetDataBlock IRQL == PASSIVE_LEVEL
Parameter Description
IN PDEVICE_OBJECT pDeviceObject Pointer to driver's device object
IN PIRP pIrp Pointer to IRP of WMI request
IN ULONG GuidIndex Index into WMILIB_CONTEXT structure's GuidList, identifying data block to modify
IN ULONG InstanceIndex Specific data instance being modified
IN ULONG BufferSize Size of Buffer
IN PUCHAR Buffer Buffer supplying new instance data
Return value STATUS_SUCCESS
STATUS_PENDING
STATUS_WMI_READ_ONLY
STATUS_WMI_SET_FAILURE
STATUS_WMI_GUID_NOT_FOUND
STATUS_WMI_INSTANCE_NOT_ FOUND

Table 13.14. DpWmiSetDataItem Function Prototype
NTSTATUS DpWmiSetDataItem IRQL == PASSIVE_LEVEL
Parameter Description
IN PDEVICE_OBJECT pDeviceObject Pointer to driver's device object
IN PIRP pIrp Pointer to IRP of WMI request
IN ULONG GuidIndex Index into WMILIB_CONTEXT structure's GuidList, identifying data block
IN ULONG InstanceIndex Specific data instance being modified
IN ULONG DataItemId ID of data item being modified
IN ULONG BufferSize Size of Buffer
IN PUCHAR Buffer Buffer supplying new instance data
Return value STATUS_SUCCESS
STATUS_PENDING
STATUS_WMI_READ_ONLY
STATUS_WMI_SET_FAILURE
STATUS_WMI_GUID_NOT_FOUND
STATUS_WMI_INSTANCE_NOT_ FOUND

DpWmiExecuteMethod

The DpWmiExecuteMethod function is described in Table 13.15. It is invoked by WMILIB when the requesting IRP contains the minor subcode IRP_MN_EXECUTE_METHOD. The purpose of this driver routine is to dispatch execution to the specified method.

In many ways, this is a "direct call" interface from WMI clients into driver code. The interface is marshaled by the DpWmiExecuteMethod routine, which has the ability to validate and convert parameters before presentation to the requested method. Separately, the output buffer can be marshaled before it is returned to the client. The passing of addresses within the input or output buffer is problematic and should probably be avoided.

DpWmiFunctionControl

The DpWmiFunctionControl function is described in Table 13.16. It is invoked by WMILIB when the requesting IRP contains the minor subcode IRP_MN_ENABLE_COLLECTION, IRP_MN_DISABLE_COLLECTION, IRP_MN_ ENABLE_EVENTS, or IRP_MN_DISABLE_EVENTS. The purpose of this driver routine is to start or stop the collection of data (i.e., data that is marked as "expensive" with the bit WMIREG_FLAG_EXPENSIVE at registration) or to start or stop the generation of events.

Table 13.15. DpWmiExecuteMethod Function Prototype
NTSTATUS DpWmiExecuteMethod IRQL == PASSIVE_LEVEL
Parameter Description
IN PDEVICE_OBJECT pDeviceObject Pointer to driver's device object
IN PIRP pIrp Pointer to IRP of WMI request
IN ULONG GuidIndex Index into WMILIB_CONTEXT structure's GuidList, identifying data block
IN ULONG InstanceIndex Specific instance with method to execute
IN ULONG MethodId ID of method to execute
IN ULONG InBufferSize Number of bytes passed in Buffer to method
IN ULONG OutBufferSize Size of Buffer
IN OUT PUCHAR Buffer Input and output buffer for executing method
Return value STATUS_SUCCESS
STATUS_BUFFER_TOO_SMALL
STATUS_INVALID_DEVICE_REQUEST
STATUS_WMI_INSTANCE_NOT_FOUND
STATUS_WMI_ITEM_ID_NOT_FOUND

Table 13.16. DpWmiFunctionControl Function Prototype
NTSTATUS DpWmiFunctionControl IRQL == PASSIVE_LEVEL
Parameter Description
IN PDEVICE_OBJECT pDeviceObject Pointer to driver's device object
IN PIRP pIrp Pointer to IRP of WMI request
IN ULONG GuidIndex Index into WMILIB_CONTEXT structure's GuidList, identifying data block
IN WMIENABLEDISABLECONTROL WmiEventControl: control event generation
Function WmiDataBlockControl: control collection
IN BOOLEAN bEnable TRUE - Enable event or collection
FALSE - Disable event or collection
Return value STATUS_SUCCESS
STATUS_WMI_GUID_NOT_FOUND
STATUS_INVALID_DEVICE_REQUEST

< BACK  NEXT >


The Windows 2000 Device Driver Book(c) A Guide for Programmers
The Windows 2000 Device Driver Book: A Guide for Programmers (2nd Edition)
ISBN: 0130204315
EAN: 2147483647
Year: 2000
Pages: 156

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net