Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / ATL

Developing WMI Hi-Perf Provider using C++

4.60/5 (14 votes)
16 Oct 20058 min read 1   2.6K  
Developing a high-performance provider in WMI using C++.

Introduction

You can always obtain help for developing WMI providers from various Internet forums but I couldn't find any article/guide that could assist me in developing WMI - high performance provider using C++. After some toil, I decided to develop my own provider with the help of MSDN. The objective of this article is to help developers simplify the process of understanding the concept/implementation of Hi-perf providers. I admit that I'm not good at writing an article, but still whatever I have learnt I would like to share it with you all.

Basic concepts of WMI

Windows Management Instrumentation (WMI) is used to access and manipulate system management information such as hardware/software resources, system related data etc. Obtaining such system information finds its main application in administering systems in a network. WMI technology consists of:

  1. Management Infrastructure (MI)

    It includes the Common Information Model (CIM) Object Manager and CIM Object Manager (CIMOM) Repository. The MI stores the schema definitions of the provider classes and provider-binding information. When the MI receives a request for data it dynamically retrieves it from the provider.

  2. WMI providers

    The main task of WMI providers is to act as an intermediary between the CIMOM and the underlying managed objects. For example, a managed object could be hardware related such as drivers, memory etc. or software related such as registry, active directory, drivers etc. The WMI providers interact with the WMI object model and supply the CIMOM with data from these managed objects. They handle requests from management applications and generate event notifications whenever changes occur within the managed objects.

  3. WMI consumers

    They constitute the consumer components and the application monitors. They monitor the changes in CIMOM and upon receipt of an event notification perform a set actions. The client/consumer gives a request to the WMI-CIM Object Manager, and the CIMOM evaluates and routes the request to the corresponding provider. Following this the data is retrieved from the CIMOM and routed to the consumer through the WMI provider. The WMI architecture provides complete transparency to the client/consumer, and they need not worry about which provider is serving or from where the data is coming. Everything is managed by WMI.

WMI providers

There are two ways by which WMI can retrieve instances of classes. One is by reading the repository, the other is by calling a COM object to retrieve the information. These COM objects are referred to as providers. We can say that the WMI provider is analogous to an object-oriented database. It provides data about applications, devices, and other system information in a fashion unlike the standard relational database. It supports classes, instances of those classes and inheritance relationships between these classes. Many of the terms used by WMI map fairly well to the relational database concepts. However, they are just roughly related. On a finer plane, WMI offers features that a relational database does not, and vice versa.

Mapping of WMI to RDMS terms

WMI Terms -> RDBMS equivalent
------------------------------
Namespace -> Database
Class -> Table 
Instance -> Row
Property -> Column
Key -> Primary Key
Association -> Foreign Key

Hi-Perf provider

Hi-perf provider is also known as 'pull provider'. In an instance provider, WMI calls the Performance Counter Provider (PCP) to access data from the managed objects. The PCP in turn calls the performance library to collect this data and finally it returns all instances to the client. In the design of the Hi-perf provider this layer is removed. The high performance of a Hi-perf provider comes from the fact that it allows fast and efficient access to the constantly changing data of the managed objects. It achieves this by having greater control over the amount of data returned to the client. It also captures and reports the performance data that is displayed by perfmon, the windows utility for monitoring system specific data in addition to improving the speed of access. Instead of retrieving all the information of the instances, the hi-perf provider manages to retrieve only the information that is required by the client/consumer. Specific counters can be queried rather than retrieving all the counter data for an object.

What are managed objects?

A managed object (MO) can be a hardware entity such as a memory array, a port or a disk drive. It can also be a software entity such as a service, a user account, or a page file.

What is MOF?

The Managed Object Format (MOF) language was defined with CIM so that descriptions of classes and instances defined as part of CIM could be created in a simple ASCII (or Unicode) text format. The MOF file provides a mechanism to import or export these definitions to or from a CIM repository.

Let’s start now

As discussed earlier, a provider acts as an intermediary between WMI and the managed objects. This intermediary can be developed as managed code (using .NET Framework) or unmanaged code (COM server). The article discusses developing the provider using C++ with COM since it is more efficient than using .NET.

For simplicity, the development of Hi-Perf provider is divided into two phases.

Phase 1

