Is it possible to query to WMI on a Remote Computer for MicrosoftTPM namespace? [Remote WMI query to Win32_Tpm class failed with, HRESULT 0x80041013] - wmi

I am trying to query to Win32_Tpm class of WMI from remote machine.but It's failing with HRESULT 0x80041013 & Description: Provider load failure.
Is it possible to access MicrosoftTPM namespace remotely?
Following is the code,
hres = pSvc ->CreateInstanceEnum(
bstr_t(Class),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&Enumerator);
hres = CoSetProxyBlanket(
Enumerator, // Indicates the proxy to set
RPC_C_AUTHN_DEFAULT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_xxx
COLE_DEFAULT_PRINCIPAL, // Server principal name
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
mUserAcct, // client identity
EOAC_NONE // proxy capabilities
);
hres = Enumerator->Next(WBEM_INFINITE, 1, &TPMClass, &uReturn);
//Here I am failing with hres = 0x80041013 and uReturn = 0, value of TPMClass is NULL after execution of above statement also.
Bellow is the detailed code,
IEnumWbemClassObject* Enumerator;
IWbemClassObject* TPMClass = NULL;
ULONG uReturn = 0;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IDENTIFY, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"\\\\REMOTE\\root\\cimv2\\Security\\MicrosoftTpm"),
_bstr_t(useToken ? NULL : pszName), // User name
_bstr_t(useToken ? NULL : pszPwd), // User password
NULL, // Locale
NULL, // Security flags
_bstr_t(useNTLM ? NULL : pszAuthority),// Authority
NULL, // Context object
&pSvc // IWbemServices proxy
);
COAUTHIDENTITY *userAcct = NULL;
COAUTHIDENTITY authIdent;
//Created COAUTHIDENTITY with internal function
userAcct = &authIdent;
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_DEFAULT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_xxx
COLE_DEFAULT_PRINCIPAL, // Server principal name
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
userAcct, // client identity
EOAC_NONE // proxy capabilities
);
hres = pSvc ->CreateInstanceEnum(
bstr_t(Class),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&Enumerator);
hres = CoSetProxyBlanket(
Enumerator, // Indicates the proxy to set
RPC_C_AUTHN_DEFAULT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_xxx
COLE_DEFAULT_PRINCIPAL, // Server principal name
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
mUserAcct, // client identity
EOAC_NONE // proxy capabilities
);
//Here I am failing , value of TPMClass is NULL after execution of following statement also.
hres = Enumerator->Next(WBEM_INFINITE, 1, &TPMClass, &uReturn);

Above class name is L"Win32_Tpm" in function CreateInstanceEnum().
I am able to get instance while accessing from local machine but it's failing while accessing from remote machine.
Note: I have assigned proper permissions to user on machine for remote.

Related

Change Brightness using WMI

