Getting information from WMI in C

You will need to include the libraries ole32.lib, oleaut32.lib and wbemuuid.lib into your project. The following code can be compiled in Code::Blocks and Eclipse, no need for Visual Studio.

Includes and Definitions:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <stdbool.h>
#include <wbemidl.h>
 
#define WIN_VISTA		0x0600
 
CLSID CLSID_WbemLocator2 = {0x4590F811, 0x1D3A, 0x11D0, {0x89, 0x1F, 0, 0xAA, 0, 0x4B, 0x2E, 0x24}};

Functions to connect to WMI and execute a Query:

bool wmiInitialize(){
  HRESULT result;
  bool _init_success = false, _initsec_success = false;
 
  result = CoInitializeEx(0, COINIT_MULTITHREADED);
  if (FAILED(result)) return false;
  _init_success = (result == S_OK || result == S_FALSE || result == RPC_E_CHANGED_MODE);
 
  result =  CoInitializeSecurity(
      NULL,
      -1,
      NULL,
      NULL,
      RPC_C_AUTHN_LEVEL_DEFAULT,
      RPC_C_IMP_LEVEL_IMPERSONATE,
      NULL,
      EOAC_NONE,
      NULL
      );
 
  if (FAILED(result)) return false;
  _initsec_success = (result == S_OK || result == RPC_E_TOO_LATE);
 
  return (_init_success && _initsec_success);
}
 
void* wmiCreate(){
  HRESULT result;
  IWbemLocator *locator = NULL;
 
  result = CoCreateInstance(
      &CLSID_WbemLocator2, NULL,
      CLSCTX_INPROC_SERVER | CLSCTX_NO_FAILURE_LOG | CLSCTX_NO_CODE_DOWNLOAD,
      &IID_IWbemLocator, (LPVOID *) &locator);
 
  if (FAILED(result)) return NULL;
  if(result == S_OK && locator != NULL) return locator;
 
  return NULL;
}
 
void* wmiConnect(IWbemLocator *locator, BSTR resource){
  HRESULT result;
  IWbemServices *services = NULL;
  bool _connect_success = false, _setproxy_success = false;
 
  result = locator->lpVtbl->ConnectServer(
      locator,
      resource,
      NULL,
      NULL,
      NULL,
      0,
      NULL,
      NULL,
      &services
    );
 
  if (FAILED(result)) return NULL;
  _connect_success = (result == WBEM_S_NO_ERROR);
 
  result = CoSetProxyBlanket(
       (IUnknown *)services,
       RPC_C_AUTHN_WINNT,
       RPC_C_AUTHZ_NONE,
       NULL,
       RPC_C_AUTHN_LEVEL_CALL,
       RPC_C_IMP_LEVEL_IMPERSONATE,
       NULL,
       EOAC_NONE
      );
 
  if (FAILED(result))
  {
      services->lpVtbl->Release(services);
      return NULL;
  }
  _setproxy_success = (result == S_OK);
 
  if(_connect_success && _setproxy_success) return services;
  return NULL;
}
 
void* wmiQuery(IWbemServices *services, BSTR query){
  HRESULT result;
  BSTR language = SysAllocString(L"WQL");
  IEnumWbemClassObject *pEnumerator = NULL;
 
  result = services->lpVtbl->ExecQuery(
      services,
      language,
      query,
      WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
      NULL,
      &pEnumerator);
 
  if (FAILED(result)) {
      SysFreeString(language);
      return NULL;
  }
 
  if(result == WBEM_S_NO_ERROR && pEnumerator != NULL) {
      SysFreeString(language);
      return pEnumerator;
  }
 
  SysFreeString(language);
  return NULL;
}
 
void wmiGetStringField(IEnumWbemClassObject *pEnumerator, WCHAR *pfieldname){
  IWbemClassObject *pclsObj = NULL;
  ULONG uReturn = 0;
  HRESULT result;
 
  result = pEnumerator->lpVtbl->Next(pEnumerator, WBEM_INFINITE, 1, &pclsObj, &uReturn);
  if (FAILED(result) || uReturn == 0) {
      return;
  }
 
  VARIANT vtProp;
  result = pclsObj->lpVtbl->Get(pclsObj, pfieldname, 0, &vtProp, 0, 0);
  if (FAILED(result)) {
    pclsObj->lpVtbl->Release(pclsObj);
    return;
  }
 
  wprintf(L"Value: %s\n", vtProp.bstrVal);
 
  VariantClear(&vtProp);
  pclsObj->lpVtbl->Release(pclsObj);
}

Example – Get processor model:

void GetProcessor(IWbemLocator *locator, IWbemServices *services) {
  IEnumWbemClassObject *pEnumerator = NULL;
  BSTR query    = SysAllocString(L"SELECT Name FROM Win32_Processor");
 
  pEnumerator = (IEnumWbemClassObject *) wmiQuery(services, query);
  if(pEnumerator == NULL) {
      SysFreeString(query);
      return;
  }
 
  wmiGetStringField(pEnumerator, L"Name");
 
  pEnumerator->lpVtbl->Release(pEnumerator);
  SysFreeString(query);
}

Usage:

int main(void) {
    IWbemLocator *locator = NULL;
    IWbemServices *services = NULL;
    BSTR resource;
 
    if(!wmiInitialize()) {
        CoUninitialize();
        return -1;
    }
 
    locator = (IWbemLocator *) wmiCreate();
    if(locator == NULL) {
      CoUninitialize();
      return -1;
     }
 
    resource = SysAllocString(L"ROOT\\cimv2");
 
    services = (IWbemServices *) wmiConnect(locator, resource);
    if(services == NULL) {
      locator->lpVtbl->Release(locator);
      CoUninitialize();
      SysFreeString(resource);
      return -1;
    }
 
    GetProcessor(locator, services);
 
    locator->lpVtbl->Release(locator);
    services->lpVtbl->Release(services);
    CoUninitialize();
    SysFreeString(resource);
 
    return EXIT_SUCCESS;
}
Categories: C Tags: , , ,
%d bloggers like this: