WMI Concepts
Figure 10-2 diagrams the overall architecture of WMI. In the WMI model, the world is divided into consumers and providers of data and events. Consumers consume, and providers provide, blocks of data that are instances of abstract classes. The concept involved here is no different from that of a class in the C++ language. Just like C++ classes, WMI classes have data members and methods that implement behaviors for objects. What goes inside a data block isn t specified by WMI that depends on who s producing the data and for what purpose.
Figure 10-2. The world of WMI.
WMI allows for multiple namespaces, each of which contains classes belonging to one or more providers. A namespace contains attributes and classes, each of which must have a unique name within that namespace. Each namespace can have its own security descriptor, which an administrator can specify in the Computer Management applet. Consumers and providers alike specify the namespace within which they will operate. Table 10-1 lists some of the namespaces that exist on one of my computers. The WMI namespace is the one we re concerned with in this chapter since it s where the classes are located that drivers work with.
Namespace Name | Description |
root\CIMV2 | Industry-standard classes |
root\DEFAULT | Registry access and monitoring |
root\Directory\LDAP | Active Directory objects |
root\MSAPPS | Microsoft application classes |
root\WMI | WDM device driver classes |
A WDM driver can provide instances of one or more WMI classes in the root\wmi namespace. Many drivers support standard classes defined by Microsoft in the DDK file named WMICORE.MOF. Drivers can also implement a customschema that includes vendor-specific or device-specific classes. You define a schema by using a language named the Managed Object Format, or MOF. The system maintains a data dictionary known as the repository that contains the definitions of all known schemas. Assuming you do all the right things in your driver, the system will automatically put your schema into the repository when it initializes your driver.
More Info
Another way of thinking about WMI is in terms of a classical relational database. A WMI class is the same thing as a table. Instances of a class correspond to records, and the class members to fields in a record. The repository plays the same role as a traditional data dictionary. There is even a query language associated with WMI that includes concepts drawn from Structured Query Language (SQL), which database programmers are familiar with.
A Sample Schema
Later in this chapter, I ll show you a sample named WMI42.SYS, which is available in the companion content. This sample has the following MOF schema:
[Dynamic, Provider("WMIProv"), WMI, Description("Wmi42 Sample Schema"), guid("A0F95FD4-A587-11d2-BB3A-00C04FA330A6"), locale("MS\\0x409")] class Wmi42 { [key, read] string InstanceName; [read] boolean Active; [WmiDataId(1), Description("The Answer to the Ultimate Question") ] uint32 TheAnswer; };
I don t propose to describe all the details of the MOF syntax; that information is available as part of the Platform SDK and WMI SDK documentation. You can either construct your MOF by hand, as I did for this simple example, or use a tool named WBEM CIM Studio that comes with the WMI SDK. Here, however, is a brief explanation of the contents of this MOF file:
The provider named WMIProv is the system component that knows how to instantiate this class. It understands, for example, how to call into kernel mode and send an I/O request packet (IRP) to an appropriate driver. It can find the right driver by means of the globally unique identifier (GUID) that appears near the beginning of the file.
This schema declares a class named WMI42, which coincidentally has the same name as our driver. Instances of the class have properties named InstanceName, Active, and TheAnswer.
As developers, we run the MOF compiler on this schema definition to produce a binary file that eventually ends up as a resource in our driver executable file. Resource in this sense is the same concept that application developers have in mind when they build dialog box templates, string tables, and other things that are part of their project s resource script.
Mapping WMI Classes to C Structures
The WMI42 class is especially simple because it has just a single data member that happens to be a 32-bit integer. The mapping from the class data structure used by WMI to the C structure used by the driver is therefore completely obvious. The mapping of a more complex WMI class is harder to determine, especially if you declare the data items in a different order than the WmiDataId ordinals. Rather than trying to predict how WMI will map a class, I recommend that you ask WMIMOFCK to create a header file containing the declarations you ll need. You can issue commands like these at a command prompt:
mofcomp -wmi -b:wmi42.bmf wmi42.mof wmimofck -hwmi42.h -m wmi42.bmf
The mofcomp step yields a binary MOF file (wmi42.bmf). Among other things, the wmimofck step creates a header file (wmi42.h) like this one:
#ifndef _wmi42_h_ #define _wmi42_h_ // Wmi42 - Wmi42 // Wmi42 Sample Schema #define Wmi42Guid \ { 0xa0f95fd4,0xa587,0x11d2, \ { 0xbb,0x3a,0x00,0xc0,0x4f,0xa3,0x30,0xa6 } } DEFINE_GUID(Wmi42_GUID, 0xa0f95fd4,0xa587,0x11d2,0xbb,0x3a, 0x00,0xc0,0x4f,0xa3,0x30,0xa6); typedef struct _Wmi42 { // The Answer to the Ultimate Question of Life, // the Universe, and Everything ULONG TheAnswer; #define Wmi42_TheAnswer_SIZE sizeof(ULONG) #define Wmi42_TheAnswer_ID 1 } Wmi42, *PWmi42; #define Wmi42_SIZE (FIELD_OFFSET(Wmi42, TheAnswer) \ + Wmi42_TheAnswer_SIZE) #endif
Note that the size of the structure is not simply sizeof(Wmi42). The reason for the curious definition of Wmi42_SIZE is that WMI class structures aren t padded to a multiple of the most stringent interior alignment as are C structures.
TIP
All of the examples in this chapter rely on the version of WMIMOFCK that is part of beta versions of the Windows .NET Server DDK. If you try to use an earlier DDK to build and test these samples, you ll probably have to make some source changes to the driver code.