I have tried this Windows example Getting WMI Data from a Remote Computer and this other Calling a Provider Method, and both work correctly in my computer. However I have tried to use WMI to change the brightness and I am getting an error on step 6, in this part:
//Get the Next Object from the collection
hres = pEnum->Next(WBEM_INFINITE, //Timeout
1, //No of objects requested
&pObj, //Returned Object
&ulReturned /*No of object returned*/);
pEnum is a negative value.
IMPORTANT: While I was writing this question, I tried with different computers and I get errors in all of them, except when I use a laptop. Therefore, how can I change the brightness of a monitor?
I also realize that if I go to wbemtest.exe, in all my computers the class WmiMonitorBrightnessMethods and the method WmiSetBrightness exist, but only in the laptop there is an instance of it. In fact, in the computers when I click on view objects of the class I get this message (see image)
This is my code:
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
int main(int iArgCnt, char ** argv)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM negotiates service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object. "
<< "Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: ---------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the local root\wminamespace
// and obtain pointer pSvc to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\WMI"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels for the proxy ------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Call WmiSetBrightness method -----------------------------
// set up to call the Win32_Process::Create method
BSTR ClassName = SysAllocString(L"WmiMonitorBrightnessMethods");
BSTR MethodName = SysAllocString(L"WmiSetBrightness");
BSTR bstrQuery = SysAllocString(L"Select * from WmiMonitorBrightnessMethods");
IEnumWbemClassObject *pEnum = NULL;
hres = pSvc->ExecQuery(_bstr_t(L"WQL"), //Query Language
bstrQuery, //Query to Execute
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, //Make a semi-synchronous call
NULL, //Context
&pEnum /*Enumeration Interface*/);
hres = WBEM_S_NO_ERROR;
ULONG ulReturned;
IWbemClassObject *pObj;
DWORD retVal = 0;
//Get the Next Object from the collection
hres = pEnum->Next(WBEM_INFINITE, //Timeout
1, //No of objects requested
&pObj, //Returned Object
&ulReturned /*No of object returned*/);
IWbemClassObject* pClass = NULL;
hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
IWbemClassObject* pInParamsDefinition = NULL;
hres = pClass->GetMethod(MethodName, 0, &pInParamsDefinition, NULL);
IWbemClassObject* pClassInstance = NULL;
hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
VARIANT var1;
VariantInit(&var1);
BSTR ArgName0 = SysAllocString(L"Timeout");
V_VT(&var1) = VT_BSTR;
V_BSTR(&var1) = SysAllocString(L"0");
hres = pClassInstance->Put(ArgName0,
0,
&var1,
CIM_UINT32); //CIM_UINT64
VariantClear(&var1);
VARIANT var;
VariantInit(&var);
BSTR ArgName1 = SysAllocString(L"Brightness");
V_VT(&var2) = VT_BSTR;
V_BSTR(&var2) = SysAllocString(L"80"); //Brightness value
hres = pClassInstance->Put(ArgName1,
0,
&var2,
CIM_UINT8);
VariantClear(&var2);
// Call the method
VARIANT pathVariable;
VariantInit(&pathVariable);
hres = pSvc->ExecMethod(pathVariable.bstrVal,
MethodName,
0,
NULL,
pClassInstance,
NULL,
NULL);
VariantClear(&pathVariable);
return 0;
}
As Amit Shakya has stated. changing the brightness throught WMI is only possible in systems that can dynamically set the brightness (laptops and some some all-in-one devices).
However, there is a Microsoft function that allows you to change the brightness of an external monitor, SetMonitorBrightness.
See Microsoft library
I attach a simple example of how to do it:
// Includes
#include "PhysicalMonitorEnumerationAPI.h"
#include "HighLevelMonitorConfigurationAPI.h"
(...)
// Prepare variables
HMONITOR hMonitor = NULL;
HMONITOR hMonitorTest = NULL;
DWORD cPhysicalMonitors;
LPPHYSICAL_MONITOR pPhysicalMonitors = NULL;
// Get the screen
HWND hWnd = GetDesktopWindow();
hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY);
_BOOL success = GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &cPhysicalMonitors);
if(success)
{
pPhysicalMonitors = (LPPHYSICAL_MONITOR)malloc(cPhysicalMonitors* sizeof(PHYSICAL_MONITOR));
if(pPhysicalMonitors != NULL)
{
success = GetPhysicalMonitorsFromHMONITOR(hMonitor,cPhysicalMonitors, pPhysicalMonitors);
HANDLE hPhysicalMonitor = pPhysicalMonitors[0].hPhysicalMonitor;
// Set brightness to 50%
DWORD dwNewBrightness = 50;
success = SetMonitorBrightness(hPhysicalMonitor, dwNewBrightness);
// Free resources
free(pPhysicalMonitors);
}
}
It is mostly because your PC does not support brightness controls via a software. For example in laptops there are hotkeys that can be used to control the brightness, if that exists that you will get an instance and make use of it via WMI.
To be sure, you can run below mentioned command in powershell. If it returns Not supported then you can not use WMI for these controls.
Get-CimInstance -Namespace root/WMI -ClassName WmiMonitorBrightnessMethods
Note : Hotkeys work via another softwares like Mobility Center etc.

WMI query returns no result C++

I'm connecting to Windows server 2012 and 2008 R2 from a Windows 7 machines.
My code is working in some computers but in some computers when I run my app query always return NULL.
When I execute Next method on IEnumWbemClassObject object it returns error code x80041003.
I'm trying to query Win32_Process class
My Code:
hres = CoInitializeEx( 0, COINIT_MULTITHREADED );
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_CONNECT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
0 // Reserved
);
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
hres = pLoc->ConnectServer( ServerName,Username, Password, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pSvc);
COAUTHIDENTITY AuthId;
memset(&AuthId, 0, sizeof(COAUTHIDENTITY));
//Initialized AuthId
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
&AuthId, // client identity
EOAC_NONE
);
Query.Format( _T( "SELECT * FROM Win32_Process WHERE Name like '%s.exe'" ), App.Name );
IEnumWbemClassObject* pEnumerator = NULL;
hr = App.Server.pSvc->ExecQuery(
L"WQL",
Query.AllocSysString(),
WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator
);
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

Get asset tag and serial from bios using C++

I am wanting to learn how to get asset tag and serial number from the bios of a local machine using c++. I have been searching online for almost an hour now and all I have come up with so far is a few script written in vb.
I am working on a Windows 7 computer, but would like it to work with Windows 8 as well.
You can use WMI
An example function would be something like the following source which I put together to obtain the serial number for a PC and it seems to work quite nicely. There is a fall back to pull a serial number from the Windows Registry however just ignore that as it is for a specialized environment.
# pragma comment(lib, "wbemuuid.lib")
static SHORT CDeviceConfigCheckSerialNumber (TCHAR *tcsSerialNo)
{
HRESULT hres;
IWbemLocator *pLoc = NULL;
*tcsSerialNo = 0; // initialze return string to empty string
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (for example, Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
pLoc->Release();
return 2; // Program has failed.
}
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
return 3; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
// bstr_t("SELECT * FROM Win32_SystemEnclosure"),
// bstr_t("SELECT * FROM Win32_BaseBoard"),
bstr_t("SELECT * FROM Win32_BIOS"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
return 4; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
IWbemClassObject *pclsObj;
ULONG uReturn = 0;
SHORT sRetStatus = -100;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
if (!FAILED(hres)) {
switch (vtProp.vt) {
case VT_BSTR:
_tcscpy (tcsSerialNo, vtProp.bstrVal);
sRetStatus = 0;
break;
}
}
VariantClear(&vtProp);
pclsObj->Release();
}
pEnumerator->Release();
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
// if the search for a serial number in the BIOS did not provide
// something then lets see if the NCR Retail Systems Manager has
// put a serial number into the Windows Registry.
if (sRetStatus != 0) {
ULONG ulCount = 0;
TCHAR lpszValue[256] = {0};
ScfGetRsmValue (L"SerialNumber", &ulCount, lpszValue);
if (ulCount > 0) {
_tcscpy (tcsSerialNo, lpszValue);
sRetStatus = 0;
}
}
return sRetStatus;
}

Get all processes for Current User