We need to inform WMI about our provider. This can be done by designing the class schema and adding it to the CIM repository. The schema includes a few qualifiers to specify how the class, property or method should be implemented.

  • Step 1: Create an instance of a __Win32Provider with Managed Object Format (MOF) code by providing the Name and CLSID of the provider:
    //Describes the Provider
    instance of __Win32Provider as $P
    {
        Name="MyHiPerf_v1";
        CLSID="{F7FAA84D-0CA4-400E-9346-F6BADA1A8511}";
        ClientLoadableCLSID="{F7FAA84D-0CA4-400E-9346-F6BADA1A8511}";
    };
  • Step 2: Create an instance of __InstanceProviderRegistration class that describes the feature set of the provider:
    //Describe the Features of a Provider
    instance of __InstanceProviderRegistration
    {
        Provider = $P;
        SupportsGet = TRUE;
        SupportsEnumeration = TRUE;
    };
  • Step 3: To enable the counter to appear in the perfmon system monitor, the class must be added to root\cimv2 namespace and should be derived from Win32_PerfRawData. Use MOF code to create the dynamic class for which the provider supplies instances. A dynamic class is a class whose instances receive updates from a provider. These updates can be regular or linked to sporadic changes in the objects the instances represent:
    #pragma namespace("\\\\.\\Root\\CimV2")
    
    qualifier vendor:ToInstance;
    qualifier guid:ToInstance;
    qualifier displayname:ToInstance;
    qualifier perfindex:ToInstance;
    qualifier helpindex:ToInstance;
    qualifier perfdetail:ToInstance;
    qualifier countertype:ToInstance;
    qualifier perfdefault:ToInstance;
    qualifier defaultscale:ToInstance;
    
    [
      hiperf(true),
      dynamic,
      provider("MyHiPerf_v1"),
      displayname("My_Sample_Hi_Perf_Counter"),
      description("My Hi Perf Prov"), 
      perfdetail(100), 
      locale(0x409), 
      maxInstances( 100 ) 
                                               
    ]
    class Win32_MyHiPerf
              : Win32_PerfRawData
    {
        [key, label] uint32 ID = 0;
        [
         displayname("MyCounter1"),
         countertype(0x10000),
         defaultscale(0),
         perfdetail(100),
         perfdefault(0),
         description("Counter to be displayed in perfmon")
        ]
        uint32 MyCounter1 = 0;
    };
  • Step 4: Register your classes with WMI. We can do the registration by either of the two methods:
    1. Automatic registration

      Place the MOF file in %WinDir%\System32\wbem\mof, it gets automatically compiled by winmgmt.exe if it's running, and if successfully compiled it goes to good directory else it goes to bad directory.

    2. Using mofcomp

      From the command prompt in your provider directory, type the following to register the example MOF code with WMI: mofcomp.

Phase 2

Build a COM server that carries out the functions of the provider. This will act as an intermediary between the WMI and the managed object.

  • Step 1: As with any COM object, you must implement a constructor and a destructor, as well as the QueryInterface, AddRef and Release methods.
  • Step 2: Implement IwbemProviderInit::Initialize. The provider should implement this method. It will be called by the WMI to initialize your provider.
  • Step 3: High-performance provider uses a refresher object to keep data up-to-date for the remote client. Therefore, you must implement the following methods for a high-performance provider:

    Implement the HighPerformance interface i.e. IwbemHiPerfProvider

    • IwbemHiPerfProvider::GetObjects - to retrieve the specified objects.
    • IwbemHiPerfProvider::CreateRefresher – to create a refresher.
    • IwbemHiPerfProvider::CreateRefreshableObject - to create a refreshable instance object.
    • IwbemHiPerfProvider::CreateRefreshableEnum - to create a refreshable enumerator.
    • IwbemHiPerfProvider::StopRefreshing - to stop refreshing an enumerator or an instance object.
  • Step 4: If we are implementing IWbemHiPerfProvider then we got to implement the IWbemRefresher interface because it provides an entry point through which refreshable objects, enumerators, and other refreshers can be refreshed. In case of an instance provider, we add an enumerator to enumerate both the instances and the data in each instance, here we add the enumerator to the refresher and when we call IWbemRefresher::Refresh it results in a complete enumeration. When IWbemRefresher::Refresh is called the provider should only access the objects and enumerators in a refresher.

How to use the demo?

Download and unzip WMI_Hi-Perf_Provider_demo.zip. Open the command prompt and go to the Demo directory. In the command prompt, type regsvr32 MyHiPerfProvider.dll to register the provider. Compile the mof using mofcomp e.g. mofcomp MyHiPerf.mof.

That's it, now open the perfmon, right click and say add counter, and select My_WMI_Perf_Counter from the Performance object. By default MyCounter1 will be displayed in the counter list, click on Add and Close, now you will be able to see the graph in the perfmon:

Note: The system monitor displays the calculated or processed performance data from the performance libraries.

Tools

  1. The WMI SDK consists of:
    1. CIM Studio - to define your classes.
    2. CIM Studio MOF Generator - to produce the document that allows you to install your schema on other machines.
    3. WMI code generator.
  2. Winmgmt.exe – can be used as Windows management service.
    1. To know more about this, type winmgmt /?
  3. mofcomp – used to compile MOF files.
  4. winmgmt.msc – helps to configure WMI settings on a local or remote computer like, modify the maximum size of log files, the level of detail entered in them, and the logging directory. It enables the administrator to define authorized users and groups for specific namespaces in WMI.
  5. wbemtest.exe – Windows management instrumentation tester. This GUI-based application enables the user to connect to a namespace and create, delete, and enumerate classes or instances. It also provides an option to enter queries in WMI Query Language ( WQL ) and execute methods. It can be a useful tool for developing WMI provider.
  6. wmic – WMI console.

Conclusions

The code in the source files is mostly an aggregation of code snippets from MSDN. I would really appreciate your comments/suggestions on this article.

Reference

Books

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here