I need to get all processes for current user. Currently I have a function implemented using WMI that gets all active processes by All Users. I need to somehow get all processes by Current User.
If you go to Task Manager in Windows, Details tab, you will see all processes by All Users. But say you are in Visual Studio and you go to Debug/Attach To Process, this shows all processes by Current User. That's the list that I need.
Here is my solution of All Processes by All Users:
CComPtr<IEnumWbemClassObject> pEnumerator;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_Process"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
Either a WMI or Win32 solution will be good enough. Thank you!!
OK, there is now short way. But here is the working solution if anyone is interested:
std::wstring GetProcessUserName(DWORD dwProcessId)
{
HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
if (processHandle != NULL)
{
HANDLE tokenHandle;
if (OpenProcessToken(processHandle, TOKEN_READ, &tokenHandle))
{
TOKEN_USER tokenUser;
ZeroMemory(&tokenUser, sizeof(TOKEN_USER));
DWORD tokenUserLength = 0;
PTOKEN_USER pTokenUser;
GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS::TokenUser, NULL,
0, &tokenUserLength);
pTokenUser = (PTOKEN_USER) new BYTE[tokenUserLength];
if (GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS::TokenUser, pTokenUser, tokenUserLength, &tokenUserLength))
{
TCHAR szUserName[_MAX_PATH];
DWORD dwUserNameLength = _MAX_PATH;
TCHAR szDomainName[_MAX_PATH];
DWORD dwDomainNameLength = _MAX_PATH;
SID_NAME_USE sidNameUse;
LookupAccountSid(NULL, pTokenUser->User.Sid, szUserName, &dwUserNameLength, szDomainName, &dwDomainNameLength, &sidNameUse);
delete pTokenUser;
return std::wstring(szUserName);
}
}
}
return std::wstring();
}
std::unordered_map<std::wstring, std::vector<DWORD>> GetAllRunningProcessesForCurrentUser()
{
std::unordered_map<std::wstring, std::vector<DWORD>> processHash;
HRESULT hres;
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
return processHash;
}
do {
// Obtain the initial locator to WMI -------------------------
CComPtr<IWbemLocator> pLoc;
hres = pLoc.CoCreateInstance(CLSID_WbemLocator);
if (FAILED(hres))
{
break;
}
// Connect to WMI through the IWbemLocator::ConnectServer method
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
CComPtr<IWbemServices> pSvc;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (for example, Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
break;
}
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
break;
}
// Use the IWbemServices pointer to make requests of WMI ----
CComPtr<IEnumWbemClassObject> pEnumerator;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_Process"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
break;
}
// Get the data from the query in step 6 -------------------
CComPtr<IWbemClassObject> pclsObj;
while (pEnumerator)
{
ULONG uReturn = 0;
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn)
{
break;
}
VARIANT vtProp;
VARIANT vtProp2;
hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
hr = pclsObj->Get(L"ProcessId", 0, &vtProp2, NULL, NULL);
auto userName = GetProcessUserName(vtProp2.intVal);
TCHAR szActiveUserName[_MAX_PATH];
DWORD dwActiveUserNameLength = _MAX_PATH;
GetUserName(szActiveUserName, &dwActiveUserNameLength);
if (_tcscmp(userName.c_str(), szActiveUserName) == 0)
{
processHash[vtProp.bstrVal].push_back(vtProp2.intVal);
}
VariantClear(&vtProp2);
VariantClear(&vtProp);
pclsObj.Release();
}
} while (false);
CoUninitialize();
return processHash;
}

Using WMI in C++ to obtain the InterfaceIndex of an adapter

I've written some code to initialise COM and enumerate the network adapters attached to the PC by querying the Win32_NetworkAdapter class using WMI. The reason I need to use WMI is that the adapter I need to enumerate is disabled at the time but I still need to find out its InterfaceIndex, and using GetInterfaceInfo only detects enabled adapters. It all compiles and runs but at the line:
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObj, &ulReturnVal);
which is meant to retrieve the very first adapter, it returns no devices and a garbage HRESULT. I used the example on this page as my guidance.
CoInitialize(NULL); // Initialize COM
HRESULT hr = NULL;
hr = CoInitializeSecurity(
NULL, // security descriptor
-1, // use this simple setting
NULL, // use this simple setting
NULL, // reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // authentication level
RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level
NULL, // use this simple setting
EOAC_NONE, // no special capabilities
NULL); // reserved
if (FAILED(hr))
{
CoUninitialize();
return -1;
}
IWbemLocator *pLoc = 0;
hr = CoCreateInstance(CLSID_WbemLocator, 0,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hr))
{
CoUninitialize();
return -1; // Program has failed.
}
IWbemServices *pSvc = 0;
// Connect to the root\default namespace with the current user.
hr = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
if (FAILED(hr))
{
pLoc->Release();
CoUninitialize();
return -1; // Program has failed.
}
hr = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (FAILED(hr))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -1; // Program has failed.
}
IEnumWbemClassObject* pEnumerator = NULL;
hr = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_NetworkAdapter"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
if (FAILED(hr))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -1;
}
IWbemClassObject *pClassObj;
ULONG ulReturnVal;
while ( pEnumerator )
{
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObj, &ulReturnVal);
// code would go here to obtain the adapter properties.
pClassObj->Release();
}
return -1;
The correction/solution was to use the RPC_C_IMP_LEVEL_DELEGATE parameter with CoInitializeSecurity and CoSetProxyBlanket rather than RPC_C_IMP_LEVEL_IMPERSONATE.